JSON.parse frente a eval ()

94

Mi Spider Sense me advierte que usar eval()para analizar JSON entrante es una mala idea. Me pregunto si JSON.parse(), que supongo que es parte de JavaScript y no una función específica del navegador, es más seguro.

Kevin Major
fuente
En cuanto al rendimiento, JSON.parsees más rápido que eval, al menos en V8 (motor JS de Chromium). Fuente .
Paul

Respuestas:

110

Eres más vulnerable a los ataques si usas eval: JSON es un subconjunto de Javascript y json.parse solo analiza JSON, mientras evalque dejaría la puerta abierta a todas las expresiones JS.

jldupont
fuente
"Eres más vulnerable a los ataques" , ¡no estoy de acuerdo!
Hydroper
4
Lo siento, Matheus, estoy de acuerdo. El problema es cuando está usando eval () para interpretar la "entrada del usuario", que es CUALQUIER fuente externa a su JavaScript (incluidos los valores devueltos de servlets u otros servicios web que haya llamado). No puede garantizar que los usuarios no hayan ingresado JavaScript malicioso directamente en su aplicación cliente, o indirectamente debido a datos no validados almacenados en la base de datos del servidor y luego pasados ​​a su programa a través de una llamada estilo AJAX. Es posible que aún deba validar campos individuales para evitar ataques de "delegados confusos", pero usar JSON.parse es un buen primer paso.
JackLThornton
1
@Hydro Breve prueba de concepto: inténtalo eval('alert(1)');.
Valerio Bozz
37

Todas las JSON.parseimplementaciones probablemente usaneval()

JSON.parsese basa en la solución de Douglas Crockford , que se utiliza eval()allí mismo en la línea 497 .

// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.

j = eval('(' + text + ')');

La ventaja de JSON.parsees que verifica que el argumento tenga la sintaxis JSON correcta.

empollón
fuente
56
sí, excepto que la línea antes de eso verifica que es una cadena segura y válida.
nickf
6
Probé JSON.parse()en Firefox 28 y Chromium 33 en mi sistema Linux Mint. Fue 2 veces más rápido que eval()en Firefox y 4 veces más rápido en Chromium. No estoy seguro de qué código fuente está publicando, pero no son lo mismo en mis navegadores.
jbo5112
La "ventaja" de @plodder probablemente no sea barata para hacer esa verificación.
mmm
2
Los navegadores modernos proporcionan una JSON.parse()implementación nativa que es más segura y rápida que los eval()analizadores basados ​​en.
Mohammad Alhashash
15

No todos los navegadores son compatibles con JSON nativo, por lo que habrá ocasiones en las que necesitará utilizar eval() la cadena JSON. Utilice el analizador JSON de http://json.org, ya que se encarga de todo mucho más fácilmente para usted.

Eval() es un mal pero contra algunos navegadores es un mal necesario pero donde puedas evitarlo, hazlo !!!!!

Probador Automatizado
fuente
12

Hay una diferencia entre lo que aceptarán JSON.parse () y eval (). Prueba eval en esto:

var x = "{\" shoppingCartName \ ": \" shopping_cart: 2000 \ "}"

eval(x)         //won't work
JSON.parse(x)   //does work

Vea este ejemplo .

Jeff Lowery
fuente
1
eval no funciona porque analiza cadenas como declaraciones de código y, por lo tanto, considera "{...}" como una expresión de código en lugar de una expresión de declaración de valor. si elimina la ambigüedad ("[{....}]" por ejemplo), no hay duda sobre la naturaleza de la expresión y eval creará una matriz que contiene el objeto analizado
Charles HETIER
1
Si. Tradicionalmente, x estaría entre paréntesis: eval ("(" + x + ")"). Lo que dije sigue en pie: no hay ambigüedad al usar JSON.parse ().
Jeff Lowery
9

Si analiza el JSON con eval, está permitiendo que la cadena que se analiza contenga absolutamente cualquier cosa, por lo que en lugar de ser solo un conjunto de datos, podría encontrarse ejecutando llamadas a funciones, o lo que sea.

Además, JSON parseacepta un parámetro adicional, reviver, que le permite especificar cómo manejar ciertos valores, como las fechas y horas (más información y ejemplo en la documentación en línea aquí )

David Hedlund
fuente
4

JSON es solo un subconjunto de JavaScript. Pero evalevalúa el lenguaje JavaScript completo y no solo el subconjunto que es JSON.

Gumbo
fuente
Bien, lo sé. ¿Está insinuando que JSON.parse () SOLO evalúa JSON y falla en todos los demás datos entrantes? O es simplemente un contenedor para: var myObject = eval ('(' + responseText + ')'); ??
Kevin Major
6
@Kevin Major: Sí, el implementado de forma nativa JSON.parse(implementado directamente en el motor de JavaScript) analiza solo JSON. Pero otras implementaciones que no son nativas usan verificaciones de cordura y luego usan evalpor razones de rendimiento.
Gumbo