Sicurezza di Python's eval () su stringhe non attendibili?
Domanda
Se sto valutando una stringa Python usando eval (), e ho una classe come:
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:
-
eval(string, {"f": Foo()}, {})
non è sicuro? Cioè, puoi raggiungere os o sys o qualcosa di non sicuro da un'istanza di Foo? -
eval(string, {}, {})
non è sicuro? Cioè, posso raggiungere os o sys interamente da builtin come len e list? - C'è un modo per rendere i builtin non presenti affatto nel contesto eval?
Esistono stringhe non sicure come " [0] * 100000000 " Non mi interessa, perché nel peggiore dei casi rallentano / fermano il programma. Sono principalmente preoccupato per la protezione dei dati degli utenti esterni al programma.
Ovviamente, eval(string)
senza dizionari personalizzati non è sicuro nella maggior parte dei casi.
Soluzione
Non puoi proteggere eval con un approccio in blacklist come questo. Vedi Eval è davvero pericoloso per esempi di input che segfaultano l'interprete CPython, danno accesso a qualsiasi classe ti piaccia, e così via.
Altri suggerimenti
eval()
consentirà ai dati dannosi di compromettere l'intero sistema, uccidere il tuo gatto, mangiare il tuo cane e fare l'amore con tua moglie.
Di recente c'è stato un thread su come fare questo genere di cose in modo sicuro nell'elenco di Python-Dev, e le conclusioni sono state:
- È davvero difficile farlo correttamente.
- Richiede patch all'interprete Python per bloccare molte classi di attacchi.
- Non farlo a meno che tu non voglia davvero.
Inizia qui per leggere la sfida: http: // tav.espians.com/a-challenge-to-break-python-security.html
In quale situazione vuoi usare eval ()? 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.
Puoi accedere a os
usando le funzioni integrate: __import__('os')
.
Per python 2.6+, il ast module può aiutare; in particolare ast.literal_eval
, anche se dipende esattamente da cosa vuoi valutare.
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)
Probabilmente starai meglio girando la domanda:
- Che tipo di espressioni vuoi valutare?
- Puoi assicurarti che solo le stringhe che corrispondono ad una sintassi definita in modo stretto siano eval () d?
- Quindi considera se quello è sicuro.
Ad esempio, se si desidera consentire all'utente di immettere un'espressione algebrica per la valutazione, prendere in considerazione la possibilità di limitarli a nomi di variabili di una lettera, numeri e un set specifico di operatori e funzioni. Non eval () stringhe contenenti altro.
Esiste un ottimo articolo sulla non sicurezza di eval()
nel Dive into Python di Mark Pilgrim.
Citato da questo articolo:
Alla fine, è possibile in sicurezza valutare espressioni Python non attendibili, per qualche definizione di & # 8220; sicuro & # 8221; quello risulta non essere terribilmente utile in vita reale. & # 8217; va bene se & # 8217; sei giusto giocando, ed è & # 8217; va bene se tu trasmetti sempre solo input affidabili. Ma qualsiasi altra cosa sta solo chiedendo guai.