Część języków programowania zawiera funkcję eval lub jej funkcjonalny odpowiednik. Można tu przywołać (choćby) JavaScript, Python, PHP, Perl, Smalltalk. Problem w tym, że eval jest czasami nadużywany i przez to ZŁY!
eval jest ZŁY!
Funkcja (funkcjonalność) eval pozwala na potraktowania łańcucha znaków (stringu) jako fragmentu kodu i wykonanie go. Zaletą tego rozwiązania jest fakt, że kod ten może zostać dynamicznie zbudowany, co czasami się przydaje. Problem jest w tym, że dynamiczne budowanie, czyli istnieje (spory) potencjał dla code injection.
Prosty i niezbyt sensowny przykład z wykorzystaniem Python i funkcji exec:
code = "a='%s';b='%s';c=a+b;print c" % (p1,p2) print code exec(code)
Parametry p1 i p2 są kontrolowane przez atakującego i w założeniu mają być ciągami znaków. To skomplikowane wyrażenie zwraca string złożony z p1 i p2. Problem zaczyna się wtedy, gdy w stringu p1 lub p2 pojawi się znak ', na przykład jeśli p1 ma wartość b': a='a';b='b'';c=a+b;print c Co prawda kod się nie wykona, bo składnia jest nieprawidłowa, ale nie jest problemem dobranie odpowiedniej składni, co na przykład stanie się przy takiej wartości p2: b';import sys;print sys.version;#? Podpowiem:
a='a';b='b';import sys;print sys.version;#';c=a+b;print c 2.6 (r26:66721, Oct 2 2008, 11:35:03) [MSC v.1500 32 bit (Intel)]
W pierwszej linii jest kod programu, który jest rzeczywiście wykonywany, w drugiej rezultat funkcji exec. Okazuje się, że dzieje się coś zupełnie innego, niż przewidział programista.
A teraz trochę mięska. Programista "zabezpiecza się" poprzez "maskowanie" znaku ', czyli upewnia się, że w przypadku p1 i p2 jeśli występuje znak ', to zostanie on zastąpiony przez \', kod wówczas wygląda mniej więcej tak:
p1 = p1.replace("'","\\'") p2 = p2.replace("'","\\'") code = "a='%s';b='%s';c=a+b;print c" % (p1,p2) print code exec(code)
Rezultat wykonania dla wartości p1 i p2 jak wcześniej jest teraz taki:
a='a';b='b\';import sys;print sys.version;#';c=a+b;print c ab';import sys;print sys.version;#
Problem rozwiązany, programista może iść do domu w poczuciu dobrze spełnionego obowiązku.
...kilka godzin później pojawia się znudzony ktoś i rezultatem wykonania programu znów jest:
(...cenzura...) 2.6 (r26:66721, Oct 2 2008, 11:35:03) [MSC v.1500 32 bit (Intel)]
Zagadka - jaka jest wartość parametru p2? :)
Dlaczego o tym piszę? Niestety, na popularności zyskuje AJAX. Sensowne jego wykorzystanie jest uzasadnione, ale jak zawsze, trzeba zachować umiar. Niestety, coraz częściej tego umiaru nie ma, a przeglądarka zamiera na kilka ładnych sekund przygotowując nową stronę do wyświetlenia, podczas gdy "zaawansowane skrypty" mieszają jej w DOM wyświetlanego dokumentu. Patrząc w źródła skryptów na takich stronach, można zauważyć (nad)używanie funkcji eval, co więcej używanie jej w taki sposób, że aż prosi się o code injection.
Szanowny programisto, eval i evil są podobne do siebie nie przez przypadek, eval (i jego odpowiedniki) powinny trafić na listę banned API. Użycie eval musi być naprawdę dobrze uzasadnione. Jeśli już musisz (sprawdź jeszcze raz, czy aby na pewno!) użyć eval lub jego funkcjonalnego odpowiednika (w jakimkolwiek języku!), pamiętaj, że user input też jest ZŁY!
Z zadaniem dotyczącym analizy obfuskowanego skryptu poradziło sobie już kilka osób. Udało mi się zainspirować tym zadaniem powstanie ciekawego wpisu: Beating JavaScript obfuscators with Firebug. Ja ze swojej strony przygotowałem drobną modyfikację zadania
Przesłany: Apr 15, 17:01