2010-08-18 17 views
30

Chcę w łatwy sposób zrobić "API kalkulatora" w Pythonie.Python: make eval safe

W tej chwili nie obchodzi mnie dokładnie zestaw funkcji obsługiwanych przez kalkulator.

Chcę, aby otrzymał ciąg znaków, powiedzmy "1+1" i zwróć ciąg znaków z wynikiem, w naszym przypadku "2".

Czy istnieje sposób, aby uczynić eval bezpiecznym dla takich rzeczy?

Na początek chciałbym zrobić

env = {} 
env["locals"] = None 
env["globals"] = None 
env["__name__"] = None 
env["__file__"] = None 
env["__builtins__"] = None 

eval(users_str, env) 

tak, że rozmówca nie bałagan z moich lokalnych zmiennych (lub ich zobaczyć).

Ale jestem pewien, że wiele tutaj nadzoruję.

Czy można naprawić problemy związane z bezpieczeństwem eval lub czy istnieje zbyt wiele drobnych szczegółów, aby działało poprawnie?

+0

Zobacz także: http://stackoverflow.com/questions/594266/equation-parsing-in-python – kennytm

+0

Czy może to rozwiązać problem https://github.com/odoo/odoo/blob/d7cfa8c502f27bee5c2fccb35db47b08e3b3804b/odoo/ tools/safe_eval.py – bkmagnetron

Odpowiedz

43

są kwestie bezpieczeństwa eval na poprawieniu lub są tam po prostu zbyt wiele drobnych szczegółów dostać to działa dobrze?

Zdecydowanie ten drugi - sprytny haker zawsze znajdzie sposób obejścia swoich środków ostrożności.

Jeśli nie masz satysfakcji z wyrażeń prostych, używając literałów typu elementarnego, użyj ast.literal_eval - po to jest to! Dla wszystkich bardziej doświadczonych, polecam pakiet parsujący, taki jak ply, jeśli dobrze znasz klasyczne podejście lexx/yacc, lub pyparsing, aby uzyskać jeszcze bardziej podejście Pythoniczne.

+0

Nadal można rozbić' ast.literal_eval': / –

2

Kwestie bezpieczeństwa nie są (nawet blisko) naprawiane.

Chciałbym użyć pyparsing, aby przetworzyć wyrażenie na listę tokenów (nie powinno to być zbyt trudne, ponieważ gramatyka jest prosta), a następnie obsługiwać tokeny indywidualnie.

Możesz także użyć modułu ast do zbudowania Pythona AST (ponieważ używasz poprawnej składni Pythona), ale może to być otwarte na subtelne luki w zabezpieczeniach.

+0

Myślę, że to nie działa, ponieważ ustawiam locals i globals na None, więc nie są one widoczne z wnętrza wyrażenia eval. – flybywire

+0

@flybywire: przeprosiny, to prawda; edytowane. Nadal jest to zły pomysł. – katrielalex

+0

@flybywire: http://stackoverflow.com/questions/661084/security-of-pythons-eval-on-untrusted-strings – katrielalex

7

Możliwe jest uzyskanie dostępu do dowolnej klasy, która została zdefiniowana w procesie, a następnie można utworzyć instancję i wywołać metody na nim. Możliwe jest rozbicie interpretera CPythona lub zakończenie go. Zobacz to: Eval really is dangerous

1

Perl posiada bezpieczny modułu EVAL http://perldoc.perl.org/Safe.html

googlowania "Python odpowiednik Perl Safe" znajdzie http://docs.python.org/2/library/rexec.html

ale Python "ograniczone exec" jest przestarzała.

-

ogólnie rzecz biorąc, "eval" bezpieczeństwa, w dowolnym języku, jest to duży problem. Ataki typu SQL injection są tylko przykładem takiej luki w zabezpieczeniach.Perl Safe ma na przestrzeni lat błędy bezpieczeństwa - ostatni, jaki pamiętam, był bezpieczny, z wyjątkiem destruktorów na obiektach zwróconych z bezpiecznej ewaluacji.

Jest to coś, czego mogę użyć do własnych narzędzi, ale nie ujawnić strony internetowej.

Mam jednak nadzieję, że pewnego dnia w pełni bezpieczne rzeczy będą dostępne w wielu językach.