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é.

Kevin Major
la source
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.

jldupont
la source
"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.

bûcheur
la source
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 !!!!!

AutomatedTester
la source
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 .

Jeff Lowery
la source
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 )

David Hedlund
la source
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.

Gombo
la source
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