Escapando las constantes de JavaScript

7

¿cómo pueden incluirse valores no confiables en una página html como constantes de cadena de javascript? Aunque el caso que estoy preguntando utiliza JSF y Rails, creo que este es un problema general independiente del marco del lado del servidor.

en-atributos

Obviamente, no es suficiente escapar \ '"en los atributos on:

onclick='alert("[variable]")'
variable: hello, world"); alert("XSS
result: alert("hello, world"); alert("XSS")

En Firefox esto mostrará un "Hola, mundo" y un diálogo de alerta "XSS". Como la variable no contiene un ", la función Rails escape_javascript no es suficiente en este contexto. Appyling html El escape parece ser seguro, ya que solo se muestra el cuadro de diálogo original en este caso:

result: onlick='alert("hello, world"); alert("XSS")'

etiquetas de script

En < script > Las etiquetas, sin embargo, se aplican diferentes reglas en Firefox:

<script type="text/javascript">
   alert("hello, world&quot;); alert(&quot;XSS");
</script>

Esto muestra solo un cuadro de diálogo; pero las citas se muestran en su forma de escape. Hay dos conclusiones: 1) & quot; no se analiza como un signo de cita de JavaScript (bueno), segundo) tampoco se analiza de acuerdo con las reglas HTML (incorrecto). Para que cualquier intento de html escapar de la constante crea datos rotos.

Saltar html que se escapa en las etiquetas de script, sin embargo, no es una opción:

<script type="text/javascript">alert("[variable]");</script>
variable: hello, world</script><script>alert("XSS
result: <script type="text/javascript">
        alert("hello, world</script><script>alert("XSS");</script>

La primera etiqueta de secuencia de comandos crea un error de sintaxis debido a la falta ". Pero en Firefox se ejecuta la segunda etiqueta de secuencia de comandos inyectada.

tl, dr

¿Existe una forma segura de escribir valores no confiables en constantes de JavaScript? Esto parece ser un desastre total, y actualmente me estoy inclinando hacia el uso de elementos html (con style="dispaly: none"). Una llamada XMLHttpRequest usando JSON sería otra opción. Pero ambos enfoques se sienten como trampa.

    
pregunta Hendrik Brummermann 23.12.2010 - 19:53
fuente

4 respuestas

4

Si estuviera en ASP.NET, le recomendaría que utilice WPL de MS: el componente AntiXSS proporciona un código .JavaScriptEncode () Método, exactamente lo que necesitas.
Si estuvieras en JEE, te hubiera sugerido que uses biblioteca ESAPI de OWASP : también hay una. Método encodeForJavaScript () (creo que lo escribí correctamente, de la memoria ...).
Desafortunadamente, no estoy lo suficientemente familiarizado con Rails para proporcionar una solución para eso, pero quizás OWASP también tenga algo allí ... (EDIT: OWASP está trabajando actualmente en un puerto para Ruby, aunque aún no se ha publicado) ...

Lo que hacen ambos métodos: codifica explícitamente todo que no se considera un carácter "seguro".
Lo que hace not do: listas negras de ciertos caracteres "malos", que deberían actualizarse constantemente, ya que se omiten.
De ser necesario, probablemente debería poder piratear eso también en Rails, de acuerdo con la primera parte. PERO No lo recomendaría, a menos que fuera absolutamente necesario.

    
respondido por el AviD 23.12.2010 - 23:44
fuente
6

Otra biblioteca de codificación interesante (más antigua) es el Proyecto de codificación OWASP (anteriormente, la biblioteca "Reform") - enlace

Esto es funcionalmente idéntico al AntiXSS 1.x de Microsoft (no es inusual: Mike Eddington escribió gran parte de la biblioteca interna de Microsoft que luego se convirtió en AntiXSS y luego en WPL), pero es compatible con la mayoría de los idiomas web comunes excepto Ruby / Rails.

Implementa un enfoque de codificación pesimista (codifica todo excepto lo que se sabe que es seguro), y te da resultados como estos:

eval ('; - > eval \ x28 \ x27 \ x3b

eval \ u0080 - > eval \ u0080

\ u003cscript \ u003e. - > \ x3cscript \ x3e.

    
respondido por el Justin Clarke 27.12.2010 - 15:19
fuente
6

El escape de HTML no es suficiente en los atributos de un clic si alguna de sus propiedades de seguridad se basa en la ejecución del código, por ejemplo. un controlador de envío de información crítico o un controlador de carga. Si un atacante puede incrustar el punto de código U + 2028 o U + 2029, entonces puede causar que el análisis se rompa, ya que no se permite que salgan de forma segura en las cadenas JS.

Si está tratando con XHTML en lugar de HTML, y ha definido sus propias% entidades, entonces estas son siempre una vía de ataque, a menos que también escape%, pero si está usando XML, entonces hay menos de una diferencia entre cuerpos de elementos de script y atributos.

    
respondido por el Mike Samuel 10.01.2011 - 13:49
fuente
5

Como ha notado, hay al menos dos contextos diferentes, que requieren diferentes reglas de escape: etiquetas SCRIPT y valores de atributos que contienen Javascript. En lugar de intentar encontrar una sola respuesta que funcione para ambos, debe buscar una solución diferente para cada contexto. Comentaré principalmente sobre literales de cadena dentro de las etiquetas SCRIPT.

Una forma sencilla de codificar constantes de cadena en Javascript es tomar caracteres no seguros y traducirlos a escapes de Unicode: por ejemplo, a - > %código%. Sugiero construir una pequeña lista blanca de caracteres seguros (a-z, A-Z, 0-9) y codificar todo lo demás.

Incluso mejor sería utilizar una biblioteca estándar y bien examinada para escapar. No tengo una recomendación específica, pero otros pueden tener una. AntiXSS tiene una buena reputación, y JavaScriptEncode parece relevante. Solo asegúrate de que sea apropiado para el contexto particular en el que se insertará la cadena.

Trampas no obvias:

  • Como notó, \u0061 puede terminar una etiqueta SCRIPT, incluso cuando está dentro de una cadena entre comillas. Esto se debe a que, cuando el navegador ve una etiqueta </SCRIPT> open, el analizador HTML del navegador comienza a buscar una etiqueta <SCRIPT> de cierre antes , comienza a analizar el Javascript utilizando el analizador Javascript y un </SCRIPT> dentro de una constante de cadena puede cerrar prematuramente la etiqueta SCRIPT. Por lo tanto, los paréntesis angulares no son seguros para aparecer sin escapar dentro de un literal de cadena de Javascript. Por razones similares, los símbolos no son seguros, tampoco. (Agradezco a Adam Barth y Collin Jackson por enseñarme acerca de esta sutileza).
  • Las citas se pueden usar para romper una cadena entre comillas, por lo que las comillas simples y dobles no son seguras.
  • Las barras invertidas se pueden usar para romper una cadena entrecomillada (imagine que termina con un </SCRIPT> ) y, por lo tanto, no son seguras.
  • Si usa JSON e incluye entradas de usuarios que no son de confianza dentro del nombre de una propiedad (en lugar del valor), las cosas pueden complicarse. Asegúrese de citar el nombre y aplique las mismas reglas que usaría para otros literales de cadena. Además, también pueden ser necesarias otras comprobaciones (por ejemplo, deshabilitar 'valueOf', etc.).
  • Tenga cuidado con el conjunto de caracteres utilizado en la página HTML. UTF-7 realmente puede arruinar tu día . Le sugiero que trate a + y - como caracteres no seguros, y que se asegure de que la página incluya un conjunto de caracteres explícitos en el encabezado HTTP de tipo de contenido o una etiqueta META HTML (para minimizar la posibilidad de que el navegador intente detectar automáticamente la conjunto de caracteres).
  • Tenga cuidado de no hacer doble escape. El doble escape puede reintroducir problemas de seguridad, en algunos casos.

Recursos útiles: enlace , enlace . Además, lo aliento a que revise Blueprint y Interpolique de Dan Kaminsky, dos Métodos innovadores para abordar este tipo de problemas.

    
respondido por el D.W. 07.01.2011 - 10:35
fuente

Lea otras preguntas en las etiquetas