Dlaczego cechy podobne do ewaluacji są uważane za złe, w przeciwieństwie do innych potencjalnie szkodliwych cech?

51

Większość współczesnych języków (które są w jakiś sposób interpretowane) pełni funkcję ewaluacji . Taka funkcja wykonuje dowolny kod języka, przez większość czasu jako główny argument jako ciąg znaków (różne języki mogą dodawać więcej funkcji do funkcji eval).

Rozumiem, że użytkownikom nie powinno się zezwalać na wykonywanie tej funkcji ( edycja, tj. Pobieranie bezpośrednio lub pośrednio dowolnych danych wejściowych od dowolnego użytkownika do przekazania eval), szczególnie w przypadku oprogramowania po stronie serwera, ponieważ mogą zmusić proces do wykonania złośliwego kodu. W ten sposób samouczki i społeczności mówią nam, aby nie używać eval. Jednak wiele razy eval jest użyteczny i używany:

  • Niestandardowe reguły dostępu do elementów oprogramowania (IIRC OpenERP ma obiekt, ir.rulektóry może używać dynamicznego kodu python).
  • Niestandardowe obliczenia i / lub kryteria (OpenERP ma takie pola, aby umożliwić niestandardowe obliczenia kodu).
  • Parsery raportów OpenERP (tak, wiem, że wariuję cię materiałami OpenERP ... ale to jest mój główny przykład).
  • Kodowanie efektów zaklęć w niektórych grach RPG.

Więc mają dobre zastosowanie, o ile są właściwie używane. Główną zaletą jest to, że ta funkcja pozwala administratorom pisać niestandardowy kod bez konieczności tworzenia większej liczby plików i dołączania ich (chociaż większość frameworków korzystających z funkcji eval ma również sposób na określenie pliku, modułu, pakietu, ... do odczytu).

Jednak ewolucja jest złem w kulturze popularnej. Przychodzą mi na myśl rzeczy takie jak włamanie się do twojego systemu.

Istnieją jednak inne funkcje, które mogą być szkodliwe, jeśli w jakiś sposób są dostępne dla użytkowników: odłączanie, odczytywanie, zapisywanie (semantyka plików), alokacja pamięci i arytmetyka wskaźników, dostęp do modelu bazy danych (nawet jeśli nie uwzględnia się przypadków iniekcji SQL).

Zasadniczo więc przez większość czasu, gdy jakikolwiek kod nie jest napisany poprawnie lub nie jest właściwie obserwowany (zasoby, użytkownicy, środowiska, ...), kod jest zły i może prowadzić nawet do skutków ekonomicznych.

Ale jest coś specjalnego z evalfunkcjami (niezależnie od języka).

Pytanie : Czy istnieje jakiś historyczny fakt, że ten strach staje się częścią kultury popularnej, zamiast zwracać taką samą uwagę na inne potencjalnie niebezpieczne cechy?

Luis Masuelli
źródło
11
Nie zgadzam się, że jest to zbyt szerokie i jako dowód przedstawiam cztery rozsądne odpowiedzi.
12
Głosowali za zamknięci jako zbyt szerokie ? (Nie widzę jeszcze bliskich głosów w tej społeczności) Ten ścisły powód staje się ostatnio znakiem wieloznacznym, który w ogóle nie ma żadnego znaczenia. Zwłaszcza gdy punkt, o który pytam, jest dość jasny z przykładami i konkretnym punktem, o który należy zapytać. Zapytam ten temat w Meta ...
Luis Masuelli
13
Dlaczego stał się częścią kultury popularnej, z większą uwagą niż inne niebezpieczne funkcje? Ponieważ aliteracja eval - zło jest łatwa do zapamiętania
BERGI
5
Przydział pamięci i arytmetyka wskaźników przez wielu postrzegane jako zło.
user253751
5
Należy zauważyć, że OpenERP (obecnie Odoo) nie tylko wywołuje eval, ale ma wewnętrzną funkcję wywołującą , safe_evalktóra przygotowuje środowisko do zapobiegania niebezpiecznym działaniom kodu. Znaleziono jednak błędy, ponieważ Python jest dość elastycznym językiem, a zatem trudnym do kontrolowania.
André Paramés

Odpowiedzi:

76

evalFunkcja sama w sobie nie jest złe, i nie ma subtelny punkt, że nie wierzę robisz:

Zezwolenie programowi na wykonanie dowolnego wprowadzania danych przez użytkownika jest złe

Napisałem kod, który używał pewnego evalrodzaju funkcji i był bezpieczny: program i parametry były zakodowane na stałe. Czasami nie ma funkcji języka ani biblioteki do robienia tego, czego potrzebuje program, a uruchomienie polecenia powłoki jest krótką ścieżką. „Muszę skończyć kodowanie za kilka godzin, ale napisanie kodu Java / .NET / PHP / innego kodu zajmie dwa dni. Albo mogę evalto zrobić za pięć minut.”

Gdy pozwalasz użytkownikom na wykonywanie dowolnych czynności, nawet jeśli są zablokowane przez uprawnienia użytkownika lub za „bezpiecznym” ekranem, tworzysz wektory ataku. Każdego tygodnia niektóre losowe CMS, oprogramowanie do blogowania itp. Ma łatkę zabezpieczającą, w której atakujący może wykorzystać taką lukę. Polegasz na całym stosie oprogramowania, aby chronić dostęp do funkcji, której można użyć, rm -rf /lub czegoś innego katastroficznego (uwaga: to polecenie prawdopodobnie nie powiedzie się, ale zakończy się niepowodzeniem po spowodowaniu niewielkiego uszkodzenia).

Czy jest jakiś fakt historyczny, że ten strach staje się częścią kultury popularnej, zamiast zwracać tę samą uwagę na inne, być może niebezpieczne, cechy?

Tak, istnieje precedens historyczny. Ze względu na liczne błędy, które zostały naprawione przez lata w różnych programach, które pozwalają zdalnym atakującym na wykonanie dowolnego kodu, pomysł na evalwiększość z nich wyszedł z łask. Nowoczesne języki i biblioteki mają bogaty zestaw funkcji, które sprawiają, że evalmniej ważne, i to nie przypadek. Obie sprawiają, że funkcje są łatwiejsze w użyciu i zmniejszają ryzyko exploita.

Wiele uwagi poświęcono wielu potencjalnie niepewnym funkcjom w popularnych językach. Czy ktoś otrzymuje więcej uwagi jest przede wszystkim kwestia opinii, ale evalcechy z pewnością mają udowodnienia problem bezpieczeństwa, który jest łatwy do zrozumienia. Po pierwsze, umożliwiają wykonywanie poleceń systemu operacyjnego, w tym wbudowanych powłok i programów zewnętrznych, które są standardowe (np. rmLub del). Po drugie, w połączeniu z innymi exploitami, osoba atakująca może przesłać własny plik wykonywalny lub skrypt powłoki, a następnie wykonać go za pośrednictwem oprogramowania, otwierając drzwi do prawie wszystkiego, co się stanie (nic dobrego).

To trudny problem. Oprogramowanie jest złożone, a stos oprogramowania (np. LAMP ) to wiele elementów oprogramowania, które oddziałują na siebie w złożony sposób. Uważaj, jak korzystasz z takich funkcji językowych, i nigdy nie zezwalaj użytkownikom na wykonywanie dowolnych poleceń.


źródło
2
Jesteś tym jedynym :). Chociaż istnieje dobrze znany przykład, który przyczynił się do powstania tej kultury, chciałbym zobaczyć go w odpowiedzi.
Luis Masuelli
5
Nie znam żadnego pojedynczego przykładu, uważam, że jest to bardziej „śmierć tysiącem cięć” z wieloma mniejszymi przykładami exploitów wykorzystywanych i łatanych. Nie przesadzam, gdy mówię, że jakiś zdalny exploit jest załatany co tydzień w jakimś oprogramowaniu.
1
Moje IDE to program, który pozwala mi - jego użytkownikowi - na wykonywanie dowolnych danych wejściowych. Uważam to za przydatne, a nie złe.
Den
3
@Den byłby to wyjątek. Będąc IDE, jestem pewien, że bez tej umiejętności mógłbyś spowodować chaos. Po prostu napisz to w swoim kodzie źródłowym. Ponadto masz już pełny dostęp do komputera, na którym działa. Oznacza to, że evalmoże podnieść uprawnienia. co nie stanowi problemu, jeśli są już podwyższone.
3
@Den: Tak to podsumował Raymond Chen jako „druga strona śluzy”. Możesz już uruchomić rm -rf /, nie trzeba tego robić w skomplikowany sposób za pomocą IDE. Problem evalpolega na tym, że otwiera tę umiejętność wielu aktorom, którzy nie powinni jej mieć.
MSalters
38

Częściowo jest to, że niuans jest trudny. Łatwo powiedzieć, że nigdy nie używaj goto, pól publicznych, interpolacji ciągów dla zapytań sql lub eval. Stwierdzeń tych nie należy tak naprawdę rozumieć jako stwierdzenia, że ​​nigdy, pod żadnym pozorem, nie ma powodu, aby z nich korzystać. Ale unikanie ich jako ogólnej zasady jest dobrym pomysłem.

Eval jest mocno odradzany, ponieważ łączy w sobie kilka typowych problemów.

Po pierwsze, jest podatny na ataki iniekcyjne. Tutaj jest to jak wstrzyknięcie SQL, ponieważ gdy dane kontrolowane przez użytkownika są wstawiane do kodu, łatwo przypadkowo pozwala na wstawienie dowolnego kodu.

Po drugie, początkujący zwykle używają eval do omijania źle skonstruowanego kodu. Początkujący programista może napisać kod, który wygląda następująco:

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

To działa, ale tak naprawdę jest to zły sposób na rozwiązanie tego problemu. Oczywiście użycie listy byłoby znacznie lepsze.

Po trzecie, eval jest zazwyczaj nieefektywne. Dużo wysiłku włożono w przyspieszenie implementacji języka programowania. Ale ewaluacja jest trudna do przyspieszenia, a jej użycie zazwyczaj będzie miało szkodliwy wpływ na wydajność.

Zatem eval nie jest złem. Można powiedzieć, że eval jest złem, ponieważ cóż, jest chwytliwym sposobem na wyrażenie tego. Każdy początkujący programista powinien ściśle unikać eval, ponieważ cokolwiek chcą zrobić, eval jest prawie na pewno złym rozwiązaniem. W niektórych zaawansowanych przypadkach użycia eval ma sens i powinieneś go używać, ale oczywiście uważaj na pułapki.

Winston Ewert
źródło
13
Twoja druga sprawa jest bardzo ważna. W językach, które mają eval, ale są również skompilowane, ocena łańcucha w celu utworzenia odwołania do zmiennej nie jest trywialna. Np. Jeśli var x = 3; print(x)jest skompilowany, to nie musi być żadnej wiedzy w czasie wykonywania, że źródło używało nazwy „x”. Aby var x = 3; print(eval("x"))zadziałało, mapowanie musi zostać zarejestrowane. To jest prawdziwy problem: w Common Lisp (let ((x 3)) (print (eval 'x)))zgłosi wyjątek zmiennej niezwiązanej, ponieważ zmienna leksykalna x nie ma żadnego połączenia z nazwą po skompilowaniu kodu.
Joshua Taylor
@JohnuaTaylor Masz na myśli trzeci powód, a nie drugi?
user253751
1
@immibis, myślę, że odnosi się do kodu z drugiego powodu. Ale masz rację, to naprawdę odnosi się do trzeciego powodu: wydajności.
Winston Ewert
Widziałeś to pytanie , prawda? ;)
jpmc26
@ jpmc26, no. Ale widziałem wiele takich.
Winston Ewert
20

Sprowadza się to do tego, że „wykonanie dowolnego kodu” to tech-talk dla „w stanie zrobić wszystko”. Jeśli ktoś jest w stanie wykorzystać wykonanie dowolnego kodu w twoim kodzie, jest to dosłownie najgorsza możliwa luka w zabezpieczeniach, ponieważ oznacza to, że jest w stanie zrobić wszystko, co możliwe dla twojego systemu.

„Inne potencjalnie szkodliwe błędy” mogą również mieć ograniczenia, co oznacza, że ​​są one z definicji mniej szkodliwe niż wykorzystywanie dowolnego wykonania kodu.

Mason Wheeler
źródło
2
Ze względu na argument, niewłaściwe użycie wskaźników prowadzi również do wykonania dowolnego kodu , ale wskaźniki nie są zadowolone z tego powodu eval.
Dmitrij Grigoryjew
12
@DmitryGrigoryev Czy naprawdę są? Poza C ++ wskaźniki są ogólnie uważane za wyjątkowo niebezpieczne i należy ich unikać. C # obsługuje na przykład wskaźniki, ale zwykle jest to ostatnia rzecz, którą wypróbujesz po wyczerpaniu wszystkich innych opcji (zwykle ze względu na wydajność podczas manipulacji danymi). Większość współczesnych języków nie obsługuje wskaźników. Nawet sam C ++ zmierza w kierunku „bezpieczniejszych” wskaźników, które próbują złagodzić problemy z dowolnymi wskaźnikami (np. Używając prawdziwych list / tablic zamiast samych wskaźników, używając safe_ptr, przekazywanie referencji ...).
Luaan
2
@DmitryGrigoryev: Czy możesz podać odniesienie dla każdego, kto twierdzi, że wskaźniki są mniej niebezpieczne niż eval?
JacquesB
2
@JacquesB proszę bardzo :)
Dmitry Grigoryev
1
@JacquesB, tak; to miał być żart (spodziewałem się, że uśmiech wystarczająco jasno to wyjaśni). OP złożył to oświadczenie, nie ja, więc powinieneś poprosić go o dowód.
Dmitrij Grigoriew
15

Istnieje praktyczny i teoretyczny powód.

Praktycznym powodem jest to, że obserwujemy, że często powoduje problemy. Rzadko zdarza się, że eval skutkuje dobrym rozwiązaniem, a często skutkuje złym rozwiązaniem, w którym miałbyś w końcu lepsze rozwiązanie, gdybyś udawał, że eval nie istnieje i podchodził do problemu inaczej. Tak więc uproszczona rada polega na jej zignorowaniu, a jeśli wpadniesz na przypadek, w którym chcesz zignorować uproszczoną poradę, miejmy nadzieję, że dokładnie ją przemyślałeś, aby zrozumieć, dlaczego uproszczona rada nie ma zastosowania i że pułapki nie wpłyną na ciebie.

Bardziej teoretycznym powodem jest to, że jeśli trudno jest napisać dobry kod, jeszcze trudniej jest napisać kod, który pisze dobry kod. Niezależnie od tego, czy używasz eval, czy generujesz instrukcje SQL, sklejając ciągi znaków lub pisząc kompilator JIT, to, co próbujesz, jest często trudniejsze niż się spodziewasz. Potencjał wstrzykiwania szkodliwego kodu jest jedną dużą częścią problemu, ale poza tym ogólnie trudniej jest wiedzieć, czy kod jest poprawny, jeśli kod nie istnieje nawet do czasu wykonania. Uproszczona rada polega na tym, aby ułatwić sobie: „używać sparametryzowanych zapytań SQL”, „nie używać eval”.

Biorąc przykład z efektów zaklęcia: jedną rzeczą jest zbudowanie kompilatora lub interpretera Lua (lub cokolwiek) w grze, aby umożliwić projektantom gry łatwiejszy język niż C ++ (lub cokolwiek innego) do opisywania efektów zaklęcia. Większość „problemów z ewaluacją” nie ma zastosowania, jeśli wszystko, co robisz, to ocenianie kodu, który został napisany i przetestowany i włączony do gry lub w DLC lub co masz. To tylko mieszanie języków. Wielkie problemy napotykają cię, gdy próbujesz generować Lua (lub C ++, SQL, polecenia powłoki lub cokolwiek innego) w locie i zepsuć to.

Steve Jessop
źródło
1
Oczywiście, generowanie kodu środowiska wykonawczego może być wykonane poprawnie, a eval może być przydatne. Np. Często używam eval do metaprogramowania / rzeczy podobnych do makr, szczególnie gdy chcę większej wydajności niż „czystszy” OOP lub funkcjonalne rozwiązanie. Wynikowy kod jest często lepszy i prostszy, ponieważ ma mniejszą liczbę szablonów. Jednak świadomość różnych problemów związanych z piaskownicą, mechanizmami ucieczki, wstrzykiwaniem kodu, regułami określania zakresu, raportowaniem błędów, optymalizacją itp. Wymaga nietrywialnego poziomu biegłości w języku, a eval bez tej wiedzy byłby niebezpieczny.
amon
11

Nie, nie ma oczywistych faktów historycznych.

Zło ewaluacji widać od samego początku. Inne funkcje są lekko niebezpieczne. Ludzie mogą usuwać dane. Ludzie mogą zobaczyć dane, których nie powinni. Ludzie mogą zapisywać dane, których nie powinni. I mogą zrobić większość z tych rzeczy, jeśli w jakiś sposób spieprzysz i nie zweryfikujesz danych wprowadzanych przez użytkownika.

Dzięki eval mogą zhakować pięciokąt i sprawić, że będzie wyglądał tak, jak ty. Mogą sprawdzać twoje naciśnięcia klawiszy, aby uzyskać twoje hasła. Zakładając pełny język Turinga, mogą dosłownie zrobić wszystko, co komputer jest w stanie zrobić.

I nie można sprawdzić poprawności danych wejściowych. Jest to dowolny ciąg znaków w dowolnej formie. Jedynym sposobem na sprawdzenie poprawności byłoby zbudowanie analizatora składni i silnika analizy kodu dla danego języka. Powodzenia z tym.

Telastyn
źródło
1
... lub mieć dane wejściowe pochodzące z zaufanego źródła, takie jak pliki definicji pisowni dla gry.
user253751
3
@immibis, ale jeśli dane wejściowe są wstępnie zdefiniowane i przetestowane bezpiecznie, po co korzystać z eval, kiedy można je włączyć do źródła systemu?
Jules
3
@immibis - ponieważ nikt nigdy nie hakuje plików gry ...
Telastyn
2
... to nie to, co oznacza „Turing zakończony” (kompletność Turinga jest o krok od nieistotnego przetwarzania w świecie rzeczywistym).
Leushenko
1
@Telastyn: Czego program Javascript nie może zrobić. Lub nawet program C ++. JavaScript działa wewnątrz piaskownicy (przeglądarki), która sama jest w innej piaskownicy (pierścień 3 w x86 speak). Wektor przerwania znajduje się poza piaskownicą, pod kontrolą systemu operacyjnego. Zewnętrzna piaskownica, pierścień 3, jest wymuszona przez procesor.
MSalters
6

Myślę, że sprowadza się to do następujących aspektów:

  • Konieczność
  • (Chronione) Użycie
  • Dostęp
  • Sprawdzalność
  • Ataki wieloetapowe

Konieczność

Cześć, napisałem to niezwykle fajne narzędzie do edycji obrazu (dostępne za 0,02 USD). Po otwarciu obrazu możesz przesłać na niego wiele filtrów. Możesz nawet sam napisać skrypt za pomocą Pythona (program, w którym napisałem aplikację). Wykorzystam tylko evaltwój wkład, ufając, że będziesz szanowanym użytkownikiem.

(później)

Dzięki za zakup. Jak widać, działa dokładnie tak, jak obiecałem. Och, chcesz otworzyć obraz? Nie możesz Nie użyję tej readmetody, ponieważ jest ona nieco niepewna. Oszczędność? Nie, nie użyję write.

Próbuję powiedzieć: potrzebujesz odczytu / zapisu dla prawie podstawowych narzędzi. To samo dotyczy przechowywania najlepszych wyników Twojej niesamowitej gry.

Bez odczytu / zapisu edytor obrazów jest bezużyteczny. Bez eval? Napiszę do tego niestandardową wtyczkę!

(Chronione) Użycie

Wiele metod może być potencjalnie niebezpiecznych. Na przykład readi write. Typowym przykładem jest usługa internetowa umożliwiająca odczytywanie obrazów z określonego katalogu poprzez podanie nazwy. Jednak „nazwa” może w rzeczywistości być dowolną prawidłową (względną) ścieżką w systemie, umożliwiając odczytanie wszystkich plików, do których dostęp ma usługa sieciowa, a nie tylko obrazów. Nadużywanie tego prostego przykładu nazywa się „przemierzaniem ścieżki”. Jeśli Twoja aplikacja umożliwia przechodzenie przez ścieżkę, jest zła. readBez obrony przed przechodzenia do ścieżki może wel nazwać złem.

Jednak w innych przypadkach ciąg dla readjest całkowicie pod kontrolą programistów (może zakodowany na stałe?). W takim przypadku nie jest to nic złego w użyciu read.

Dostęp

Teraz kolejny prosty przykład użycia eval.

Gdzieś w swojej aplikacji internetowej potrzebujesz dynamicznych treści. Pozwolisz administratorom wprowadzić kod, który jest wykonywalny. Ponieważ administratorzy są zaufanymi użytkownikami, teoretycznie może to być w porządku. Upewnij się, że nie wykonałeś kodu przesłanego przez osoby niebędące administratorami, i nic ci nie jest.

(To znaczy, dopóki nie zwolniłeś tego miłego administratora, ale zapomniałeś odwołać jego dostęp. Teraz twoja aplikacja internetowa jest zniszczona).

Sprawdzalność.

Innym ważnym aspektem, jak sądzę, jest łatwość weryfikacji danych wejściowych użytkownika.

Korzystasz z danych wprowadzonych przez użytkownika w wywołaniu odczytu? Upewnij się (bardzo), że dane wejściowe dla wywołania odczytu nie zawierają niczego złośliwego. Normalizuj ścieżkę i sprawdź, czy otwarty plik znajduje się w katalogu multimediów. To jest bezpieczne.

Dane wprowadzane przez użytkownika podczas zapisu? Podobnie!

Zastrzyk SQL? Po prostu ucieknij lub użyj sparametryzowanych zapytań, a będziesz bezpieczny.

Eval? Jak zamierzasz zweryfikować dane wejściowe użyte do evalpołączenia? Możesz pracować bardzo ciężko, ale jest naprawdę bardzo ciężko (jeśli nie niemożliwe), aby zapewnić bezpieczną pracę.

Ataki wieloetapowe

Teraz za każdym razem, gdy korzystasz z danych wprowadzanych przez użytkownika, musisz rozważyć korzyści płynące z korzystania z nich, z uwzględnieniem zagrożeń. Chroń jego użytkowanie jak najwięcej.

Zastanów się jeszcze raz nad evalsprawami w przykładzie administratora. Mówiłem ci, że to w porządku.

Teraz zastanów się, że w Twojej aplikacji internetowej jest miejsce, w którym zapomniałeś uciec od treści użytkownika (HTML, XSS). To mniejsze przestępstwo niż ewaluacja dostępna dla użytkownika. Ale korzystając z nieskalowanej treści użytkownika, użytkownik może przejąć przeglądarkę internetową administratora i dodać evalzdolny obiekt blob w sesji administratora, umożliwiając ponownie pełny dostęp do systemu.

(Ten sam wieloetapowy atak można wykonać za pomocą wstrzyknięcia SQL zamiast XSS lub zapisu w dowolnym pliku zastępującym kod wykonywalny zamiast użycia eval)

Sjoerd Job Postmus
źródło
2
„Możesz pracować bardzo ciężko, ale naprawdę bardzo ciężko (jeśli nie niemożliwe) jest zapewnienie jej bezpieczeństwa”. - To jest niemożliwe. Prosty dowód: zamiast próbuje dowiedzieć się, czy kodu użytkownik warunkiem jest „bezpieczne”, po prostu spróbować, aby dowiedzieć się czegoś o wiele prostsze, i zobaczyć, jak trudne to jest już: czy kod świadczone przez zatrzymanie użytkownika?
Jörg W Mittag
2
@ JörgWMittag: daj mi program napisany w Coq, a ja to udowodnię.
André Paramés
1
@ JörgWMittag: Zgoda. W zależności od języka i zakresu wprowadzania danych przez użytkownika. Równie dobrze może być eval("hard coded string" + user_input_which_should_be_alphanumeric + "remainder"). Możliwe jest sprawdzenie, czy dane wejściowe są alfanumeryczne. Ponadto „czy się zatrzymuje” jest ortogonalne w stosunku do „czy modyfikuje / uzyskuje dostęp do stanu, którego nie powinien dotykać” i „czy to metody, których nie powinien wywoływać”.
Sjoerd Job Postmus
3
@ JörgWMittag Nie można udowodnić, że dany program nic nie zrobi, ale nie jest niemożliwe konserwatywne zdefiniowanie ograniczonego zestawu programów, dla których można to udowodnić, i wymuszenie, aby programy wejściowe były członkami tego zestawu.
user253751
3

Aby ta funkcja w ogóle działała, oznacza to, że muszę zachować warstwę odbijającą, która umożliwia pełny dostęp do stanu wewnętrznego całego programu.

W przypadku języków interpretowanych mogę po prostu użyć stanu interpretera, co jest łatwe, ale w połączeniu z kompilatorami JIT nadal znacznie zwiększa złożoność.

Bez evaltego kompilator JIT często może udowodnić, że lokalne dane wątku nie są uzyskiwane z żadnego innego kodu, więc jest całkowicie dopuszczalne, aby zmieniać kolejność dostępu, pomijać blokady i buforować często używane dane przez dłuższy czas. Kiedy inny wątek wykonuje evalinstrukcję, może być konieczne zsynchronizowanie z tym działającego kodu skompilowanego JIT, więc nagle wygenerowany kod JIT potrzebuje mechanizmu awaryjnego, który powróci do niezoptymalizowanego wykonania w rozsądnym czasie.

Ten rodzaj kodu ma zwykle wiele subtelnych, trudnych do odtworzenia błędów, a jednocześnie ogranicza optymalizację w kompilatorze JIT.

W przypadku skompilowanych języków kompromis jest jeszcze gorszy: większość optymalizacji jest zabroniona i muszę zachować obszerne informacje o symbolach i tłumacza, więc dodatkowa elastyczność na ogół nie jest tego warta - często łatwiej jest zdefiniować interfejs do niektórych wewnętrznych konstrukcje, np dając skryptów widoku i kontrolera jednoczesny dostęp do programu modelu .

Simon Richter
źródło
„Aby ta funkcja w ogóle działała, oznacza to, że muszę mieć wokół siebie warstwę odbijającą, która umożliwia pełny dostęp do stanu wewnętrznego całego programu” - nie, tylko części, na które chcesz wpłynąć. W przypadku OpenERP / Odoo ewaluowany kod ma dostęp tylko do bardzo ograniczonej liczby zmiennych i funkcji, które może wywoływać, i wszystkie są lokalne dla wątków.
André Paramés
1

Odrzucam przesłankę evaluważaną za bardziej złą niż arytmetyka wskaźników lub bardziej niebezpieczną niż bezpośredni dostęp do pamięci i systemu plików. Nie znam rozsądnego programisty, który by w to uwierzył. Co więcej, języki obsługujące arytmetykę / bezpośredni dostęp do pamięci wskaźników zwykle nie obsługują evali vice versa, więc jestem pewien, jak często takie porównanie byłoby nawet istotne.

Ale evalmoże to być bardziej znana luka z tego prostego powodu, że jest obsługiwany przez JavaScript. JavaScript jest językiem piaskownicy bez bezpośredniego dostępu do pamięci lub systemu plików, więc po prostu nie ma tych luk, które wykluczają słabości samej implementacji języka. Evaljest zatem jedną z najniebezpieczniejszych cech języka, ponieważ otwiera możliwość wykonania dowolnego kodu. Wierzę, że o wiele więcej programistów rozwija się w JavaScript niż w C / C ++, więc evaljest to po prostu ważniejsze, aby być świadomym niż przepełnienia bufora dla większości programistów.

JacquesB
źródło
0

Żaden poważny programista nie uznałby Eval za „Evil”. To po prostu narzędzie programistyczne, jak każde inne. Strach (jeśli istnieje strach) przed tą funkcją nie ma nic wspólnego z kulturą popularną. Jest to po prostu niebezpieczne polecenie, które jest często niewłaściwie używane i może powodować poważne luki w zabezpieczeniach oraz obniżać wydajność. Z własnego doświadczenia powiedziałbym, że rzadko spotyka się problem z programowaniem, którego nie można rozwiązać bezpieczniej i wydajniej za pomocą innych środków. Programiści, którzy najprawdopodobniej używają eval, to ci, którzy są prawdopodobnie najmniej wykwalifikowani, aby robić to bezpiecznie.

To powiedziawszy, istnieją języki, w których użycie eval jest właściwe. Przychodzi mi na myśl Perl. Jednak osobiście uważam, że jest bardzo rzadko potrzebny w innych, bardziej nowoczesnych językach, które natywnie obsługują ustrukturyzowaną obsługę wyjątków.

użytkownik1751825
źródło
to nawet nie próbuje odpowiedzieć na postawione pytanie: „Czy istnieje jakiś historyczny fakt, że ten strach staje się częścią kultury popularnej”? Zobacz, jak odpowiedzieć
gnat
Moim zdaniem pytanie opiera się na fałszywym założeniu, więc jako takie odpowiedziałem.
user1751825,
0

Myślę, że dość dobrze ujęłeś to w następującej części twojego pytania (moje podkreślenie):

mają dobre zastosowanie, o ile są właściwie używane

Dla 95%, którzy mogą go właściwie używać, wszystko jest w porządku; ale zawsze znajdą się ludzie, którzy nie używają go prawidłowo. Niektóre z nich będą spowodowane brakiem doświadczenia i brakiem umiejętności, reszta będzie złośliwa.

Zawsze znajdą się ludzie, którzy chcą przekraczać granice i znajdować dziury w zabezpieczeniach - niektórzy na dobre, inni na złe.

Jeśli chodzi o fakt historyczny, evalfunkcje typu pozwalają zasadniczo na wykonanie dowolnego kodu, który był wcześniej wykorzystywany w popularnym internetowym systemie CMS, Joomla! . Z Joomla! zasila ponad 2,5 miliona witryn na całym świecie , co powoduje wiele potencjalnych szkód nie tylko dla odwiedzających te witryny, ale potencjalnie dla infrastruktury, na której jest hostowany, a także dla reputacji witryn / firm, które zostały wykorzystane.

Joomla! przykład może być prosty, ale został zarejestrowany.

gabe3886
źródło
0

Istnieje kilka dobrych powodów, aby zniechęcać do korzystania z nich eval(chociaż niektóre są specyficzne dla niektórych języków).

  • Środowisko (leksykalne i dynamiczne), z którego korzysta, evaljest często zaskakujące (to znaczy, że uważasz, że eval(something here)powinieneś zrobić jedną rzecz, ale robi inną, prawdopodobnie wywołując wyjątki)
  • Często istnieje lepszy sposób na osiągnięcie tego samego (łączenie skonstruowanych zamknięć leksykalnych jest czasem lepszym rozwiązaniem, ale może być również specyficzne dla wspólnego Lisp)
  • Zbyt łatwo jest skończyć z oceną niebezpiecznych danych (choć można w większości tego uniknąć).

Osobiście nie posunąłbym się nawet do stwierdzenia, że ​​jest to zło, ale zawsze będę kwestionować użycie evalw przeglądzie kodu, używając sformułowań w stylu „czy rozważałeś jakiś kod tutaj ?” (jeśli mam czas, aby dokonać choćby wstępnej wymiany) lub „czy jesteś pewien, że eval jest tutaj najlepszym rozwiązaniem?” (jeśli nie).

Vatine
źródło
to nawet nie próbuje odpowiedzieć na postawione pytanie: „Czy istnieje jakiś historyczny fakt, że ten strach staje się częścią kultury popularnej”? Zobacz, jak odpowiedzieć
gnat
0

Mówi w Minsky's Society of Mind , rozdział 6.4

Jest jeden sposób, aby umysł obserwował siebie i wciąż śledził, co się dzieje. Podziel mózg na dwie części, A i B. Podłącz wejścia i wyjścia mózgu A do prawdziwego świata - aby mógł wyczuć, co się tam dzieje. Ale nie łącz wcale mózgu B ze światem zewnętrznym; zamiast tego podłącz go, aby mózg A był światem mózgu B!

Kiedy jeden program (B) pisze inny program (A), działa on jako metaprogram. Przedmiotem B jest program A.

Istnieje program C. To ten w twojej głowie, który pisze program B.

Niebezpieczeństwo polega na tym, że może istnieć ktoś (C ') o złych zamiarach, który może ingerować w ten proces, więc dostajesz takie rzeczy jak wstrzyknięcie SQL.

Wyzwanie polega na tym, aby uczynić oprogramowanie bardziej inteligentnym, nie czyniąc go jednocześnie bardziej niebezpiecznym.

Mike Dunlavey
źródło
Dwa głosowania pozytywne i dwa głosowania negatywne. Wygląda na to, że to działa na nerwy.
Mike Dunlavey,
0

Masz tutaj wiele dobrych odpowiedzi, a głównym powodem jest wyraźnie to, że wykonanie dowolnego kodu jest złe mmmkay, ale dodam jeszcze jeden czynnik, który inni dotknęli tylko na krawędzi:

To jest naprawdę trudne do rozwiązywania kod, który jest przetwarzany na ciąg tekstowy. Twoje normalne narzędzia do debugowania są prawie całkowicie wyskakujące z okna i jesteś zredukowany do bardzo oldschoolowego śledzenia lub echa. Oczywiście nie ma to większego znaczenia, jeśli masz fragment w jednej linijce, który chcesz, evalale jako doświadczony programista prawdopodobnie możesz znaleźć lepsze rozwiązanie tego problemu, podczas gdy generowanie kodu na większą skalę może być gdzieś funkcją oceny staje się potencjalnie użytecznym sojusznikiem.

glenatron
źródło