Perché le caratteristiche simili ad Eval sono considerate malvagie, in contrasto con altre caratteristiche forse dannose?


51

La maggior parte delle lingue moderne (che sono in qualche modo interpretate) hanno una sorta di funzione di valutazione . Tale funzione esegue un codice di linguaggio arbitrario, il più delle volte passato come argomento principale come una stringa (lingue diverse possono aggiungere più funzionalità alla funzione di valutazione).

Comprendo che agli utenti non dovrebbe essere consentito eseguire questa funzione ( modifica, ovvero accettare direttamente o indirettamente input arbitrari da un utente arbitrario a cui passare eval), specialmente con software lato server, poiché potrebbero forzare il processo ad eseguire codice dannoso. In questo modo, tutorial e community ci dicono di non usare eval. Tuttavia, ci sono molte volte in cui eval è utile e utilizzato:

  • Regole di accesso personalizzate agli elementi software (IIRC OpenERP ha un oggetto ir.ruleche può usare il codice python dinamico).
  • Calcoli e / o criteri personalizzati (OpenERP ha campi del genere per consentire calcoli con codice personalizzato).
  • Analizzatori di report OpenERP (sì, lo so che sto andando fuori di testa con roba OpenERP ... ma è l'esempio principale che ho).
  • Effetti degli incantesimi di codifica in alcuni giochi di ruolo.

Quindi hanno un buon uso, purché siano usati correttamente. Il vantaggio principale è che la funzione consente agli amministratori di scrivere codice personalizzato senza dover creare più file e includerli (anche se la maggior parte dei framework che utilizzano le funzionalità eval hanno anche un modo per specificare un file, un modulo, un pacchetto, ... da cui leggere).

Tuttavia, eval è malvagio nella cultura popolare. Mi viene in mente roba come irrompere nel tuo sistema.

Tuttavia, ci sono altre funzioni che potrebbero essere dannose se in qualche modo gli utenti accedessero: scollegamento, lettura, scrittura (semantica dei file), allocazione della memoria e aritmetica dei puntatori, accesso al modello di database (anche se non si considerano casi iniettabili SQL).

Quindi, fondamentalmente, il più delle volte quando un codice non è scritto correttamente o non è visto correttamente (risorse, utenti, ambienti, ...), il codice è malvagio e può portare anche a un impatto economico.

Ma c'è qualcosa di speciale con le evalfunzioni (indipendentemente dalla lingua).

Domanda : c'è qualche fatto storico per cui questa paura diventa parte della cultura popolare, invece di prestare la stessa attenzione alle altre caratteristiche forse pericolose?


11
Non sono d'accordo sul fatto che ciò sia troppo ampio e, come prova, presento le quattro risposte che hanno una lunghezza ragionevole.

12
Hanno votato per chiudere come troppo ampio ? (Non riesco ancora a vedere voti ravvicinati in questa community) Quella ragione stretta sta diventando una ragione jolly senza alcun significato ultimamente. Specialmente quando il punto che chiedo è abbastanza chiaro con esempi e un punto specifico da chiedere. Chiederò questo argomento in Meta ...
Luis Masuelli il

13
Perché diventa parte della cultura popolare, con più attenzione rispetto ad altre caratteristiche pericolose? Perché l'allitterazione eval - il male è facile da ricordare
Bergi

5
L'allocazione della memoria e l'aritmetica del puntatore sono viste come malvagie da molti.
user253751

5
Va notato che OpenERP (ora Odoo) non si limita a chiamare eval, ma ha una funzione interna chiamata safe_evalche prepara l'ambiente per impedire al codice di fare cose pericolose. Sono stati rilevati bug, poiché Python è un linguaggio abbastanza flessibile e quindi difficile da controllare.
André Paramés

Risposte:


76

Una evalfunzione di per sé non è cattiva, e c'è un punto sottile che non credo che tu stia facendo:

Consentire a un programma di eseguire input dell'utente arbitrario non è valido

Ho scritto un codice che utilizzava un evaltipo di funzione ed era sicuro: il programma e i parametri erano codificati. A volte, non esiste alcuna funzione di lingua o libreria per fare ciò di cui il programma ha bisogno ed eseguire un comando shell è il percorso breve. "Devo finire di scrivere questo codice in poche ore, ma scrivere Java / .NET / PHP / qualunque codice impiegherà due giorni. O posso evalfarlo in cinque minuti."

Una volta che si consente agli utenti di eseguire tutto ciò che vogliono, anche se bloccato dal privilegio dell'utente o dietro una schermata "sicura", si creano vettori di attacco. Ogni settimana, alcuni CMS casuali, software di blog, ecc. Presentano una falla di sicurezza in cui un utente malintenzionato può sfruttare una falla come questa. Ti stai affidando all'intero stack software per proteggere l'accesso a una funzione che può essere utilizzata rm -rf /o qualcos'altro catastrofica (nota: è improbabile che quel comando abbia successo, ma fallirà dopo aver causato un po 'di danno).

Esiste un fatto storico per cui questa paura diventa parte della cultura popolare, invece di porre la stessa attenzione alle altre caratteristiche forse pericolose?

Sì, esiste un precedente storico. A causa dei numerosi bug che sono stati corretti nel corso degli anni in vari software che consentono agli autori degli attacchi remoti di eseguire codice arbitrario, l'idea di evalessere in gran parte sfuggita al favore. I linguaggi e le biblioteche moderne hanno un ricco set di funzionalità che rendono evalmeno importante, e questo non è un caso. Entrambi rendono le funzioni più facili da usare e riducono il rischio di un exploit.

C'è stata molta attenzione a molte funzionalità potenzialmente insicure nelle lingue popolari. Se uno riceve più attenzione è principalmente una questione di opinione, ma le evalfunzionalità hanno certamente un problema di sicurezza dimostrabile che è facile da capire. Da un lato, consentono l'esecuzione di comandi del sistema operativo inclusi gli incorporamenti della shell e programmi esterni standard (ad es. rmO del). Due, in combinazione con altri exploit, un utente malintenzionato potrebbe essere in grado di caricare il proprio eseguibile o script di shell, quindi eseguirlo tramite il proprio software, aprendo la porta a qualsiasi cosa accada (niente di buono).

Questo è un problema difficile Il software è complesso e uno stack software (ad es. LAMP ) è costituito da più parti di software che interagiscono tra loro in modi complessi. Fai attenzione a come usi le funzionalità del linguaggio come questa e non consentire mai agli utenti di eseguire comandi arbitrari.


2
Tu sei quello :). Sebbene se c'è un buon esempio ben noto che ha contribuito a questa cultura, mi piacerebbe vederlo nella risposta.
Luis Masuelli,

5
Non sono a conoscenza di alcun singolo esempio, credo che si tratti di più "morte per mille tagli" con molti piccoli esempi di exploit utilizzati e rattoppati. Non sto esagerando quando dico che alcuni exploit remoti vengono aggiornati settimanalmente in alcuni software.

1
Il mio IDE è un programma che mi consente - è l'utente - di eseguire input arbitrari. Lo trovo utile piuttosto che cattivo.
Den

3
@Den sarebbe un'eccezione. Essendo un IDE, sono sicuro che potresti causare caos senza quell'abilità. Scrivilo nel tuo codice sorgente. Inoltre, hai già pieno accesso al computer su cui è in esecuzione. L'implicazione qui è che si evalpossono elevare i privilegi. che non è un problema se sono già elevati.

3
@Den: è quello che Raymond Chen ha riassunto come "l'altro lato della camera di equilibrio". Puoi già eseguire rm -rf /, non è necessario farlo in modo complicato tramite un IDE. Il problema evalè che apre quella capacità a molti attori che non dovrebbero avere quella capacità.
Salterio

38

Parte di ciò è semplicemente che la sfumatura è difficile. È facile dire cose come non usare mai goto, campi pubblici, interpolazione di stringhe per query sql o eval. Queste affermazioni non dovrebbero davvero essere intese nel senso che non c'è mai, in nessun caso, un motivo per usarle. Ma evitarli come regola generale è una buona idea.

Eval è fortemente scoraggiato perché combina diversi problemi comuni.

Innanzitutto, è suscettibile agli attacchi di iniezione. Qui è come l'iniezione SQL in quanto quando i dati controllati dall'utente vengono inseriti nel codice, è facile consentire l'inserimento accidentale di codice arbitrario.

In secondo luogo, i principianti tendono a usare eval per aggirare il codice mal strutturato. Un programmatore principiante potrebbe scrivere un codice simile a:

x0 = "hello"
x1 = "world"
x2 = "how"
x3 = "are"
x4 = "you?"
for index in range(5):
   print eval("x" + index)

Funziona, ma è davvero il modo sbagliato di risolvere questo problema. Ovviamente, usare un elenco sarebbe molto meglio.

In terzo luogo, eval è in genere inefficiente. Ci si impegna molto per accelerare le implementazioni del nostro linguaggio di programmazione. Ma eval è difficile da accelerare e l'utilizzo in genere avrà effetti dannosi sulle prestazioni.

Quindi, eval non è male. Potremmo dire che eval è malvagio, perché beh, è ​​un modo accattivante per dirlo. Qualsiasi programmatore principiante dovrebbe stare lontano da eval perché qualunque cosa vogliano fare, eval è quasi sicuramente la soluzione sbagliata. Per alcuni casi d'uso avanzati, eval ha senso e dovresti usarlo, ma ovviamente fai attenzione alle insidie.


13
Il tuo secondo caso è molto importante. Nelle lingue che hanno eval ma che sono anche compilate, valutare una stringa per produrre un riferimento variabile non è banale. Ad esempio, se var x = 3; print(x)viene compilato , non è necessario che ci sia alcuna conoscenza di runtime che l' origine abbia usato il nome "x". Per var x = 3; print(eval("x"))funzionare, è necessario registrare tale mappatura. Questo è un vero problema: in Common Lisp (let ((x 3)) (print (eval 'x)))genererà un'eccezione variabile non associata perché la variabile lessicale x non ha alcuna connessione con il nome dopo che il codice è stato compilato.
Joshua Taylor,

@JohnuaTaylor Intendi la terza ragione, non la seconda?
user253751

1
@immibis, penso che si stia riferendo al codice nel secondo motivo. Ma hai ragione, è proprio in relazione al terzo motivo: le prestazioni.
Winston Ewert,

Hai visto questa domanda , vero? ;)
jpmc26

@ jpmc26, no. Ma ne ho visti molti simili.
Winston Ewert

20

Ciò che si riduce è che "l'esecuzione di codice arbitrario" è un discorso tecnico per "essere in grado di fare qualsiasi cosa". Se qualcuno è in grado di sfruttare l'esecuzione di codice arbitrario nel tuo codice, questa è letteralmente la peggiore vulnerabilità di sicurezza possibile, perché significa che sono in grado di fare tutto ciò che è possibile fare per il tuo sistema.

"Altri bug potenzialmente dannosi" potrebbero avere dei limiti, il che significa che, per definizione, sono in grado di nuocere meno di un'esecuzione arbitraria di codice.


2
Per motivi di argomento, l'uso improprio dei puntatori porta anche all'esecuzione di codice arbitrario , ma i puntatori sono disapprovati molto meno di quanto non evalsia.
Dmitry Grigoryev

12
@DmitryGrigoryev Lo sono davvero? Al di fuori del C ++, i puntatori sono generalmente considerati estremamente pericolosi ed evitati. C # supporta i puntatori, ad esempio, ma tende ad essere l'ultima cosa che provi dopo aver esaurito tutte le altre opzioni (di solito, per motivi di prestazioni sulla manipolazione dei dati). La maggior parte delle lingue moderne non supporta i puntatori. Anche lo stesso C ++ si sta muovendo verso puntatori "più sicuri" che tentano di alleviare i problemi con puntatori arbitrari (ad es. Usando liste / matrici reali anziché solo puntatori, usando safe_ptr, passaggio di riferimento ...).
Luaan

2
@DmitryGrigoryev: puoi fornire un riferimento a chiunque affermi che i puntatori sono meno pericolosi di valutazione?
Jacques

2
@JacquesB ecco qua :)
Dmitry Grigoryev

1
@JacquesB, sì; era inteso come uno scherzo (mi aspettavo che il sorriso lo chiarisse abbastanza). L'OP ha fatto quella dichiarazione, non io, quindi dovresti chiedergli una prova.
Dmitry Grigoryev

15

C'è una ragione pratica e una teorica.

Il motivo pratico è che lo osserviamo spesso causa problemi. È raro che eval si traduca in una buona soluzione, e spesso si traduce in una cattiva soluzione in cui avresti avuto una migliore alla fine se avessi fatto finta che Eval non esistesse e avessi affrontato il problema in modo diverso. Quindi il consiglio semplificato è di ignorarlo, e se ti viene in mente un caso in cui vuoi ignorare il consiglio semplificato, beh, speriamo che tu abbia pensato a sufficienza per capire perché il consiglio semplificato non è applicabile e il comune le insidie ​​non ti influenzeranno.

La ragione più teorica è che se è difficile scrivere un buon codice, è ancora più difficile scrivere un codice che scriva un buon codice. Sia che tu stia utilizzando eval o che generi istruzioni SQL incollando stringhe o scrivendo un compilatore JIT, ciò che stai tentando è spesso più difficile di quanto ti aspetti. Il potenziale per l'iniezione di codice dannoso è una grande parte del problema, ma a parte questo è generalmente più difficile sapere che il codice è corretto se il codice non esiste nemmeno fino al runtime. Quindi il consiglio semplificato è di semplificare le cose: "usa query SQL con parametri", "non usare eval".

Prendendo l'esempio degli effetti degli incantesimi: una cosa è costruire un compilatore o interprete Lua (o qualunque altra cosa) nel tuo gioco per consentire ai progettisti di giochi un linguaggio più semplice del C ++ (o qualunque altra cosa) per descrivere gli effetti degli incantesimi. La maggior parte dei "problemi di eval" non si applica se tutto ciò che stai facendo è valutare il codice che è stato scritto e testato e incluso nel gioco o in DLC o what-have-you. Questo è solo mescolando le lingue. I grandi problemi ti colpiscono quando provi a generare Lua (o C ++, o SQL, o comandi shell, o qualsiasi altra cosa) al volo, e rovinalo.


1
Naturalmente, la generazione del codice di runtime può essere eseguita correttamente ed eval può essere utile. Ad esempio, uso spesso eval per metaprogrammi / cose simili a macro, specialmente quando voglio più prestazioni di quelle che un OOP "più pulito" o una soluzione funzionale potrebbero fornire. Il codice risultante è spesso migliore e più semplice perché ha meno boilerplate. Tuttavia, essere consapevoli di vari problemi relativi al sandboxing, ai meccanismi di escape, all'iniezione di codice, alle regole di scoping, alla segnalazione degli errori, all'ottimizzazione ecc. Richiede un livello non banale di competenza nella lingua ed eval è positivamente pericoloso senza quella conoscenza.
amon

11

No, non esiste un fatto storico ovvio.

I mali di Eval sono evidenti sin dall'inizio. Altre caratteristiche sono leggermente pericolose. Le persone possono eliminare i dati. Le persone possono vedere i dati che non dovrebbero. Le persone possono scrivere dati che non dovrebbero. E possono fare la maggior parte di queste cose solo se in qualche modo rovini e non convalidi l'input dell'utente.

Con eval, possono hackerare il pentagono e far sembrare che tu l'abbia fatto. Possono controllare i tasti premuti per ottenere le password. Supponendo un linguaggio completo Turing, possono letteralmente fare tutto ciò che il tuo computer è in grado di fare.

E non è possibile convalidare l'input. È una stringa di forma libera arbitraria. L'unico modo per convalidarlo sarebbe costruire un parser e un motore di analisi del codice per la lingua in questione. Buona fortuna con quello.


1
... o avere l'input proveniente da una fonte attendibile, come i file di definizione dell'incantesimo per un gioco.
user253751

3
@immibis ma se l'ingresso è predefinito e testato sicuro perché usare eval quando potrebbe essere incluso nella fonte del sistema?
Jules

3
@immibis - perché nessuno ha mai
hackerato i

2
... questo non significa "Turing complete" (la completezza di Turing è a un passo dall'informatica irrilevante al mondo reale).
Leushenko,

1
@Telastyn: cosa che un programma Javascript non può fare. O anche un programma C ++. Javascript funziona all'interno di un sandbox (browser) che è esso stesso in un altro sandbox (l'anello 3 in x86 parla). Il vettore di interruzione è esterno a quel sandbox, sotto il controllo del sistema operativo. E quel sandbox esterno, l'anello 3, è imposto dalla CPU.
Salterio

6

Penso che si riduce ai seguenti aspetti:

  • Necessità
  • (Custodito) Utilizzo
  • Accesso
  • verificabilità
  • Attacchi a più stadi

Necessità

Ciao, ho scritto questo strumento di modifica delle immagini estremamente interessante (disponibile per $ 0,02). Dopo aver aperto l'immagine, è possibile passare una moltitudine di filtri sull'immagine. Puoi anche scriverne alcuni tu stesso usando Python (il programma in cui ho scritto l'applicazione). Userò solo evalil tuo contributo, confidando che tu sia un utente rispettabile.

(dopo)

Grazie per averlo acquistato. Come puoi vedere funziona esattamente come ti avevo promesso. Oh, vuoi aprire un'immagine? No, non puoi. Non userò il readmetodo perché è alquanto insicuro. Salvataggio? No, non userò write.

Quello che sto cercando di dire è: hai bisogno di leggere / scrivere per quasi gli strumenti di base. Lo stesso per la memorizzazione dei punteggi più alti del tuo gioco davvero fantastico.

Senza lettura / scrittura, l'editor di immagini è inutile. Senza eval? Ti scriverò un plugin personalizzato per questo!

(Custodito) Utilizzo

Molti metodi possono essere potenzialmente pericolosi. Ad esempio il reade write. Un esempio comune è un servizio Web che consente di leggere immagini da una directory specifica specificando il nome. Tuttavia, il 'nome' può in effetti essere qualsiasi percorso (relativo) valido sul sistema, che consente di leggere tutti i file a cui il servizio Web ha accesso, non solo le immagini. Abusare di questo semplice esempio si chiama "percorso trasversale". Se la tua app consente l'attraversamento del percorso, è un problema. A readsenza difendersi contro per l'attraversamento del sentiero può essere definito malvagio.

Tuttavia, in altri casi, la stringa per readè completamente sotto il controllo dei programmatori (forse hardcoded?). In tal caso, non è affatto male da usare read.

Accesso

Ora, un altro semplice esempio, usando eval.

Da qualche parte nella tua app web, vuoi dei contenuti dinamici. Consentirai agli amministratori di inserire un codice eseguibile. Dato che gli amministratori sono utenti fidati, in teoria questo può essere ok. Assicurati di non eseguire il codice inviato da non amministratori e stai bene.

(Cioè, fino a quando non hai licenziato quel simpatico amministratore ma hai dimenticato di revocare il suo accesso. Ora la tua app web è stata spazzata via).

Verificabilità.

Un altro aspetto importante, penso, è quanto sia facile verificare l'input dell'utente.

Usando l'input dell'utente in una chiamata letta? Assicurati (molto) che l'input per la chiamata in lettura non contenga nulla di dannoso. Normalizza il percorso e verifica che il file aperto sia nella directory multimediale. Questo è sicuro.

Input dell'utente su una chiamata di scrittura? Stesso!

SQL Injection? Basta scappare o utilizzare query parametrizzate e sei al sicuro.

Eval? Come hai intenzione di verificare l'input utilizzato per la evalchiamata? Puoi lavorare molto duramente, ma è davvero difficile (se non impossibile) farlo funzionare in sicurezza.

Attacchi a più stadi

Ora, ogni volta che si utilizza l'input dell'utente, è necessario valutare i vantaggi del suo utilizzo, rispetto ai pericoli. Proteggi il suo utilizzo il più possibile.

Considera di nuovo le evalcose utili nell'esempio admin. Ti ho detto che era un po 'ok.

Ora, considera che in realtà c'è un posto nella tua app web in cui hai dimenticato di sfuggire al contenuto dell'utente (HTML, XSS). Questa è un'offesa minore rispetto alla valutazione accessibile all'utente. Tuttavia, utilizzando il contenuto utente senza escape, un utente può assumere il browser Web di un amministratore e aggiungere un evalBLOB in grado attraverso la sessione di amministratori, consentendo nuovamente l'accesso completo al sistema.

(Lo stesso attacco in più fasi può essere eseguito con l'iniezione SQL anziché XSS, oppure alcune scritture di file arbitrarie sostituiscono il codice eseguibile anziché utilizzare eval)


2
"Puoi lavorare molto duramente, ma è davvero difficile (se non impossibile) farlo funzionare in sicurezza." - Si è impossibile. Prova semplice: invece di cercare di capire se il codice che l'utente fornito è "sicuro", solo cercare di capire qualcosa di molto, molto più semplice, e vedere quanto sia difficile che è già: fa il codice fornito da l'arresto utente?
Jörg W Mittag,

2
@ JörgWMittag: dammi un programma scritto in Coq e lo dimostrerò.
André Paramés

1
@ JörgWMittag: concordato. A seconda della lingua e dell'ambito dell'input dell'utente. Potrebbe anche essere eval("hard coded string" + user_input_which_should_be_alphanumeric + "remainder"). È possibile verificare che l'ingresso sia alfanumerico. Inoltre, "ferma" è ortogonale a "modifica / accede allo stato che non deve toccare" e "utilizza metodi che non dovrebbe chiamare".
Sjoerd Job Postmus

3
@ JörgWMittag È impossibile dimostrare che un determinato programma non farà qualcosa, ma non è impossibile definire in modo conservativo un insieme ristretto di programmi per i quali è possibile provarlo e imporre che i programmi di input siano membri di quel set.
user253751

3

Affinché questa funzione funzioni, significa che devo mantenere un livello di riflessione che consenta il pieno accesso all'intero stato interno del programma.

Per i linguaggi interpretati, posso semplicemente usare lo stato dell'interprete, che è semplice, ma in combinazione con i compilatori JIT aumenta ancora significativamente la complessità.

Senza eval, il compilatore JIT può spesso dimostrare che i dati locali di un thread non sono accessibili da nessun altro codice, quindi è perfettamente accettabile riordinare gli accessi, omettere i blocchi e memorizzare nella cache i dati utilizzati più spesso per periodi più lunghi. Quando un altro thread esegue evalun'istruzione, potrebbe essere necessario sincronizzare il codice compilato JIT in esecuzione con quello, quindi all'improvviso il codice generato da JIT necessita di un meccanismo di fallback che ritorni all'esecuzione non ottimizzata entro un intervallo di tempo ragionevole.

Questo tipo di codice tende ad avere molti bug sottili, difficili da riprodurre e allo stesso tempo pone un limite all'ottimizzazione nel compilatore JIT.

Per i linguaggi compilati, il compromesso è ancora peggio: la maggior parte delle ottimizzazioni sono vietate e ho bisogno di mantenere informazioni dettagliate sui simboli e un interprete in giro, quindi la flessibilità aggiuntiva in genere non ne vale la pena - spesso è più facile definire un'interfaccia per alcuni interni strutture, ad esempio fornendo una vista di scripting e un controller di accesso simultaneo al modello del programma .


"Affinché questa funzione funzioni, significa che devo mantenere un livello di riflessione che consenta il pieno accesso allo stato interno dell'intero programma" - no, solo alle parti che si desidera influenzare. Nel caso di OpenERP / Odoo, il codice che viene valutato ha accesso solo a un numero molto limitato di variabili e funzioni che può chiamare e sono tutti thread-local.
André Paramés

1

Respingo la premessa che evalè considerata più malvagia dell'aritmetica del puntatore o più pericolosa dell'accesso diretto alla memoria e al file system. Non conosco nessuno sviluppatore ragionevole che potrebbe crederci. Inoltre, i linguaggi che supportano l'accesso aritmetico / diretto alla memoria del puntatore in genere non supportano evale viceversa, quindi sono sicuro di quanto spesso un simile confronto sarebbe persino rilevante.

Ma evalpotrebbe essere una vulnerabilità più nota , per la semplice ragione che è supportata da JavaScript. JavaScript è un linguaggio sandbox senza accesso diretto alla memoria o al file system, quindi semplicemente non ha queste vulnerabilità che impediscono i punti deboli nell'implementazione del linguaggio stesso. Evalè quindi una delle caratteristiche più pericolose del linguaggio, poiché apre la possibilità di esecuzione di codice arbitrario. Credo che molti più sviluppatori sviluppino in JavaScript che in C / C ++, quindi evalè semplicemente più importante essere consapevoli degli overflow del buffer per la maggior parte degli sviluppatori.


0

Nessun programmatore serio considererebbe Eval "malvagio". È semplicemente uno strumento di programmazione, come qualsiasi altro. La paura (se c'è paura) di questa funzione non ha nulla a che fare con la cultura popolare. È semplicemente un comando pericoloso che viene spesso utilizzato in modo improprio e può introdurre gravi falle nella sicurezza e ridurre le prestazioni. Per esperienza personale direi che è raro incontrare un problema di programmazione che non può essere risolto in modo più sicuro ed efficiente con altri mezzi. I programmatori che hanno maggiori probabilità di usare eval sono quelli che sono probabilmente i meno qualificati per farlo in sicurezza.

Detto questo, ci sono lingue in cui l'uso di eval è appropriato. Mi viene in mente Perl. Tuttavia, personalmente trovo che sia molto raramente necessario in altre lingue più moderne, che supportano nativamente la gestione strutturata delle eccezioni.


questo non tenta nemmeno di rispondere alla domanda posta: "Esiste un fatto storico per far diventare questa paura parte della cultura popolare"? Vedi Come rispondere
moscerino

La domanda, secondo me, si basa su una premessa errata, quindi ho risposto come tale.
user1751825

0

Penso che lo coprirai abbastanza bene nella parte seguente della tua domanda (enfasi sulla mia):

hanno un buon uso, purché siano usati correttamente

Per il 95% che potrebbe usarlo correttamente va tutto bene; ma ci saranno sempre persone che non lo usano correttamente. Alcuni di questi saranno dovuti all'inesperienza e alla mancanza di abilità, il resto sarà dannoso.

Ci saranno sempre persone che vogliono oltrepassare i limiti e trovare falle nella sicurezza, alcune nel bene e altre nel male.

Per quanto riguarda l'aspetto storico dei fatti, le evalfunzioni di tipo consentono essenzialmente l' esecuzione di codice arbitrario che è stata precedentemente sfruttata nel popolare CMS Web, Joomla! . Con Joomla! alimentando oltre 2,5 milioni di siti in tutto il mondo , questo è un sacco di potenziali danni non solo ai visitatori di quei siti, ma potenzialmente all'infrastruttura su cui è ospitato e anche alla reputazione dei siti / aziende che sono stati sfruttati.

The Joomla! l'esempio potrebbe essere semplice, ma è stato registrato.


0

Ci sono alcuni buoni motivi per scoraggiare l'uso di eval(anche se alcuni sono specifici di alcune lingue).

  • L'ambiente (lessicale e dinamico) utilizzato da evalè spesso sorprendente (vale a dire, pensi che eval(something here)dovrebbe fare una cosa, ma fa un'altra, scatenando possibilmente eccezioni)
  • Esiste spesso un modo migliore per ottenere lo stesso risultato (la concatenazione di chiusure lessicali costruite è talvolta una soluzione migliore, ma potrebbe benissimo essere specifica di Lisp comune)
  • È fin troppo facile finire con la valutazione di dati non sicuri (anche se questo può essere per lo più protetto).

Personalmente, non andrei fino al punto di dire che è malvagio, ma sfiderò sempre l'uso di evaluna revisione del codice, con le parole sulla falsariga di "hai considerato del codice qui ?" (se ho tempo di fare almeno una sostituzione provvisoria) o "sei sicuro che una valutazione sia davvero la migliore soluzione qui?" (se non lo faccio).


questo non tenta nemmeno di rispondere alla domanda posta: "Esiste un fatto storico per far diventare questa paura parte della cultura popolare"? Vedi Come rispondere
moscerino

0

In Minsky's Society of Mind , capitolo 6.4, afferma

C'è un modo per una mente di guardare se stessa e tenere traccia di ciò che sta accadendo. Dividi il cervello in due parti, A e B. Collega gli input e gli output del cervello A al mondo reale, in modo che possa percepire cosa succede lì. Ma non collegare affatto il cervello B al mondo esterno; invece collegalo in modo che il cervello A sia il mondo del cervello B!

Quando un programma (B) scrive un altro programma (A) funziona come un meta-programma. L'oggetto di B è il programma A.

C'è un programma C. Questo è quello nella tua testa che scrive il programma B.

Il pericolo è che ci possa essere qualcuno (C ') con intenzioni malvagie, che può interferire in questo processo, in modo da ottenere cose come SQL-injection.

La sfida è rendere il software più intelligente senza renderlo anche più pericoloso.


Due voti positivi e due voti negativi. Sembra che forse questo colpisce un nervo.
Mike Dunlavey,

0

Hai molte buone risposte qui e il motivo principale è chiaramente che l'esecuzione di codice arbitrario non è buona mmmkay ma aggiungerò un altro fattore che altri hanno toccato solo al limite di:

È davvero difficile risolvere il codice che viene valutato da una stringa di testo. I tuoi normali strumenti di debug sono praticamente usciti dalla finestra e sei ridotto a traccia o eco della vecchia scuola. Ovviamente non importa molto se hai un frammento in una riga che desideri, evalma come programmatore esperto puoi probabilmente trovare una soluzione migliore per questo, mentre la generazione di codice su larga scala potrebbe essere da qualche parte che una funzione di valutazione diventa un alleato potenzialmente utile.

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.