XSS rompiendo el atributo JSON.parse y href

4

Tengo un caso bastante complicado en el que intento realizar un ataque XSS almacenado al cargar un archivo jpg con un nombre de archivo malicioso.

El espacio en blanco se está filtrando, pero parece comillas simples y dobles junto con < > no se filtran Además, parece que está prohibida la barra inclinada / y la barra invertida \

La entrada controlada por el usuario es un nombre de archivo; este nombre de archivo se pasa primero a un script js que crea datos JSON de la siguiente manera (el nombre de archivo controlado por el usuario se representa como INJECT_HERE).

<script>
var foo = JSON.parse('{"x":1,"id":"2","myarr":[{"x1":"1"}],"x2":[{"id1":3,"id2":"15","name":"INJECT_HERE","path":"\/uploads\/pics\/1\/INJECT_HERE","b":"1"}]}')
</script>

Luego, la variable anterior se usa para pasar la entrada suministrada por el usuario a un elemento HTML. El nombre de archivo (a través de foo.myarr.x2.name) se pasa a un atributo href (con vue-js y v-bind) y el resultado html se ve así:

<div href="https://localhost/INJECT_HERE" class="foobar"></div>

¿Cómo puedo salir de ambos contextos al mismo tiempo para realizar un XSS almacenado? ¿Es factible o intento algo que no se puede hacer?

    
pregunta XII 31.05.2018 - 13:13
fuente

3 respuestas

4

No puedes hacerlo. Vue usa el DOM para configurar el atributo href, por lo que no está codificado de forma rígida desde el servidor de una manera que pueda engañar al analizador de HTML. Es simplemente imposible establecer un atributo con el DOM de una manera que "rompa" el atributo, o inicie un nuevo atributo como si tuviera una fuente de HTML sin formato; todos los caracteres no válidos se escaparán lógicamente, incluso si los valores sin procesar en las herramientas de desarrollo hacen que parezca que el ataque debería funcionar.

Si realizó alguna de las plantillas en el servidor (quizás en un intento de pre-renderización), entonces es un problema, pero tal como está, está seguro.

tenga en cuenta que data: y javascript: urls podrían seguir siendo un problema, pero probablemente ya tenga protección de esa configuración, dado su aparente nivel de experiencia.

EDITAR: respondiendo a un comentario

considere una página simple que usa el DOM para inyectar contenido:

<html> 
   <a id=a href="#">xss</a>
   <script>a.href='"><script>alert(123)<\/script>';</script>
</html>

Si observa la vista de inspección de las herramientas del desarrollador, es posible que vea algo aterrador como este:

<a id="a" href=""><script>alert(123)</script>">xss</a>

Parece que hay una etiqueta <script> dentro de la etiqueta <a> , y de hecho, si la copia en una página en blanco y la ve, se alertará. Sin embargo, no es realmente un problema porque las herramientas para desarrolladores están jugando un truco visual. El contenido real del elemento cuando se serializa es más parecido a esto:

<a id="a" href="&quot;&gt;&lt;script&gt;alert(123)&lt;/script&gt;">xss</a>

Eso es lo que quise decir con el DOM que escapa automáticamente cualquier contenido arbitrario; Mientras use el DOM para establecer un atributo, no hay manera de "eliminar" el atributo con ningún contenido. Eso no significa que un atributo con efecto secundario, como onmouseover no pueda hacerte mal, solo que no puedes establecer onmouseover ajustando un href .

Ese protocolo% ur_de% y data: url se discute bien en otra parte, pero tenga en cuenta que es una forma de vincular documentos de contenido arbitrario ( javascript: ) y código JS ( data: ).

Por ejemplo, ambas alertas "666" (marca de la bestia) cuando se hace clic:

Javascript: jacascript:

Datos: <a href=javascript:alert(666)>xss</a>

Ambos se pueden usar en lugar de una URL de http (s), así que asegúrate de protegerte de eso, especialmente <a href=data:text/html,%3Cscript%3Ealert%28666%29%3C/script%3E>xss</a> porque no necesita una barra para hacer que el código sea ejecutable.

    
respondido por el dandavis 31.05.2018 - 21:54
fuente
0

Si toda la línea JSON.parse se genera en el servidor (en lugar de, por ejemplo, llamar a JSON.parse en una variable que contiene el resultado de un XHR), se permiten comillas simples y dobles (más ( ) y al menos uno de + - ; ) esto es fácil. Tu contenido ya se está evaluando dentro de un bloque de secuencia de comandos, ¿por qué te preocupas por lo que sucede después de cuando finaliza la secuencia de comandos? ¡Ya deberías haber ejecutado tu carga útil para entonces!

Un nombre de archivo de ejemplo, utilizando + para la concatenación de cadenas: badfile"'+alert('xss')+' Esto generará una cadena JSON sin sentido completamente (e inválida), pero no te importa; tu código se ejecuta (dos veces) cuando el motor JS intenta concatenar las cadenas, ¡antes de que incluso se llame a JSON.parse !

<script>
var foo = JSON.parse('{"x":1,"id":"2","myarr":[{"x1":"1"}],"x2":[{"id1":3,"id2":"15","name":"badfile"'+alert('xss')+'","path":"\/uploads\/pics\/1\/badfile"'+alert('xss')+'","b":"1"}]}')
</script>
    
respondido por el CBHacking 31.05.2018 - 22:21
fuente
-1

Esto no parece posible en absoluto. Cuando se selecciona un archivo para cargar, solo permanece allí hasta que se procesa. Por lo tanto, para que JavaScript obtenga el nombre de archivo, primero debe seleccionar la entrada y obtener el valor del atributo o textContent , que se devuelve como string . Por lo tanto, no puede salir de JSON.parse .

Y, como se indicó en el comentario, está configurando el atributo href añadiéndolo a la URL base. Por lo tanto, no puedes romper el atributo href. Solo puede manipular el valor del atributo href, pero tampoco puede cambiar base_url .

Por lo tanto, en este caso particular, no es posible activar XSS de ninguna manera.

    
respondido por el 1lastBr3ath 31.05.2018 - 14:53
fuente

Lea otras preguntas en las etiquetas