Skip to main content

prototype-pollution

Hunt JavaScript prototype pollution (CWE-1321) — the 2023-2026 meta-vulnerability that chains into RCE, auth bypass, and SSRF on most Node.js stacks.

Ir a la instalación

Datos de origen

Repositorio
BitterSecurity/Decepticon
Última actividad en el origen
2 de junio de 2026 a las 17:42
Idioma detectado de SKILL.md
inglés
Estrellas
5565
Forks
1053

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
prototype-pollution
description
Hunt JavaScript prototype pollution (CWE-1321) — the 2023-2026 meta-vulnerability that chains into RCE, auth bypass, and SSRF on most Node.js stacks.
metadata
{"subdomain":"web-exploitation","when_to_use":"javascript prototype pollution cwe-1321 node js __proto__ constructor chain rce auth bypass ssrf gadget"}
# Prototype Pollution Playbook Prototype pollution is the JavaScript equivalent of a universal gadget: plant a property on `Object.prototype` and it appears on every object in the runtime. Worthless in isolation, deadly in chain (`__proto__.isAdmin = true` → auth bypass; `__proto__.shell = "/bin/bash"` → RCE via `spawn`). ## 1. Sinks — the libraries that still introduce sinks Keep a running list per engagement. These continue to ship sinks in 2026: - **Deep-merge:** `lodash.merge`, `deepmerge` (pre-fix), `merge-deep`, `deepExtend`, `hoek.merge`, `mixme` - **Deep-clone:** `lodash.defaultsDeep`, `lodash.zipObjectDeep`, `set-value` (pre-3.0.3) - **URL-to-obj:** `qs`, `express-fileupload`, `jquery.extend(true, ...)` - **Config loaders:** `node-config` recursive merge, `dotenv-extended`, `rc` - **Template engines:** Handlebars helpers fed from untrusted ctx ```bash # Every JS/TS project: sweep known-bad versions jq '.dependencies,.devDependencies | to_entries[] | select(.key | test("merge|lodash|set-value|dot-object|dot-prop|node-pg"))' /workspace/src/package.json npm ls lodash set-value dot-prop 2>/dev/null | grep -E '[0-9]' ``` ## 2. Sources Any user input deserialized into a nested object: - JSON body parsers (`body-parser`, `express.json`) - Query string parsers (`qs` with default config parses `a[b][__proto__][c]=1`) - YAML uploads - Form-data / multipart ## 3. Audit workflow 1. Find every deep merge call site. 2. Trace each one backwards — is the right-hand object user-controlled? 3. If yes: check the merge function's prototype-pollution fix version. 4. Even if the merge is fixed, check whether a *copy* (lodash.set, dot-path-value, jsonpath.set) creates a pollution path. ## 4. Exploitation gadgets Poisoning `Object.prototype` doesn't do anything by itself — you need a gadget that reads a property that didn't exist before. Classic gadgets: - **`child_process.spawn(cmd, args, opts)`** — opts has a `shell` option. Poison `__proto__.shell = "/bin/bash"` then any subsequent spawn call executes through bash and interprets args as shell strings. - **Express middleware** — most middlewares check `options.someFlag` with `if (opts.someFlag)`. Poisoning that flag flips security defaults. - **Templating** — Handlebars and EJS read `helpers` and `partials` from the context object; pollution adds helpers that execute code. - **`lodash.template`** — if the template source is built from `_.template(tpl, ctx)` you can inject via polluted `escape`/`evaluate` keys. - **`mongoose`** — polluting `Schema.Types` causes subsequent schema definitions to use attacker-controlled types. ## 5. PoC template ```bash # Classic lodash.merge RCE via child_process.spawn curl -X POST https://target.com/api/settings \ -H 'Content-Type: application/json' \ -d '{"__proto__": {"shell": "/bin/bash", "env": {"PATH": "/tmp:/usr/bin"}}}' # Second request triggers the gadget curl https://target.com/api/render-pdf # → any subsequent child_process.spawn call now runs through /bin/bash ``` ## 6. Success signals for `validate_finding` - Server error with stack trace referencing `Object.prototype` - Output of injected command reflected in next response - Admin-only endpoint now returns 200 after poisoning `__proto__.isAdmin` Negative control: same payload with `proto` (no leading underscores) — should have no effect. If it does, the endpoint is treating that key specially and the finding is unrelated. ## 7. Default CVSS | Variant | Vector | Score | |---------------------------------------|----------------------------------------------|-------| | DoS (crash Node process) | AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H | 7.5 | | Auth bypass via `isAdmin` pollution | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N | 9.1 | | RCE via spawn gadget | AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H | 10.0 | ## 8. Chain promotion Prototype pollution is almost always the *first* hop of a chain. After validation, add an `enables` edge from the pollution vuln to: - the spawn / template gadget vuln (RCE chain) - the auth check vuln (privilege escalation chain) - the SSRF vuln if the downstream request lib has an options pollution surface Chain weight 0.4 — pollution is cheap once the merge sink is known.
Ver en GitHub