it-swarm-es.com

Incluir elementos DOM en la lista blanca para derrotar a XSS

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

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

Suponga que su navegador admite elementos DOM de listas blancas. Estos elementos de la lista blanca son los únicos elementos autorizados para ejecutar JavaScript. Rápidamente se da cuenta de que suena loco porque es imposible mantener su sitio web preferido funcionando correctamente si tiene una lista blanca tan genérica. ¡Y tienes razón!

Pero ahora suponga que los motores HTML y JavaScript admiten una sintaxis que le permite incluir en la lista blanca 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 renderizar 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 principal para invocar allowJavaScript.

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

<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 debería 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;
13
jweyrich

Restringir la lista blanca al elemento <head> 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 del <li> ejemplo 1 </li> no es de confianza en el ejemplo. Entonces, 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 una validación estricta del elemento dom. Pero es probable que desee permitir algunos elementos anidados como <b> y <i>.

Parece mucho más fácil escapar correctamente del contenido que no es de confianza en función de una lista blanca de etiquetas y atributos permitidos.

PD: Tenga en cuenta que hay otras cosas desagradables como JavaScript incrustado en CSS y complementos como Flash y Java.

8

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 una gran pérdida de recursos.

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

14
Purge

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

Esta es la especificación .

La Política de seguridad de 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 principal de defensa , 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 depender demasiado de la CSP.

A continuación, se muestran algunos ejemplos de políticas:

Ejemplos de definiciones de políticas

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 de cualquier lugar, agregar contenido de una lista de proveedores de medios confiables (incluida una red de distribución de contenido) y scripts solo de su servidor que aloja 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 quieren denegar todos los scripts de terceros para el sitio, y un grupo de proyecto determinado también quiere rechazar los medios de otros sitios (el encabezado proporcionado por los administradores de sistemas y el encabezado proporcionado por el grupo del 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 a los ataques, hace que sea mucho más difícil que agregar la política de seguridad en línea en el DOM donde podría mutar.

Creo que es bueno pensar en tu idea/pregunta, pero a medida que empiezas a hacerlo más y más completo, llega un punto en el que resulta demasiado caro hacerlo bien.

Tuve una idea similar cuando me di cuenta de lo molesto que es que todos los recursos ¡deberían ser servidos a través de SSL si se supone que la página está protegida por SSL. Mi primer pensamiento fue una idea en torno a tener sumas de comprobación para cada recurso que se puede cargar en la página SSL (cargarlos sin cifrar facilitaría su almacenamiento en caché). 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 DOM podría sufrir rápidamente de la misma manera.

Un último punto : si tiene suficiente conocimiento para incluir en la lista blanca en el navegador, ¿por qué no puede ejecutar la lista blanca en los datos que está proporcionando antes de enviarlos? al navegador?

10
Bradley Kreider

Me parece una idea interesante, pero como me preguntas acerca de los problemas, responderé con algunos de los obvios. No veo cómo esto se puede aplicar 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 que sea necesario aplicarlo en cualquier nivel del DOM. Por ejemplo, si solo quisiera proteger mi <div name="untrusted"> contenido.

8
Weber

XSS generalmente funciona inyectando JavaScript externo 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 es producido por una vulnerabilidad XSS? Siempre que ambos residan en el mismo contexto de la misma página, que es la idea principal de XSS, no tiene forma de distinguir uno del otro.

Por supuesto, podría decir que tiene un contexto "privilegiado", por ejemplo, dentro de <head> - y contexto "sin privilegios" 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 XSS que permitiría inyectar contenido en la parte "privilegiada" de la página. Por supuesto, esos serían menos frecuentes, pero no resolverían todo el problema; aún 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ía que editar la lista de elementos privilegiados, mientras que al mismo tiempo siempre mantiene las partes "dinámicas" fuera de ella. Eso puede resultar bastante difícil de hacer en proyectos reales, especialmente porque algunas páginas se ensamblan con muchos widgets independientes generados por partes separadas de la aplicación, que pueden ser producidos por equipos completamente diferentes.

7
StasM

Dado su interés, le animo a leer sobre Ter Louw y Vernkatakrishnan's Blueprint , Dan Kaminsky's Interpolique y la Política de seguridad de contenido de Mozilla. Consulte también escape automático consciente del contexto , como se implementó en la ctemplate de Google . Hay mucho trabajo previo fantástico: asegúrese 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 un script dentro de ella que invoca allowJavaScript?

El trabajo anterior también muestra que detener la ejecución de JavaScript malicioso no es suficiente para ser seguro. Si un atacante puede inyectar material arbitrario en su página HTML, entonces el atacante puede: (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) phishing a sus usuarios o robar credenciales de autenticación (piense en agregar un formulario de inicio de sesión que solicite al usuario su nombre de usuario y contraseña, pero donde la acción del formulario se envía al sitio del atacante), (iv) monte ataques CSRF (piense en una imagen en línea o un 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. Consulte el artículo de Huang, Weinberg, Evans y Jackson en CCS 2010. Es probable que su esquema sea vulnerable a esto, si existe algún punto de inyección en el documento, al menos en algunos navegadores.

Por último, si está incluyendo elementos en la lista blanca en el DOM, ¿qué impide que un atacante que inyecta cosas en la página HTML abra y cierre etiquetas hasta que sus datos maliciosos estén en el contexto del elemento en la lista blanca? Por ejemplo, si su política dice que la secuencia de comandos está permitida en la segunda etiqueta P debajo del primer DIV debajo de BODY, 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 navegador tratará el desagradable script del atacante como parte de la lista blanca de la página.

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

6
D.W.

Alguien me señaló su pregunta ya que tenía una muy similar pero (hasta ahora) sin la posibilidad de romper:
https://stackoverflow.com/questions/5821985/would-this-be-a-good-idea-against-xss

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

1
mgutt