diff --git a/src/pentesting-web/deserialization/nodejs-proto-prototype-pollution/prototype-pollution-to-rce.md b/src/pentesting-web/deserialization/nodejs-proto-prototype-pollution/prototype-pollution-to-rce.md index 9e7ae87852c..f5b117d6c55 100644 --- a/src/pentesting-web/deserialization/nodejs-proto-prototype-pollution/prototype-pollution-to-rce.md +++ b/src/pentesting-web/deserialization/nodejs-proto-prototype-pollution/prototype-pollution-to-rce.md @@ -67,6 +67,37 @@ for (const key of envKeys) { Check that code you can see it's possible en **poison `envPairs`** just by **polluting** the **attribute `.env`.** +### Dynamic-key grouping (`??=`) to Git SSH RCE + +When auditing object-building code, look beyond recursive merge functions for grouping patterns that use untrusted strings as keys on ordinary objects. If both keys and the value are attacker-controlled, the following pattern is a direct pollution source:[[9]](#references)[[10]](#references) + +```javascript +const grouped = {} + +for (const { groupKey, fieldKey, value } of userFields) { + grouped[groupKey] ??= {} + grouped[groupKey][fieldKey] = value +} +``` + +With `groupKey = "__proto__"`, the first lookup invokes the inherited `__proto__` getter and returns `Object.prototype`. Because that value is not nullish, `??=` does not create an own property; the next statement becomes `Object.prototype[fieldKey] = value`. The mutation remains even if later validation, an API call, or the surrounding workflow step fails, so inspect side effects that occur before error-prone operations.[[9]](#references) + +A useful external-process gadget is **Git over SSH**. In the demonstrated n8n chain, polluting `GIT_SSH_COMMAND` was inherited by a plain environment object created through `simple-git`, propagated to the spawned Git process, and interpreted by Git through the shell when cloning an SSH-style remote. The exact child-process/library path is version-dependent: exploitation requires the inherited enumerable property to be copied into the child environment and no own property to shadow it.[[9]](#references)[[11]](#references) + +```json +{ + "groupKey": "__proto__", + "fieldKey": "GIT_SSH_COMMAND", + "value": "sh -c 'id > /tmp/pp-git' --" +} +``` + +Therefore, search for a three-stage chain: **dynamic-key pollution → plain environment map → Git operation using an SSH remote**. The pollution-producing operation does not need to finish successfully if the prototype write happens first.[[9]](#references) + +This source can also cause process-wide denial of service without an RCE gadget. A later `for...in` loop enumerates inherited enumerable keys; in the documented case, TypeORM treated the polluted name as an entity field and repeatedly threw `EntityPropertyNotFoundError` until the Node.js process was restarted.[[9]](#references) + +For dictionary-like data, use `Object.create(null)`, validate every path component against `__proto__`, `constructor`, and `prototype`, and iterate only own keys (`Object.keys()` or an `Object.hasOwn()` check). Build child environments from explicit own properties rather than inheriting from application objects.[[9]](#references)[[10]](#references) + ### **Poisoning `__proto__`** > [!WARNING] @@ -780,5 +811,8 @@ Additional gadget collections and CTF examples can help identify application-spe - [6] [Exploiting prototype pollution in Node without the filesystem](https://portswigger.net/research/exploiting-prototype-pollution-in-node-without-the-filesystem) - [7] [Uncovering a Prototype Pollution Regression in Node.js (archived)](https://web.archive.org/web/20250130155632id_/https://dzone.com/articles/uncovering-prototype-pollution-regression) - [8] [Summary of CTF Web Frontend and JS Challenges in 2022](https://blog.huli.tw/2022/12/26/en/ctf-2022-web-js-summary/) +- [9] [n8n GSuiteAdmin Prototype Pollution to Remote Code Execution](https://simonkoeck.com/writeups/n8n-gsuiteadmin-prototype-pollution-rce) +- [10] [Prototype Pollution in GSuiteAdmin node parameters leads to RCE - n8n Security Advisory](https://github.com/n8n-io/n8n/security/advisories/GHSA-mxrg-77hm-89hv) +- [11] [Git environment variables - `GIT_SSH_COMMAND`](https://git-scm.com/docs/git#Documentation/git.txt-codeGITSSHCOMMANDcode) {{#include ../../../banners/hacktricks-training.md}}