Funkcja f()
wykorzystuje eval()
(lub coś równie niebezpiecznego) z danymi, które utworzyłem i zapisałem local_file
na komputerze z uruchomionym programem:
import local_file
def f(str_to_eval):
# code....
# ....
eval(str_to_eval)
# ....
# ....
return None
a = f(local_file.some_str)
f()
jest bezpieczny do uruchomienia, ponieważ ciągi, które mu dostarczam, są moje.
Jeśli jednak kiedykolwiek zdecyduję się użyć go do czegoś niebezpiecznego (np. Dane wprowadzone przez użytkownika), sprawy mogą się potoczyć bardzo źle . Ponadto, jeśli local_file
przestanie być lokalny, stworzy to lukę, ponieważ musiałbym zaufać maszynie, która również udostępnia ten plik.
Jak mam się upewnić, że nigdy nie „zapomnę”, że korzystanie z tej funkcji jest niebezpieczne (chyba że zostaną spełnione określone kryteria)?
Uwaga: eval()
jest niebezpieczny i zwykle można go zastąpić czymś bezpiecznym.
python
vulnerabilities
Paradoks Fermiego
źródło
źródło
Odpowiedzi:
Zdefiniuj typ ozdabiania „bezpiecznych” wejść. W swojej funkcji sprawdź
f()
, czy argument ma ten typ, lub wyrzuć błąd. Bądź wystarczająco inteligentny, aby nigdy nie definiować skrótudef g(x): return f(SafeInput(x))
.Przykład:
Chociaż można to łatwo obejść, utrudnia to przypadkowo. Ludzie mogą krytykować taką drakońską kontrolę typu, ale nie rozumieją o co chodzi. Ponieważ
SafeInput
typ jest tylko typem danych, a nie klasą obiektową, którą można podklasować, sprawdzanie tożsamości typu za pomocątype(x) is SafeInput
jest bezpieczniejsze niż sprawdzanie zgodności z typemisinstance(x, SafeInput)
. Ponieważ chcemy wymusić określony typ, ignorowanie typu jawnego i samo pisanie niejawnego kaczego tekstu również tutaj nie jest satysfakcjonujące. Python ma system typów, więc użyjmy go, aby wyłapać ewentualne błędy!źródło
assert
jest usuwany automatycznie, ponieważ będę korzystał ze zoptymalizowanego kodu python.if ... : raise NotSafeInputError
Potrzebne byłoby coś takiego .eval()
na metodęSafeInput
, aby nie było potrzeby jawnego sprawdzania typu. Nadaj metodzie nazwę, która nie jest używana w żadnej z innych klas. W ten sposób nadal możesz wyśmiewać to wszystko do celów testowych.eval
ma dostęp do zmiennych lokalnych, być może kod zależy od tego, jak mutuje zmienne. Przenosząc eval do innej metody, nie będzie on już mógł mutować zmiennych lokalnych.SafeInput
konstruktora nazwy / uchwytu pliku lokalnego i wykonanie samego odczytu, upewniając się, że dane rzeczywiście pochodzą z pliku lokalnego.Jak kiedyś zauważył Joel, spraw, aby zły kod wyglądał źle (przewiń w dół do sekcji „Prawdziwe rozwiązanie” lub lepiej przeczytaj go całkowicie; warto, nawet jeśli adresuje zmienną zamiast nazw funkcji). Dlatego pokornie sugeruję zmienić nazwę funkcji na coś w stylu
f_unsafe_for_external_use()
- najprawdopodobniej sam wymyślisz jakiś schemat skrótów.Edycja: Myślę, że sugestia Amona jest bardzo dobrą, opartą na OO odmianą tego samego tematu :-)
źródło
Uzupełniając sugestię @amon, możesz również pomyśleć o połączeniu wzorca strategii tutaj, a także wzorca obiektu metody.
A potem „normalna” implementacja
I implementacja admin-input-eval
(Uwaga: na przykładzie z prawdziwego świata mógłbym dać lepszy przykład).
źródło