2009-03-19 12 views
22

Se Sto valutando una stringa Python usando eval(), e ho una classe come:Sicurezza di eval di Python() su stringhe non attendibili?

class Foo(object): 
    a = 3 
    def bar(self, x): return x + a 

Quali sono i rischi per la sicurezza, se non mi fido della stringa? In particolare:

  1. È eval(string, {"f": Foo()}, {}) pericoloso? Cioè, puoi raggiungere os o sys o qualcosa di non sicuro da un'istanza di Foo?
  2. È eval(string, {}, {}) pericoloso? Cioè, posso raggiungere os o sys interamente da builtin come len e list?
  3. C'è un modo per rendere i build non presenti affatto nel contesto di valutazione?

Ci sono alcune stringhe non sicure come "[0] * 100000000" Non mi interessa, perché nel peggiore dei casi rallentano/fermano il programma. Sono principalmente preoccupato di proteggere i dati utente esterni al programma.

Ovviamente, eval(string) senza dizionari personalizzati non è sicuro nella maggior parte dei casi.

+0

sì, se c'è sys.dostuff di importazione nella stringa su cui si sta facendo eval e non ci si fida della roba delle stringhe può diventare davvero brutta. – Vasil

+0

eval ha la bella proprietà che consente solo espressioni. Quindi cose come =, import e print non sono permesse. –

+6

Prova 'eval ('__ import __ (" sys "). Stdout.write (" Hello Joe ")')' –

risposta

13

Non è possibile proteggere eval con un approccio blacklist come questo. Vedi Eval really is dangerous per esempi di input che segfault l'interprete CPython, danno accesso a qualsiasi classe che ti piace e così via.

43

eval() consentirà ai dati dannosi di compromettere l'intero sistema, uccidere il gatto, mangiare il cane e fare l'amore con tua moglie.

Recentemente c'è stato un thread su come fare questo genere di cose in modo sicuro sulla lista python-dev, e le conclusioni sono state:

  • E 'davvero difficile farlo correttamente.
  • Richiede patch all'interprete python per bloccare molte classi di attacchi.
  • Non farlo a meno che non lo desideri.

Inizia da qui per leggere la sfida: http://tav.espians.com/a-challenge-to-break-python-security.html

Quale situazione vuoi utilizzare eval() in? Vuoi che un utente sia in grado di eseguire espressioni arbitrarie? O vuoi trasferire i dati in qualche modo? Forse è possibile bloccare l'input in qualche modo.

+2

+1: Chi è la persona malintenzionata che inserisce il codice dannoso che stai eval() - ing? Trova quella persona - sul serio. La maggior parte di "eval è insicura" è un'ipotetica ondata di mano su qualche persona malvagia che nessuno può effettivamente identificare. –

+7

@S. Lott: non è forse una delle idee alla base della sicurezza per * prevenire * che le cose brutte accadano invece di sperare che sia possibile identificare l'aggressore e convincerli a non farlo di nuovo? Perché scoraggiare le buone pratiche? –

+2

Qualsiasi situazione in cui una persona su Internet più grande per scrivere codice non affidabile da eseguire sui propri sistemi richiede che le persone non fidate non siano in grado di attaccare. "Chi è questa persona" - se hai scritto qualcosa di insicuro con eval() e lo sapevo? Sarei io a mostrarti che non avresti dovuto farlo. – Jerub

4

si sono probabilmente meglio girare intorno alla questione:

  1. Che tipo di espressioni Sei voler eval?
  2. Puoi assicurare che solo le stringhe che corrispondono ad una sintassi definita in modo preciso sono eval() d?
  3. Quindi considerare se che è sicuro.

Per esempio, se si vogliono consentire all'utente di inserire un'espressione algebrica per la valutazione, considerare limitandoli a nomi di una lettera di variabili, numeri e una serie specifica di operatori e funzioni. Non utilizzare le stringhe eval() che contengono qualcos'altro.

+0

Oppure, considera questo: trova la persona che continua a inserire codice dannoso nelle tue espressioni eval. Educare quella persona alle conseguenze del proprio comportamento antisociale. Sul serio. Chi sta mettendo il codice nelle espressioni eval? –

+3

@ S.Lott - Se sta scrivendo programmi di crittografia è Carol o Eve, e per la posta elettronica gestisce il suo [email protected] ma non so se abbiamo mai identificato chi è nel caso generale. – MarkusQ

+0

Farei un passo avanti e chiedere * perché * vuoi farlo affatto. –

6

Si noti che anche se si passano dizionari vuoti a eval(), è ancora possibile segfault (C) Python con alcuni trucchi di sintassi.Ad esempio, prova questo sul tuo interprete: eval("()"*8**5)

+0

Puoi pubblicare un esempio di questi trucchi? – phihag

+0

Whoa, perché questo ha causato un segfault? – jacob

+1

Sovrasta lo stack del compilatore. –

9

È possibile ottenere os utilizzando le funzioni incorporate: __import__('os').

Per python 2.6+, il ast module può essere d'aiuto; in particolare ast.literal_eval, anche se dipende esattamente da ciò che si desidera valutare.

2

C'è un ottimo article on the un-safety of eval() nel tutorial di Mark Pilgrim Dive into Python.

Citato da questo articolo:

Alla fine, è possibile in modo sicuro valutare espressioni Python non attendibili, per qualche definizione di “sicuro” che risulta non essere terribilmente utile in reale vita. Va bene se stai solo giocando allo , e va bene se tu, , passi solo input fidati. Ma altro sta solo chiedendo il problema .

+1

Il link non è più valido. – GingerPlusPlus

+0

@GingerPlusPlus: Grazie, sembra che Mark abbia spostato il suo dominio. Ho aggiornato i collegamenti. –