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: