2009-12-03 17 views
83

My Spider Sense mi avverte che usare eval() per analizzare JSON in arrivo è una cattiva idea. Mi stavo chiedendo se JSON.parse() - che presumo sia una parte di JavaScript e non una funzione specifica del browser - sia più sicuro.JSON.parse vs. eval()

risposta

97

Siete più vulnerabili alle attacchi se si utilizza eval: JSON è un sottoinsieme di Javascript e json.parse analizza JSON mentre eval lascerebbe la porta aperta a tutte le espressioni JS.

+0

* "Sei più vulnerabile agli attacchi" *, non sono assolutamente d'accordo! – Hydro

+2

Scusa, Matheus, devo essere d'accordo. Il problema è quando si utilizza eval() per interpretare "input utente" - che è QUALUNQUE fonte esterna dal proprio JavaScript (compresi i valori restituiti da servlet o altri servizi Web che si sono chiamati).Non è possibile garantire che gli utenti non abbiano inserito il codice JavaScript dannoso direttamente nell'app del client o indirettamente a causa di dati non convalidati memorizzati nel database del server e quindi trasmessi al programma tramite una chiamata in stile AJAX. Potrebbe comunque essere necessario convalidare singoli campi per evitare attacchi "confusi da deputato", ma l'utilizzo di JSON.parse è un buon primo passo. – JackLThornton

+0

@Hydro Breve prova del concetto: prova 'eval ('alert (1)');'. –

4

JSON è solo un sottoinsieme di JavaScript. Ma eval valuta il linguaggio JavaScript completo e non solo il sottoinsieme che è JSON.

+0

Giusto, lo so. Stai insinuando che JSON.parse() SOLO valuta JSON e fallisce su tutti gli altri dati in entrata? O è semplicemente un wrapper per: var myObject = eval ('(' + responseText + ')'); ?? –

+5

@Kevin Major: Sì, il 'JSON.parse 'implementato in modo nativo (implementato direttamente nel motore JavaScript) analizza solo JSON. Ma altre implementazioni non native usano un controllo di integrità e quindi usano 'eval' per motivi di prestazioni. – Gumbo

9

Se analizzi il JSON con eval, stai permettendo che la stringa che viene analizzata contenga assolutamente nulla, quindi invece di essere solo un insieme di dati, potresti trovarti ad eseguire chiamate di funzione o altro.

Inoltre, JSON di parse accetta un parametro adizionale, reviver, che consente di specificare come trattare con certi valori, come ad esempio datetimes (ulteriori informazioni ed esempi nella documentazione in linea here)

13

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

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

29

Tutti JSON.parse implementazioni più probabile usare eval()

JSON.parse si basa su Douglas Crockford's solution, che utilizza eval() proprio lì sul 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 + ')'); 

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

+50

sì, tranne per il fatto che la riga subito prima verifica che si tratti di una stringa sicura e valida. – nickf

+3

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

+0

@plodder "advantage" probabilmente non è economico per fare ciò. – momomo

9

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 

Vai a questa example.

+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 c'è dubbio sulla natura dell'espressione e eval creerà una matrice contenente l'oggetto analizzato –

+1

Sì. Tradizionalmente, x sarebbe racchiuso tra parentesi: eval ("(" + x + ")"). Ciò che ho detto continua a essere: non c'è ambiguità quando si usa JSON.parse(). –