¿Es esta codificación JSON vulnerable a la inyección de CDATA?

2

Encontré una notación impar en las páginas generadas por jsfiddle.net

<script type='text/javascript'>//<![CDATA[ 
$(window).load(function(){
$('form, table').animate({
    opacity: 1
});
});//]]>  

</script>

A veces alimento datos JSON directamente en un script. Personalmente no uso la notación CDATA, pero quiero confirmar si un atacante podría inyectar la notación CDATA y causar que sucedan cosas malas.

Ejecuto los objetos a través de un modificador de JSON estándar que sigue todas las reglas , luego reemplazo </script con <\/script . no entre mayúsculas y minúsculas. ¿Es esto suficiente?

    
pregunta George Bailey 26.01.2012 - 21:06
fuente

2 respuestas

6

El hack //<![CDATA[ se usa en páginas XHTML que tienen que analizar tanto HTML como XML.

En las reglas de análisis de HTML, <script> y <style> son "elementos CDATA" especiales, cuyos contenidos hasta la siguiente secuencia </ (HTML4) o </script secuencia (HTML5) son datos sin procesar, por lo que if (x<y) puede escribirse sin ningún tipo de codificación; esto ensuciaría los analizadores XML.

En las reglas de análisis XML no hay elementos especiales, por lo que la misma declaración debería escribirse como if (x&lt;y) ; esto ensuciaría los analizadores HTML.

Para permitir que < se escriba sin escapar y significa lo mismo para los analizadores XML y HTML, puede envolver el script en una Sección CDATA de XML, luego proteger los analizadores HTML de esa construcción extraña escondiéndolo en un Comentario de JavaScript.

Si está utilizando este constructo para permitirle incluir estos caracteres en un literal de cadena sin escapar, no es suficiente, ya que todavía tiene que escapar de la secuencia </ (para HTML) y ]]> (para XML). Una forma de escapar de esas secuencias en un literal de cadena JS es codificar siempre los caracteres <>& a \x3C , \x3E y \x26 respectivamente ... en cuyo caso ya no necesitaría la sección CDATA.

  

Ejecuto los objetos a través de un modificador de JSON estándar que sigue todas las reglas, luego sustituyo </script con <\/script , no distingue entre mayúsculas y minúsculas. ¿Es esto suficiente?

No necesariamente.

  1. sintaxis HTML. <\/script está bien para HTML pero no para XHTML, como se indicó anteriormente.

  2. Sintaxis de JavaScript. Hay, debido a un desafortunado descuido en el diseño de JSON, algunos caracteres de control Unicode que son válidos en JSON pero no son válidos en JavaScript.

Más notablemente los caracteres U + 2028 y U + 2029, Separador de líneas y párrafos, que actúan como nuevas líneas. Inyectar una nueva línea en el medio de un literal de cadena probablemente causará un error de sintaxis (literal de cadena sin terminar).

Hay más caracteres de control que se supone que no son válidos en los literales de cadena JS, pero que en realidad no interrumpen los navegadores en la práctica.

Si su codificador JSON codifica habitualmente todos los caracteres que no son ASCII, esto no será un problema.

Alternativa a la correcta codificación de JS incrustada: evite los scripts en línea por completo, coloque sus datos en la página HTML (donde se aplican las reglas de escape de HTML normales) y recupérela de los scripts vinculados utilizando métodos DOM.

    
respondido por el bobince 26.01.2012 - 23:29
fuente
3

Respuesta corta, reemplazando los caracteres < y > globalmente con \u003c y \u003e permitirá incrustar elementos HTML <script> de forma segura, y se puede realizar en JSON válido sin romperlo.

Para incrustarlo en XML, debe asegurarse de que JSON solo contenga caracteres que puedan aparecer en XML. Específicamente, XML solo puede contener caracteres no de control , por lo que también necesita \u.... escapar de dichos caracteres.

enlace toma la entrada de tipo JSON y produce una salida que es JSON válida y que es segura de incrustar en los elementos HTML <script> y dentro de las secciones XML <![CDATA[...]]> .

  

Dado el contenido similar a JSON, lo convierte a JSON válido.

     

Esto se puede adjuntar en cualquier extremo de un flujo de datos para ayudar a satisfacer el principio de Postel:

     
    

sea conservador en lo que hace, sea liberal en lo que acepta de los demás

  
     

Aplicado a contenido similar a JSON de otros, producirá JSON bien formado que debería satisfacer cualquier analizador que uses.

     

Aplicado a su salida antes de enviar, forzará errores menores en la codificación y hará que sea más fácil incrustar su JSON en HTML y XML.

     

Salida

     

La salida es JSON bien formada como se define en RFC 4627. La salida satisface tres propiedades adicionales:

     
  1. La salida no contendrá la subcadena (insensiblemente mayúsculas y minúsculas) "</script" , por lo que se puede incrustar dentro de un elemento de script HTML sin más codificación.
  2.   
  3. La salida no contendrá la subcadena "]]>" , por lo que se puede incrustar dentro de una sección CDATA XML sin más codificación.
  4.   
  5. La salida es una expresión de Javascript válida, por lo que puede ser analizada por eval builtin de Javascript (después de estar entre paréntesis) o por JSON.parse . Específicamente, la salida no contendrá ningún literal de cadena con nuevas líneas JS incrustadas (separador de párrafo U + 2028 o separador de línea U + 2029).
  6.   

Seguridad

     

Dado que la salida está JSON bien formada, pasarla a eval no tendrá efectos secundarios ni variables libres, por lo que no es un vector de inyección de código, ni un vector para la exfiltración de secretos.

     

Esta biblioteca solo garantiza que la cadena JSON → la fase del objeto Javascript no tenga efectos secundarios y no resuelva las variables libres, y no puede controlar cómo el código del lado del cliente interpreta el objeto Javascript resultante. Entonces, si el código del lado del cliente toma una parte de los datos analizados que están controlados por un atacante y los devuelve a través de un intérprete poderoso como eval o innerHTML , entonces ese código del lado del cliente podría sufrir efectos secundarios no deseados. p>

    
respondido por el Mike Samuel 17.10.2012 - 16:46
fuente

Lea otras preguntas en las etiquetas