¿Cómo es posible envenenar el constructor de Arrays de JavaScript y cómo ECMAScript 5 evita eso?

11

De la documentación de Django de su JsonResponse :

  

Antes de la quinta edición de ECMAScript era posible para envenenar al constructor JavaScript Array. Por esta razón, Django no permite pasar objetos no dictados al constructor JsonResponse de forma predeterminada. Sin embargo, la mayoría de los navegadores modernos implementan EcmaScript 5 que elimina este vector de ataque. Por lo tanto, es posible desactivar esta precaución de seguridad.

¿Qué tan exactamente puede ser peligroso enviar datos desde el servidor al navegador en forma de una matriz de JavaScript? ¿Cómo se llama tal ataque?

Mis experimentos mostraron que mientras Django por defecto se queja por enviar algo a este navegador: ["foo", "bar"] , no se queja por enviar algo así: {"foo": ["bar", "baz"]} ¿Cómo puede ser más seguro? enviar una matriz envuelta en un objeto que enviar una matriz "sin procesar"?

¿Cómo EMCAScript 5 previene eso?

    
pregunta gaazkam 16.05.2017 - 14:02
fuente

1 respuesta

9

El ataque asociado con el envenenamiento del constructor de Array se denomina secuestro JSON . Es una instancia de un problema conocido como inclusión de secuencia de comandos entre sitios (XSSI) esto se debe al hecho de que los navegadores generalmente permiten que los sitios web incluyan archivos JS externos de origen cruzado.

Supongamos que un usuario autenticado en su sitio puede acceder a algunos "tokens secretos" en esta ubicación de API:

https://yoursite.example/api/secret_tokens

Y digamos que la respuesta de la API se parece a esto:

tokens = ["secret123", "secrect456"]

Esto crea una vulnerabilidad. Un atacante podría filtrar de forma trivial los tokens de un usuario registrado enviándoles un enlace a evil.example que tendría un código como este:

<script src="https://yoursite.example/api/secret_tokens"></script><script>alert(tokens)</script>

Deestamanera,elnavegadordelavíctimaesengañadoparainterpretarlarespuestadelaAPIcomounarchivoJSexterno.LaAPIestácreandoinadvertidamenteuncódigoJSválido(asignandolamatrizaunavariableglobaltokens)y,porlotanto,pierdelostokensdeunusuarioregistradoenevil.example.

Ahora,consideremoselcasomásprobabledequesurespuestaAPIseveasimilaraesto:

["secret123", "secret456"]

Esto sigue siendo un código JS válido, pero como solo es una expresión sin asignaciones, un atacante no puede acceder al contenido de la matriz tan fácilmente como se indicó anteriormente. La solución aquí fue simplemente anular el constructor de Array:

Array = function() { foo = this; }

Este truco en particular fue reportado y corregido en Firefox en 2007 pero desde entonces, otras técnicas, por ejemplo. empleando Object.__defineSetter__ o Object.defineProperty , se han encontrado (y corregido).

  

¿Cómo EMCAScript 5 previene eso?

Las demandas de especificación de ES5 que [] siempre usa el% incorporado Array constructor (y lo mismo se aplica a los constructores de objetos):

  

15.4.1.1 Array ([item1 [ item2 […]]])

     

Cree y devuelva un nuevo objeto de Array exactamente como si el constructor incorporado estándar Array se usara en una expresión new con los mismos argumentos (15.4.2).

Finalmente, consideremos el caso en que la API responde con un objeto JSON:

{"tokens": ["secret123", "secret456"]}

La simple razón por la que nunca ha sido vulnerable es que no es válido. JS: Un objeto aislado entre llaves es analizado como un bloque en lugar de un objeto . Por lo tanto, no puede incluir este objeto JSON como un script externo sin desencadenar un error. Históricamente, desencadenar un error de sintaxis ha sido una forma conveniente de prevenir ataques XSSI.

Aquí hay algunas referencias adicionales al secuestro JSON:

respondido por el Arminius 16.05.2017 - 14:58
fuente

Lea otras preguntas en las etiquetas