¿Impidiendo la ejecución de JavaScript con JavaScript?

7

En un comentario en esta pregunta relacionada con la prevención XSS, @dandavis sugirió:

  

si la secuencia de comandos se ejecuta primero, es fácil dividir las siguientes secuencias de comandos

La idea es proporcionar un respaldo que impida (en línea) JavaScript para los navegadores que no admiten CSP.

Sé que es posible sobrescribir las funciones existentes, pero no me queda claro cómo funcionaría esto exactamente. ¿Existe una solución trivial que el 100% impida la ejecución de un script adicional? Si no es así, ¿hay soluciones que funcionen en la mayoría de los contextos o para la mayoría de los navegadores (y formas de omitirlos para otros contextos / navegadores)?

    
pregunta tim 31.08.2016 - 23:15
fuente

3 respuestas

5
  

¿Existe una solución trivial que el 100% impida la ejecución de secuencias de comandos adicionales?

No, no lo creo. Cada etiqueta de secuencia de comandos se ejecuta por sí misma, por lo que lanzar un error no detendría la siguiente secuencia de comandos. alert y compañía y quizás AJAX sincronizado vienen a la mente para evitar que se ejecuten más scripts, pero eso bloqueará todo el navegador.

  

Si no es así, ¿hay soluciones que funcionen en la mayoría de los contextos o para la mayoría de los navegadores (y formas de omitirlos para otros contextos / navegadores)?

Bueno, podrías intentar anular todas las variables globales haciendo un bucle sobre las propiedades de la ventana. Entonces, en teoría, los scripts no tendrían acceso al DOM para hacer nada. En práctica , esto probablemente no funcionará bien ya que no todas estas propiedades se pueden escribir. Dudo que sea posible eliminar todo lo que sea de interés.

Otros posibles hacks podrían ser intentar destruir el documento antes de que se ejecuten otros scripts, tal vez utilizando document.write de alguna manera. Esto estaría en la tierra del comportamiento indefinido y los dragones.

Ejemplo de código:

Todo el mundo ama una buena muestra de código, así que aquí un ejemplo de carga útil que imagino que es difícil de superar.

<iframe name="iwin"></iframe>
<script>
(function() {
    // Due to the name attribute on the iframe, iwin is now
    // an implicit global for the iframe's contentWindow.
    // It should not have been there before the tag was parsed,
    // and the name could be randomized.

    // For legacy IE, to make globals accessible (0_o).
    iwin.execScript && iwin.execScript();

    // PWND, we have new globals.
    var XMLHttpRequest = iwin.XMLHttpRequest;
})();
</script>
    
respondido por el Alexander O'Mara 31.08.2016 - 23:51
fuente
6
  

La idea es proporcionar un respaldo que impida (en línea) JavaScript para los navegadores que no admiten CSP.

Tenga en cuenta que la CSP no debe usarse como primera línea de defensa. Debería codificar adecuadamente por contexto para evitar XSS en su aplicación. OWSAP tiene buena información sobre esto.

Dicho esto, el CSP puede ser un buen recurso para hacer que XSS sea mucho menos serio, en caso de que se encuentre una vulnerabilidad de XSS (es decir, una codificación incorrecta o nula en algún lugar de su página) en su aplicación y se aproveche.

  

Sé que es posible sobrescribir las funciones existentes, pero no me queda claro cómo funcionaría exactamente esto.

Es muy fácil de hacer. Por ejemplo, XMLHttpRequest = myFunction , o XMLHttpRequest = null evitaría que los scripts usen XMLHttpRequest directamente.

El problema es que si un atacante puede no estar usando esa función en particular, y si el atacante sabe que estás haciendo esto, podría usar fácilmente un método alternativo. Si bien podría ser posible sobrescribir todas las funciones todas , no se recomienda como una solución confiable.

  

¿Existe una solución trivial que el 100% impida la ejecución de secuencias de comandos adicionales?

Si tiene un error de sintaxis en su <script> , entonces no se ejecutará nada en ese <script>...</script> . Desafortunadamente, con XSS, el atacante podría comenzar fácilmente un nuevo <script> que funcionaría bien.

También hay muchas formas de inyectar JavaScript además de <script> , por ejemplo, <img onload> o onerror .

Que yo sepa, no puede impedir de manera confiable que todos los siguientes HTML contengan la ejecución de XSS.

  

Si no es así, ¿hay soluciones que funcionen en la mayoría de los contextos o para la mayoría de los navegadores (y formas de omitirlos para otros contextos / navegadores)?

El soporte del navegador CSP versión 1 es empieza a ser bueno , y dado que CSP fue diseñado como una copia de seguridad de todos modos (no es la primera línea de defensa) usted puede detener su búsqueda allí sabiendo que el soporte del navegador será un problema cada vez menor.

Dicho esto, creo que la idea de sobrescribir las funciones podría hacer mucho para el éxito. Parece que así podría funcionar de manera confiable en teoría . Si bien esto no es recomendable, creo que sería un estudio interesante. Me pregunto cuán complejo sería implementar.

    
respondido por el George Bailey 01.09.2016 - 00:36
fuente
3

Escribí ese comentario con jQuery en mente, ya que es muy fácil de romper accidentalmente. Dado que el código más complicado del lado del cliente (el tipo con vectores) usa jQuery, el ajax común y las plantillas que causan vulnerabilidades simplemente no se ejecutarán sin él.

El modelo de seguridad de JavaScript es basado en referencias , lo que significa que si no puede alcanzar algo, no lo hace. Existen al código. Hay un par de referencias no esperadas como constructor.constructor("alert(666)")() , pero son manejables porque JS simplemente no tiene tantas funciones integradas para ofrecer (en comparación con php o .net lib). Si puedes ocultar o destruir la referencia, eliminas la capacidad. Doug Crockford habla mucho de esto , y en el modo "use strict" , es aún más exigible a nivel granular.

  • Sería mejor redirigir a una página sin etiquetas de script; una versión no js o "lofi", si está disponible.

  • Puedes usar un iframe de tamaño 100% con sandbox attrib para volver a servir la página sin script; algo para lo que tengo un bookmarklet para usarlo en las pruebas de compatibilidad (solo crea un iframe nuevo, lo dimensiona y establece .src a location.href ). No todos los navegadores admiten sandbox , por lo que es posible que esté robando a Peter para pagar a Paul si su objetivo es reducir el XSS pasado por alto.

  • window.stop() funciona en algunos navegadores (FF seguro), y es lo suficientemente simple como para detener la carga de la página in situ.

  • "quemarlos a todos"; Agrupe todas las propiedades globales integradas, dejando atrás solo las capacidades lógicas puras del lenguaje. La desventaja es que document no es modificable, que es todo lo que realmente necesita un adversario inteligente. Puede haber una forma fácil de romper document , pero es un gran vector como está.

respondido por el dandavis 01.09.2016 - 11:27
fuente

Lea otras preguntas en las etiquetas