Prototype Pollution (2020)
portswigger.net
portswigger.net
If an attacker can perform "prototype pollution", aren't they already injecting arbitrary JavaScript into the page? If they already have script injection, why would they choose "prototype pollution" over anything else they could do with arbitrary code?
There was a write up about the kibana rce that really shows it's a problem:
https://research.securitum.com/prototype-pollution-rce-kiban...
As another commenter noted, if one can directly inject literal JS code that writes to __proto__, you've already got RCE.
The case where prototype pollution happens without arbitrary RCE looks like:
- User input can set arbitrary fields of an object and its properties, allowing the user to add or alter a field on a `__proto__` that references a widely-shared prototype;
- The existence or value of that field non-locally affects other code which assumes that the prototype is not under user control.
AFAIK An arbitraty JavaScript cannot access values declared out of its scope. Prototype pollution add a capability of an attacker introduce a hook-like mechanism to intercept values passed via an object's method.
There are other problems that naturally fall out of the fact that by default all objects, including those from JSON.parse, inherit the Object prototype though. For example -
- If you store user membership or permission as an object with some user controlled identifier (eg. a username) as key, then check if a user is permitted at all with `username in permissions`, a user can name themselves hasOwnProperty to bypass the check since it is part of the Object prototype
- If you deserialize some JSON then try to check membership with `o.hasOwnProperty(someKey)`, a malicious user can pass in JSON with hasOwnProperty as key. This will crash since hasOwnProperty is no longer a function on the object.
These are not necessarily common, but it’s annoying how easy it is for these to slip through. The object prototype in general is just a massive footgun
-innocuous looking code merges user supplied input from a json object ("we just use this to render a view or write it to an object store")
-attacker throws in a __proto__ property which means every object in the _entire_ node runtime has that value for that key until it's overwritten in script
-random templating engine has a config option that would _never_ be controlled by an attacker, right?
-oops, RCE!
var { x, y } = JSON.parse(input);
board[x][y] = true;
// ...
if (user.admin) ...
If the attacker puts: {x: "__proto__", y: "admin"}
Then board["__proto__"] might be `object` and then object["admin"] = trueNow `<any object>.admin` is true !
It’s not monkeypatching, its a class of vilnerabilities that allow an attacker to do the monkeypatching, and to do so to the root Object.
Key things about JavaScript that differ from Ruby/Python relevant to it are:
(1) Prototype-based inheritance, (2) Syntax and common idioms thar support and encourage use of plain objects where Ruby/Python would use string-keyed Hash/dict instances (equivalent to JS Map), including when objects are constructed from untrusted JSON (which, again, Ruby/Python would serialize to Hash/dict, not exposing member properties ot manipulation).
What would be reading a Hash/dict keyvalue pair from an untrusted source in Ruby or Python (not, generally, risky) can easily be, in JavaScript, opening a gateway to potentiallt inject data members to the shared prototype of all objects.