JSON.parse vs. eval ()

94

Meu Spider Sense me avisa que usar eval()para analisar JSON de entrada é uma má ideia. Só estou me perguntando se JSON.parse()- o que presumo que seja parte do JavaScript e não uma função específica do navegador - é mais seguro.

Kevin Major
fonte
Em termos de desempenho, JSON.parseé mais rápido do que eval, pelo menos no V8 (motor JS do Chromium). Fonte .
Paul

Respostas:

110

Você fica mais vulnerável a ataques se usar eval: JSON é um subconjunto de Javascript e json.parse apenas analisa JSON, enquanto evaldeixaria a porta aberta para todas as expressões JS.

jldupont
fonte
“Você está mais vulnerável a ataques” , discordo totalmente!
Hydroper
4
Desculpe, Matheus, tenho que concordar. O problema é quando você está usando eval () para interpretar a "entrada do usuário" - que é QUALQUER fonte externa de seu JavaScript (incluindo valores retornados de servlets ou outros serviços da web que você chamou). Você não pode garantir que os usuários não tenham inserido JavaScript malicioso diretamente em seu aplicativo cliente ou indiretamente por causa de dados não validados armazenados no banco de dados do servidor e depois transmitidos ao seu programa por meio de uma chamada no estilo AJAX. Você ainda pode precisar validar campos individuais para evitar ataques de "deputado confuso", mas usar JSON.parse é um bom primeiro passo.
JackLThornton
1
@Hydro Breve prova de conceito: experimente eval('alert(1)');.
Valerio Bozz
37

Todas as JSON.parseimplementações provavelmente usameval()

JSON.parseé baseado na solução de Douglas Crockford , que usa eval()ali mesmo na linha 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 + ')');

A vantagem JSON.parseé que ele verifica se o argumento é a sintaxe JSON correta.

arrastar-se
fonte
56
sim, exceto que a linha antes disso verifica se é uma string segura e válida.
nickf de
6
Testei JSON.parse()no Firefox 28 e no Chromium 33 no meu sistema Linux Mint. Foi 2x mais rápido que eval()no Firefox e 4x mais rápido no Chromium. Não tenho certeza de qual código-fonte você está postando, mas eles não são a mesma coisa em meus navegadores.
jbo5112
@plodder "vantagem" provavelmente não é barato para fazer essa verificação.
mmm
2
Os navegadores modernos fornecem JSON.parse()implementação nativa que é mais segura e mais rápida do que os eval()analisadores baseados em.
Mohammad Alhashash
15

Nem todos os navegadores têm suporte nativo a JSON, portanto, haverá momentos em que você precisará usar eval() a string JSON. Use o analisador JSON de http://json.org, pois isso torna tudo muito mais fácil para você.

Eval() é um mal, mas contra alguns navegadores é um mal necessário, mas onde você pode evitá-lo, faça-o !!!!!

AutomatedTester
fonte
12

Há uma diferença entre o que JSON.parse () e eval () aceitarão. Experimente a avaliação neste:

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

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

Veja este exemplo .

Jeff Lowery
fonte
1
eval não funciona porque analisa strings como instruções de código e, portanto, considera "{...}" como uma expressão de código em vez de uma expressão de declaração de valor. se você remover a ambigüidade ("[{....}]" por exemplo), não há dúvida sobre a natureza da expressão e eval criará uma matriz contendo o objeto analisado
Charles HETIER
1
Sim. Tradicionalmente, x seria colocado entre parênteses: eval ("(" + x + ")"). O que eu disse ainda permanece: não há ambigüidade ao usar JSON.parse ().
Jeff Lowery de
9

Se você analisar o JSON com eval, está permitindo que a string que está sendo analisada contenha absolutamente qualquer coisa, então, em vez de ser apenas um conjunto de dados, você pode se ver executando chamadas de função ou qualquer outra coisa.

Além disso, o JSON parseaceita um parâmetro adicional, reviver, que permite especificar como lidar com certos valores, como datetimes (mais informações e exemplo na documentação inline aqui )

David Hedlund
fonte
4

JSON é apenas um subconjunto do JavaScript. Mas evalavalia a linguagem JavaScript completa e não apenas o subconjunto que é JSON.

quiabo
fonte
Certo, eu sei disso. Você está insinuando que JSON.parse () SOMENTE avalia JSON e falha em todos os outros dados de entrada? Ou é simplesmente um wrapper para: var meuObjeto = eval ('(' + responseText + ')'); ??
Kevin Major
6
@Kevin Major: Sim, o implementado nativamente JSON.parse(implementado diretamente no mecanismo JavaScript) analisa apenas JSON. Mas outras implementações não nativas usam para fazer alguma verificação de integridade e depois usam evalpor motivos de desempenho.
Gumbo