2009-12-03 12 views
83

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

Respuesta

97

Usted es más vulnerable a ataques si utilizando eval: JSON es un subconjunto de JavaScript y JSON.parse simplemente analiza JSON mientras que eval dejaría la puerta abierta a todas las expresiones JS.

+0

* "Eres más vulnerable a los ataques" *, ¡estoy totalmente en desacuerdo! – Hydro

+2

Lo siento, Matheus, tengo que estar de acuerdo. El problema es cuando está utilizando eval() para interpretar "entrada de usuario", que es CUALQUIER fuente externa de su JavaScript (incluidos los valores devueltos de servlets u otros servicios web a los que ha 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 transmitidos a su programa a través de una llamada al estilo AJAX. Es posible que aún necesite validar campos individuales para evitar ataques de "diputado confundido", pero usar JSON.parse es un buen primer paso. – JackLThornton

+0

@Hydro Prueba de concepto breve: intente 'eval ('alert (1)');'. –

4

JSON es sólo un subconjunto de JavaScript. Pero eval evalúa el lenguaje de JavaScript completo y no solo el subconjunto que es JSON.

+0

Derecho, lo sé. ¿Está implicando 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 + ')'); ?? –

+5

@Kevin Major: Sí, el 'JSON.parse' originalmente implementado (directamente implementado en el motor de JavaScript) analiza solo JSON. Pero otras implementaciones que no son nativas usan algunas verificaciones de cordura y luego usan 'eval' por razones de rendimiento. – Gumbo

9

Si analiza el JSON con eval, está permitiendo que la cadena analizada contenga absolutamente todo, así que en lugar de simplemente ser un conjunto de datos, podría encontrarse ejecutando llamadas a funciones, o lo que sea.

Además, JSON de parse acepta un parámetro adicional, resucitador, que le permite especificar cómo hacer frente a ciertos valores, como datetimes (más información y ejemplos en la documentación en línea here)

13

No todos los navegadores tienen soporte JSON nativa por lo que habrá momentos en los que hay que utilizar eval() a la cadena JSON. Utilice el analizador JSON desde http://json.org ya que maneja todo mucho más fácil para usted.

Eval() es un mal sino contra algunos navegadores es un mal necesario, pero donde se puede evitar, lo hacen !!!!!

29

Todos JSON.parse implementaciones más probable es que utilice eval()

JSON.parse se basa en Douglas Crockford's solution, que utiliza eval() allí mismo, en line 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.parse es que se verifica el argumento es la sintaxis correcta JSON.

+50

, sí, excepto que la línea justo antes de eso verifica que es una cadena segura y válida. – nickf

+3

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

+0

@plodder "ventaja" probablemente no es barato hacer eso verificando. – momomo

9

hay una diferencia entre lo JSON.parse() y eval() aceptará. Trate de eval en esto:

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

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

ver este example.

+1

eval no funciona porque analiza cadenas como instrucciones 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 dudas sobre la naturaleza de la expresión y eval creará una matriz que contiene el objeto analizado –

+1

Sí. Tradicionalmente, x estaría envuelto por paréntesis: eval ("(" + x + ")"). Lo que dije sigue en pie: no hay ambigüedad al usar JSON.parse(). –