JSON.parse vs. eval ()


94

Il mio Spider Sense mi avverte che utilizzare eval()per analizzare il JSON in arrivo è una cattiva idea. Mi chiedo solo se JSON.parse()- che presumo faccia parte di JavaScript e non una funzione specifica del browser - sia più sicuro.


Dal punto di vista delle prestazioni, JSON.parseè più veloce eval, almeno nel V8 (motore JS di Chromium). Fonte .
Paul,

Risposte:


110

Sei più vulnerabile agli attacchi se usi eval: JSON è un sottoinsieme di Javascript e json.parse analizza solo JSON mentre evallascerebbe la porta aperta a tutte le espressioni JS.


"Sei più vulnerabile agli attacchi" , sono completamente in disaccordo!
Hydroper

4
Scusa, Matheus, devo essere d'accordo. Il problema è quando si utilizza eval () per interpretare "l'input dell'utente", che è QUALSIASI sorgente esterna al proprio JavaScript (inclusi i valori restituiti dai servlet o da altri servizi Web che hai chiamato). Non puoi garantire che gli utenti non abbiano inserito JavaScript dannoso direttamente nella tua app client o indirettamente a causa di dati non convalidati archiviati nel database del server e poi passati al tuo programma tramite una chiamata in stile AJAX. Potrebbe essere necessario convalidare i singoli campi per evitare attacchi "vice confusi", ma l'utilizzo di JSON.parse è un buon primo passo.
JackLThornton

1
@ Hydro Breve dimostrazione del concetto: prova eval('alert(1)');.
Valerio Bozz

37

È JSON.parsemolto probabile che tutte le implementazioni utilizzinoeval()

JSON.parsesi basa sulla soluzione di Douglas Crockford , che utilizza eval()proprio lì sulla linea 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 + ')');

Il vantaggio di JSON.parseè che verifica che l'argomento sia la sintassi JSON corretta.


56
sì, tranne per il fatto che la riga subito prima verifica che sia una stringa valida e sicura.
nickf

6
Ho provato JSON.parse()in Firefox 28 e Chromium 33 sul mio sistema Linux Mint. Era 2x più veloce eval()di Firefox e 4x più veloce di Chromium. Non sono sicuro del codice sorgente che stai pubblicando, ma non sono la stessa cosa nei miei browser.
jbo5112

@plodder "vantaggio" probabilmente non è economico per fare quella verifica.
mmm

2
I browser moderni forniscono JSON.parse()un'implementazione nativa che è più sicura e veloce dei eval()parser basati su.
Mohammad Alhashash

15

Non tutti i browser hanno il supporto JSON nativo, quindi ci saranno momenti in cui sarà necessario utilizzare eval() la stringa JSON. Usa il parser JSON da http://json.org in quanto gestisce tutto molto più facilmente per te.

Eval() è un male ma contro alcuni browser è un male necessario ma dove puoi evitarlo fallo !!!!!


12

C'è una differenza tra ciò che JSON.parse () e eval () accetteranno. Prova eval su questo:

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

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

Vedi questo esempio .


1
eval non funziona perché analizza le stringhe come istruzioni di codice e quindi considera "{...}" come un'espressione di codice invece di un'espressione di dichiarazione di valore. se rimuovi l'ambiguità ("[{....}]" per esempio), non ci sono dubbi sulla natura dell'espressione e eval creerà un array contenente l'oggetto analizzato
Charles HETIER

1
Sì. Tradizionalmente, x sarebbe racchiuso tra parentesi: eval ("(" + x + ")"). Quello che ho detto è ancora valido: non c'è ambiguità quando si usa JSON.parse ().
Jeff Lowery

9

Se analizzi il JSON con eval, stai consentendo alla stringa analizzata di contenere assolutamente qualsiasi cosa, quindi invece di essere solo un insieme di dati, potresti ritrovarti a eseguire chiamate di funzione o qualsiasi altra cosa.

Inoltre, JSON parseaccetta un parametro aggiuntivo, reviver, che ti consente di specificare come gestire determinati valori, come i datetimes (maggiori informazioni ed esempio nella documentazione in linea qui )


4

JSON è solo un sottoinsieme di JavaScript. Ma evalvaluta l'intero linguaggio JavaScript e non solo il sottoinsieme che è JSON.


Sì, lo so. Stai insinuando che JSON.parse () valuta SOLO JSON e fallisce su tutti gli altri dati in arrivo? Oppure è semplicemente un wrapper per: var myObject = eval ('(' + responseText + ')'); ??
Kevin Major

6
@ Kevin Major: Sì, l'implementazione nativa JSON.parse(implementata direttamente nel motore JavaScript) analizza solo JSON. Ma altre implementazioni non native usano eseguire alcuni controlli di integrità e quindi utilizzare evalper motivi di prestazioni.
Gumbo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.