Lista blanca de elementos DOM para derrotar a XSS

13

Como sabemos, los desarrolladores son responsables de escapar / validar correctamente los datos proporcionados por el usuario antes de procesarlos o almacenarlos. Sin embargo, debemos estar de acuerdo en que es relativamente fácil olvidar una entrada única entre cientos y, finalmente, hacer que su aplicación web sea explotada por un XSS. ¿O no has conocido a alguien que haya explotado su sitio por XSS?

Incluso Twitter y Orkut sufrieron recientemente de XSS. Y no estoy aquí para culpar a nadie.

Supongamos que su navegador admite elementos DOM de lista blanca. Estos elementos incluidos en la lista blanca son los únicos elementos que pueden ejecutar JavaScript. Rápidamente se da cuenta de que suena insano porque es imposible que su sitio web preferido funcione correctamente si tiene una lista blanca tan genérica. ¡Y estás en lo correcto!

Pero ahora suponga que los motores HTML y JavaScript admiten una sintaxis para permitirle incluir en la lista blanca los elementos de su propio sitio web. Por ejemplo:

<head>
    <script type="text/javascript">
        document.allowJavaScript(['div.item', '#list', 'a.navigate']);
    </script>
</head>

Esto no resuelve el problema de representar etiquetas <script> en medio de un árbol DOM, pero supongo que es mucho más fácil de resolver.

Además de mi punto anterior, ¿qué tipo de problemas o fallas ve en la solución descrita?

ACTUALIZACIÓN 1 : solo se debe confiar en el elemento head para invocar allowJavaScript .

ACTUALIZACIÓN 2 : con suerte, el siguiente fragmento de código explica un poco más mi idea:

<html>
<head>
    <style>
        div.outer { background-color: #aaa; width: 200px; height: 100px; }
        div.inner { background-color: #5ff; width: 100px; height: 50px; }
        ul { list-style-type: none; }
        li { background-color: #bbc; border: 1px solid #fff; float: left;
            width: 100px; height: 30px; }
    </style>
    <script type="text/javascript">
        document.allowJavaScript(['div.outer', '#list', 'a.test']);
        function register_events() {
            var list = document.querySelector('#list');
            list.onclick = function() { alert('list'); }
            var example1 = document.querySelector('#list li:nth-of-type(1)');
            example1.onclick = function() { alert('example 1'); }
        }
        window.onload = register_events;
    </script>
</head>
<body>
    <div class="outer" onclick="alert('outer');">
        <div class="inner" onmouseover="alert('inner');">
        </div>
    </div>
    <a class="navigate" href="#" onclick="alert('a');">click me</a>
    <ul id="list">
        <li>example 1</li>
        <li>example 2</li>
    </ul>
</body>
</html>

Esto NO debe permitir la ejecución de:

  1. alert('inner') - > permitimos div.outer , pero ninguno de sus elementos secundarios;
  2. alert('example 1') - > permitimos #list , pero ninguno de sus elementos secundarios;
  3. alert('a') - > permitimos a.test , no a.navigate ;
pregunta jweyrich 20.12.2010 - 12:13
fuente

7 respuestas

8

Restricción de la lista blanca a la etiqueta < head > El elemento no es útil porque < title > es parte de < head > y a menudo contiene datos proporcionados por el usuario. Por lo tanto, la definición de la lista blanca debe ser el primer elemento en < head > y solo se puede aceptar la primera llamada de la lista blanca.

El contenido de < li > ejemplo 1 < / li > No se confía en el ejemplo. Así que un atacante podría proporcionar esto:

<li>example 1><a class="test" onmouseover="alert(document.cookie)">hello</a></li>

Dado que a.test está en la lista blanca, el código se ejecuta. Sería posible aplicar la validación estricta del elemento dom. Pero es probable que desee permitir algunos elementos anidados, como < b > y < i & gt ;.

Parece mucho más fácil escapar correctamente del contenido no confiable basado en una lista blanca de etiquetas y atributos permitidos.

PS: ten en cuenta que existen otros nastiness como JavaScript incrustado en CSS y complementos como flash y java.

    
respondido por el Hendrik Brummermann 25.12.2010 - 13:40
fuente
14

JavaScript es un lenguaje del lado del cliente.

En mi opinión profesional, confiar en CUALQUIER implementación del lado del cliente para mayor seguridad es una pérdida de tiempo, y la implementación sería un desperdicio de recursos.

Su tiempo y su dinero se utilizarían mejor implementando la limpieza y validación adecuadas de la entrada en el entorno del lado del servidor.

    
respondido por el Purge 20.12.2010 - 20:03
fuente
10

¿Ha visto el trabajo de la Política de seguridad del contenido (resumen) de Mozilla?

Esta es la especificación .

  

La política de seguridad del contenido está destinada a ayudar a los diseñadores web o administradores de servidores a especificar cómo interactúa el contenido en sus sitios web. Ayuda a mitigar y detectar tipos de ataques como XSS e inyección de datos. CSP no pretende ser una línea de defensa principal , sino una de las muchas capas de seguridad que se pueden emplear para ayudar a proteger un sitio web.

Agregué énfasis a la cláusula que habla de no confiar demasiado en CSP.

Aquí hay algunos ejemplos de políticas:

  

Definiciones de políticas de muestra

     

Ejemplo 1: el sitio quiere que todo el contenido provenga de su propio dominio:

     

X-Content-Security-Policy: allow 'self'

     

Ejemplo 2: el sitio de subastas desea permitir imágenes desde cualquier lugar, contenido del complemento de una lista de proveedores de medios confiables (incluida una red de distribución de contenido) y secuencias de comandos solo de su servidor con JavaScript desinfectado:

     

X-Content-Security-Policy: allow 'self'; img-src *; \ object-src media1.com media2.com *.cdn.com; \ script-src trustedscripts.example.com

     

Ejemplo 3: los administradores del servidor desean denegar todas las secuencias de comandos de terceros para el sitio, y un grupo de proyecto determinado también desea no permitir medios de otros sitios (el encabezado proporcionado por los administradores de sistemas y el encabezado proporcionado por el grupo de proyecto están presentes):

     

X-Content-Security-Policy: allow *; script-src 'self' X-Content-Security-Policy: allow *; script-src 'self'; media-src 'self';

Parece que establecer la política de seguridad en los encabezados, aunque no es inexpugnable de atacar, hace que sea mucho más difícil que agregar la política de seguridad en línea en el DOM, donde podría mutarse.

Creo que tu idea / pregunta es buena para pensar, pero a medida que comienzas a hacer más y más completo, llega un punto en el que es demasiado caro hacerlo bien.

Tuve una idea similar cuando me di cuenta de lo molesto que es que todos los recursos deban ser servidos sobre SSL si se supone que la página está protegida por SSL. Mi primer pensamiento fue una idea sobre tener sumas de comprobación para cada recurso que se permite cargar en la página SSL (cargarlas en forma clara facilitaría el almacenamiento en caché de ellas). Por supuesto, hay una gran cantidad de problemas de seguridad para hacer eso y, finalmente, llegué a la conclusión de que cualquier ganancia de rendimiento se pierde rápidamente debido a problemas de seguridad y complejidad. Puedo ver cómo una lista blanca de DOM podría sufrir rápidamente de la misma manera.

Un último punto : si tiene conocimientos suficientes para incluir listas blancas en el navegador, ¿por qué no puede ejecutar la lista blanca con los datos que está publicando antes de enviarlos al navegador?

    
respondido por el rox0r 26.12.2010 - 06:53
fuente
8

Me parece una idea interesante, pero como estás preguntando sobre problemas con ella, responderé con algunos de los más obvios. No veo cómo esto puede aplicarse globalmente a la mayoría de los sitios, ya que la mayoría parece necesitar muchas de las peligrosas funciones de JavaScript disponibles para la funcionalidad principal. P.ej. onmouseover, href="javascript: alert (1)", etc. Para que esto sea útil como alternativa a Caja o JSReg , o JSandbox puede ser necesario aplicar a cualquier nivel en el DOM. Por ejemplo, si solo quisiera proteger mi contenido <div name="untrusted"> .

    
respondido por el Weber 20.12.2010 - 19:00
fuente
7

XSS generalmente funciona al inyectar Javascript en el cuerpo de la página de confianza. Si confía en su código que dice document.allowJavaScript(['div.outer', '#list', 'a.test']); , ¿cómo no confiaría en el código en la otra página del sitio que dice document.allowJavaScript(['div.evil', '#securityhole', 'a.exploit']); que se produce por una vulnerabilidad XSS? Mientras ambos residan en el mismo contexto de la misma página, que es la idea principal de XSS, no tiene forma de saber una de la otra.

Por supuesto, podría decir que tiene un contexto "privilegiado" (por ejemplo, dentro de <head> ) y un contexto "no privilegiado" dentro de <body> - y esto cubrirá parte de la vulnerabilidad, pero no toda. Ya que no tiene forma de garantizar que no habrá una vulnerabilidad de XSS que permita inyectar contenido en la parte "privilegiada" de la página. Por supuesto, eso sería menos frecuente, pero no resolvería todo el problema, aún así tendría que tener la validación en el servidor.

Además, introduciría un problema de mantenimiento: cada vez que el diseñador cambia algo en la página, tendrá que editar la lista de elementos privilegiados, al mismo tiempo que mantiene las partes "dinámicas" fuera de él. Esto puede resultar bastante difícil de hacer en proyectos reales, especialmente porque algunas páginas están compuestas de muchos widgets independientes generados por partes separadas de la aplicación, que pueden ser producidas por equipos completamente diferentes.

    
respondido por el StasM 25.12.2010 - 07:23
fuente
6

Teniendo en cuenta su interés, le invito a leer Ter Louw y Blueprint de Vernkatakrishnan, Interpolique de Dan Kaminsky y la Política de Seguridad de Contenido de Mozilla. También puedes ver auto-escape consciente del contexto , implementado en la plantilla de Google . Hay un montón de trabajos anteriores fantásticos: asegúrate de no reinventar la rueda.

El trabajo anterior en Blueprint y BEEP muestra que un riesgo de las políticas de seguridad en línea (como en su propuesta) es que una inyección XSS puede permitir que un atacante inyecte nuevas políticas. ¿Qué sucede si un atacante inyecta una nueva etiqueta HEAD y luego agrega una secuencia de comandos que invoca a allowJavaScript?

El trabajo anterior también muestra que detener la ejecución de Javascript malicioso no es suficiente para estar seguro. Si un atacante puede inyectar elementos arbitrarios en su página HTML, entonces el atacante podrá: (i) montar ataques de exfiltración de datos (por ejemplo, aprender tokens CSRF o secretos en la página), (ii) desfigurar su página, (iii) engañe a sus usuarios o robe las credenciales de autenticación (piense en agregar un formulario de inicio de sesión que le solicite su nombre de usuario y contraseña, pero cuando la acción del formulario se envíe al sitio del atacante), (iv) realice ataques CSRF (piense en una imagen en línea o elemento de formulario que carga automáticamente una URL en el sitio de la víctima, o que engaña al usuario para que lo haga), (v) ataques de clickjacking / strokejacking (algunos de los cuales no requieren Javascript).

El trabajo anterior también ha demostrado que los ataques son posibles, sin ejecutar ningún Javascript, atacando CSS. Vea el documento de Huang, Weinberg, Evans y Jackson en CCS 2010. Su esquema probablemente será vulnerable a esto, si existe algún punto de inyección en el documento, al menos en algunos navegadores.

Por último, si está incorporando elementos de la lista blanca en el DOM, ¿qué impide que un atacante que inyecte cosas en la página HTML abra y cierre etiquetas hasta que sus datos maliciosos se encuentren en el contexto del elemento de la lista blanca? Por ejemplo, si su política dice que la secuencia de comandos está permitida en la segunda etiqueta P debajo de la primera DIV debajo del CUERPO, y si hay un punto de inyección justo después de la primera etiqueta P, entonces un atacante podría inyectar </P><P><DIV><SCRIPT>alert('nasty')</SCRIPT> , y ahora el el navegador tratará el desagradable guión del atacante como parte de la parte de la página incluida en la lista blanca.

Recomendación general: no recomendaría confiar en esta defensa. Tiene una serie de debilidades.

    
respondido por el D.W. 07.01.2011 - 03:50
fuente
1

Alguien me señaló su pregunta porque tenía una muy similar pero (hasta ahora) sin la posibilidad de romper:
enlace

Quizás juntos encontremos una buena solución;)

    
respondido por el mgutt 02.05.2011 - 00:32
fuente

Lea otras preguntas en las etiquetas