Entrada

Client-side prototype pollution via browser APIs

Laboratorio de Portswigger sobre Prototype Pollution

Client-side prototype pollution via browser APIs

Certificaciones

  • eWPT
  • eWPTXv2
  • OSWE
  • BSCP

Descripción

En este laboratorio es posible explotar un DOM XSS a través de un prototype pollution en el lado del cliente. Los desarrolladores del sitio web detectaron un posible gadget e intentaron corregirlo. Sin embargo, es posible eludir las medidas que han implementado


Resolución

Al acceder a la web vemos esto

Lo primero que vamos a hacer es intentar inyectar una propiedad arbitraria a través de la cadena de consulta

1
https://0a0f00b803dc1fb080bbf4d600360044.web-security-academy.net/?__proto__[foo]=bar

Lo siguiente que vamos a hacer es abrirnos la consola del navegador e inspeccionar el Object.prototype para ver si lo hemos contaminado correctamente con la propiedad arbitraria. Como podemos ver, hemos conseguido contaminar la propiedad

Al inspeccionar los archivos js, este llama la atención ya que se ve que los desarrolladores han intentado bloquear posibles gadgets utilizando el método Object.defineProperty(). Lo que están haciendo los desarrolladores es establecer una propiedad directamente en el objeto afectado como no configurable y no escribible, esto lo hacen mediante un tercer argumento denominado descriptor ({configurable: false, writable: false}). Tiene este nombre porque es un objeto que le dice a JavaScript cómo debe crearse o configurarse una propiedad

En este caso pp-finder no nos reporta este gadget debido a que la propiedad transport_url ya está definida como false por lo que no la detecta como vulnerable. En la sección parameters https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties#parameters podemos ver las claves que se pueden usar en el descriptor. Estos son los valores que se les pueden asignar y los valores por defecto

1
2
3
4
5
6
configurable: true/false (default)
enumerable: true/false (default)
value: undefined (default)
writable true/false (default)
get: undefined (default)
set: undefined (default)

Los valores por defecto para las claves value, get y set no están definidos, esto significa que tenemos que ser nosotros los que les asignemos un valor

En este laboratorio la feature que se supone que sirve para securizar es la que precisamente ha generado la vulnerabilidad. Podemos aprovechar que el value no está definido en el descriptor. Al no tener el value definido si nosotros contaminamos el value del prototipo, el descriptor lo heredará y puede que podamos derivar el prototype pollution en alguna vulnerabilidad. Para envenenar el value del prototipo lo hacemos así

1
https://0a0f00b803dc1fb080bbf4d600360044.web-security-academy.net/?__proto__[value]=test

Si accedemos a esa URL y abrimos la consola, veremos un error

Si hacemos click sobre el enlace nos llevará a esta parte del código. El error se debe a que script.src espera recibir una URLpodríamos proporcionar un archivo javascript malicioso mediante una url https://attacker.com/exploit.js o embeber los datos usando una data URL data:text/javascript,alert(1)

Si accedemos a esta URL vemos que nos salta un alert, lo que quiere decir que el XSS ha funcionado

1
https://0a0f00b803dc1fb080bbf4d600360044.web-security-academy.net/?__proto__[value]=data:text/javascript,alert(1)

En este caso, no podemos contaminar la propiedad transport_url de esta forma debido a que ya está definida como false y las propiedades propias tienen prioridad sobre las del prototipo. Básicamente, esto quiere decir que el laboratorio ya era seguro antes de introducir la sanitización y que debido a ella hemos podido llevar a cabo este XSS

1
https://0a0f00b803dc1fb080bbf4d600360044.web-security-academy.net/?__proto__[transport_url]=data:text/javascript,alert(1)

Esta entrada está licenciada bajo CC BY 4.0 por el autor.