Che cosa costituisce "uso improprio" della funzione javascript Eval? [chiuso]

13

Eval è una funzionalità linguistica notoriamente controversa. Douglas Crockford lo respinge. Mi chiedo quali rischi specifici Eval comporta. Secondo questa domanda, Improper use of eval opens up your code for injection attacks .

Quali sono alcuni usi impropri del comando Eval e quali buchi di sicurezza si aprono?

    
posta Derek Adair 22.03.2011 - 04:30
fonte

7 risposte

30

Ai tempi in cui stavo implementando il motore JScript, sostenevo di avere le camicie EVAL ISEVIL stampate, ma purtroppo non ci siamo mai riusciti.

Il mio più grande problema con eval non è l'ovvio attacco di iniezione di codice dannoso, anche se questo è certamente di enorme preoccupazione. Il mio più grande problema è che le persone tendono a usarlo come un vero e proprio martello per risolvere problemi davvero piccoli. La maggior parte degli usi del mondo reale che ho visto di "eval" in the wild quando ero nel team di JScript avrebbe potuto essere banalmente risolto usando una tabella di ricerca; e dal momento che ogni oggetto in JScript è già una tabella di ricerca non è come se fosse un carico oneroso. Eval riavvia il compilatore e distrugge completamente la capacità del compilatore di ottimizzare il tuo codice .

Per alcuni altri pensieri in questo senso vedi i miei articoli del 2003 sull'argomento:

Malvagità generale:

link

Injection attack evilness:

link

    
risposta data 22.03.2011 - 05:33
fonte
4

La maggior parte dei buchi di sicurezza è lo stesso tipo di buchi dell'iniezione SQL, ovvero concatenare l'input dell'utente nel codice JavaScript. La differenza è che mentre ci sono modi per garantire che ciò non accada con SQL, non c'è molto che tu possa fare con JavaScript.

Come esempio banale e inutile, un calcolatore JavaScript semplicistico:

textbox1.value = eval(textbox2.value);

Un esempio di utilizzo corretto sono alcuni dei packer JavaScript che comprimono JavaScript estraendo parole comuni e sostituendoli con brevi sostituzioni di 1-2 caratteri. Il packer emette quindi tutto questo insieme al codice di sostituzione della stringa basato sul dizionario generato, quindi evita il risultato.

    
risposta data 22.03.2011 - 05:26
fonte
1

Ci sono alcune cose che sono impossibili da fare in JS senza una funzione simile a eval ( eval , Function , e forse più).

Prendi apply per esempio. È facile da usare quando lo si utilizza su normali chiamate di funzione:

foo.apply(null, [a, b, c])

Ma come faresti questo per gli oggetti che stai creando tramite la nuova sintassi?

new Foo.apply(null, [a, b, c]) non funziona, né forma simile.

Ma puoi aggirare questa limitazione tramite eval o Function (io uso Function in questo esempio):

Function.prototype.New = (function () {
    var fs = [];
    return function () {
        var f = fs[arguments.length];
        if (f) {
            return f.apply(this, arguments);
        }
        var argStrs = [];
        for (var i = 0; i < arguments.length; ++i) {
            argStrs.push("a[" + i + "]");
        }
        f = new Function("var a=arguments;return new this(" + argStrs.join() + ");");
        if (arguments.length < 100) {
            fs[arguments.length] = f;
        }
        return f.apply(this, arguments);
    };
}) ();

Esempio:

Foo.New.apply(null, [a, b, c]) ;

Ovviamente, potresti costruire manualmente le funzioni che Function.prototype.New usa, ma non solo è verboso e goffo, ma (per definizione) deve essere finito. Function consente al codice di funzionare per qualsiasi numero di argomenti.

    
risposta data 14.08.2013 - 20:37
fonte
1

Una mia risposta un po 'diretta da parte mia è stata lo sviluppo di un'area di test API orientata agli sviluppatori. Abbiamo dato un'area di testo su una pagina e un pulsante Esegui. Il punto centrale della pagina era che potessero provare le cose in Javascript contro le nostre API di comunicazione iframe che non erano così facili da fare in un ambiente locale.

Tutto ciò che potrebbe essere stato fatto in quel caso potrebbe anche essere stato fatto dallo sviluppatore che ha aperto gli strumenti F12.

    
risposta data 14.08.2013 - 22:23
fonte
0

Sono d'accordo che dovrebbe essere usato molto raramente, ma ho trovato un caso d'uso potente per eval .

C'è una nuova funzione sperimentale in Firefox chiamata asm.js con cui ho lavorato. Permette di inserire un sottoinsieme limitato della lingua Javascript nel codice nativo. Sì, è molto bello, ma ha dei limiti. Puoi pensare al sottoinsieme limitato di Javascript come un linguaggio simile a C incorporato in Javascript. Non è pensato per essere letto o scritto dagli umani.

Questo sottoinsieme limitato di Javascript non mi consente di iniettare il mio codice generato dal runtime nel codice compilato una volta che è stato compilato.

Ho scritto un codice che consente a un utente di scrivere, in notazione familiare, un'espressione matematica e convertirlo al volo sul codice asm.js. A meno che non volessi avere il codice elaborato sul lato server (cosa che non faccio), eval è l'unico strumento che mi permette di avere il codice risultante elaborato dal browser in tempo reale.

    
risposta data 29.08.2014 - 19:10
fonte
0

Come sottolineato da altri, la cosa più importante quando si lavora con eval è di tenerlo al sicuro. Per questo, si desidera eseguire un controllo approfondito degli argomenti e mantenere semplice il codice eval 'poiché in genere è molto più difficile mantenere e proteggere il codice generato in fase di esecuzione.

Detto questo, mi piace usare eval per due tipi di cose (anche se potrebbero esserci alternative migliori e meno malvagie):

  1. Poiché eval è un modo di "caching del codice esplicitamente", può essere utilizzato per migliorare le prestazioni. Nota che gli ottimizzatori vengono sempre migliorati, ma semplicemente non c'è alcuna garanzia su cosa possono fare per te. Rendendo le cose esplicite nel codice, puoi effettivamente aiutare l'ottimizzatore a prendere decisioni più intelligenti.
  2. Può anche essere usato per fornire forme di base di sicurezza del tipo, così come altre funzionalità linguistiche che mancano a JS, senza peggiorare le prestazioni.

Questo l'approccio iteratore di oggetti precompilato , ad esempio, mostra evidenti benefici in termini di prestazioni quando si utilizza eval per l'iterazione della proprietà dell'oggetto. Mostra anche l'inizio di un potente sistema di tipi in grado di fornire un controllo implicito dei vincoli e molto altro ancora, a un costo minimo o nullo.

Molti sviluppatori esperti di Javascript probabilmente farebbero notare che si tratta di una tana del coniglio, dal momento che, se inizi a scrivere Javascript in questo modo, cambi sostanzialmente il modo in cui usi la lingua. Tuttavia, ciò potrebbe non essere necessariamente una brutta cosa per coloro che amano Javascript ma mancano anche funzionalità linguistiche fondamentali che possono essere raggiunte solo cambiando il modo in cui usiamo il linguaggio stesso.

    
risposta data 09.09.2014 - 12:28
fonte
-3

Ho una situazione in cui eval appare come la strada da percorrere, valutando una stringa e restituendo una variabile esistente il cui nome è uguale alla stringa.

Ho diverse tabelle: table1ResultsTable, table2ResultsTable, tableNResultsTable. Ho variabili impostate con gli stessi nomi, che sono oggetti datatable di jQuery. Li uso per impostare le tabelle e chiamare su di esse funzioni databili jQuery.

Ogni tabella ha class="resultsTable" assegnato. Ora, ho bisogno di ottenere la variabile quando si fa clic sulla tabella. Lo sto facendo:

$('resultsTable).on('click', 'td', function(event) {
    var cResultsTable = eval(event.target.parentElement.parentElement.parentElement.id);
    [etc]
});

Quindi sto ottenendo l'id della tabella in cui è stata fatta clic sulla cella, che ha lo stesso nome della variabile dell'oggetto datatable corrispondente ad essa. Se qualcuno ha un suggerimento per un miglioramento mi piacerebbe saperlo.

    
risposta data 14.08.2013 - 16:46
fonte

Leggi altre domande sui tag