JSON.parse contre eval ()


94

My Spider Sense m'avertit que l'utilisation eval()pour analyser le JSON entrant est une mauvaise idée. Je me demande simplement si JSON.parse()- ce qui, je suppose, fait partie de JavaScript et non d'une fonction spécifique au navigateur - est plus sécurisé.


En termes de performances, JSON.parseest plus rapide que eval, au moins en V8 (moteur JS de Chromium). Source .
Paul

Réponses:


110

Vous êtes plus vulnérable aux attaques si vous utilisez eval: JSON est un sous-ensemble de Javascript et json.parse analyse simplement JSON alors que evalcela laisserait la porte ouverte à toutes les expressions JS.


"Vous êtes plus vulnérable aux attaques" , je ne suis pas du tout d'accord!
Hydroper

4
Désolé, Matheus, je suis d'accord. Le problème est lorsque vous utilisez eval () pour interpréter "l'entrée utilisateur" - qui est TOUTE source externe à votre JavaScript (y compris les valeurs renvoyées par les servlets ou autres services Web que vous avez appelés). Vous ne pouvez pas garantir que les utilisateurs n'ont pas saisi de code JavaScript malveillant directement dans votre application cliente ou indirectement en raison de données non validées stockées dans la base de données du serveur, puis transmises à votre programme via un appel de style AJAX. Vous devrez peut-être valider des champs individuels pour éviter les attaques de type "adjoint confus", mais l'utilisation de JSON.parse est une bonne première étape.
JackLThornton

1
@Hydro Courte preuve de concept: essayez eval('alert(1)');.
Valerio Bozz

37

Toutes les JSON.parseimplémentations utilisent probablementeval()

JSON.parseest basé sur la solution de Douglas Crockford , qui utilise eval()directement la ligne 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 + ')');

L'avantage de JSON.parseest qu'il vérifie que l'argument est la syntaxe JSON correcte.


56
ouais, sauf que la ligne juste avant cela vérifie que c'est une chaîne sûre et valide.
nickf

6
J'ai testé JSON.parse()dans Firefox 28 et Chromium 33 sur mon système Linux Mint. C'était 2x plus rapide que eval()dans Firefox et 4x plus rapide dans Chromium. Je ne sais pas quel code source vous publiez, mais ce n'est pas la même chose dans mes navigateurs.
jbo5112

@plodder "avantage" n'est probablement pas bon marché pour faire cette vérification.
mmm

2
Les navigateurs modernes fournissent une JSON.parse()implémentation native qui est plus sûre et plus rapide que les eval()analyseurs basés sur.
Mohammad Alhashash

15

Tous les navigateurs n'ont pas de support JSON natif, il y aura donc des moments où vous devrez utiliser eval() la chaîne JSON. Utilisez l'analyseur JSON de http://json.org car cela gère tout beaucoup plus facilement pour vous.

Eval() c'est un mal mais contre certains navigateurs c'est un mal nécessaire mais là où vous pouvez l'éviter, faites-le !!!!!


12

Il y a une différence entre ce que JSON.parse () et eval () accepteront. Essayez eval sur ceci:

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

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

Voyez cet exemple .


1
eval ne fonctionne pas car il analyse les chaînes comme des instructions de code et considère donc "{...}" comme une expression de code au lieu d'une expression de déclaration de valeur. si vous supprimez l'ambiguïté ("[{....}]" par exemple), il n'y a aucun doute sur la nature de l'expression et eval créera un tableau contenant l'objet analysé
Charles HETIER

1
Oui. Traditionnellement, x serait entouré de parenthèses: eval ("(" + x + ")"). Ce que j'ai dit est toujours valable: il n'y a pas d'ambiguïté lors de l'utilisation de JSON.parse ().
Jeff Lowery

9

Si vous analysez le JSON avec eval, vous autorisez la chaîne en cours d'analyse à contenir absolument n'importe quoi, donc au lieu d'être simplement un ensemble de données, vous pourriez vous retrouver à exécuter des appels de fonction, ou autre.

De plus, JSON parseaccepte un paramètre supplémentaire, reviver, qui vous permet de spécifier comment traiter certaines valeurs, telles que les dates-heures (plus d'informations et d'exemples dans la documentation en ligne ici )


4

JSON n'est qu'un sous-ensemble de JavaScript. Mais evalévalue le langage JavaScript complet et pas seulement le sous-ensemble qui est JSON.


Oui, je le sais. Voulez-vous dire que JSON.parse () évalue UNIQUEMENT JSON et échoue sur toutes les autres données entrantes? Ou est-ce simplement un wrapper pour: var myObject = eval ('(' + responseText + ')'); ??
Kevin Major

6
@Kevin Major: Oui, l'implémentation native JSON.parse(directement implémentée dans le moteur JavaScript) analyse uniquement JSON. Mais d'autres implémentations non natives utilisent des vérifications de cohérence, puis les utilisent evalpour des raisons de performances.
Gumbo
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.