You are on page 1of 42

1

Spis treci

Wstp............................................................................3
Arytmetyka i obliczenia.................................................4

Przekroczenie zakresu liczb cakowitych...........................4

Obcicie zakresu liczb cakowitych...................................8

Wycieki danych...........................................................12

Gbokie ukrycie.........................................................12

Uycie niezainicjalizowanej pamici...............................13

Stabilno i niezawodno...........................................20

Kolizje w tablicach haszujcych.....................................20

Wyszukiwanie wszystkiego...........................................22

Wielowtkowo i wielozadaniowo..........................24

Wycigi w systemie.....................................................24

Dane wejciowe..........................................................27

Deserializacja niezaufanych danych...............................27

Logika aplikacji...........................................................31

Oscylatory walutowe...................................................31

Dziwactwa..................................................................33

Nierwne rwnoci......................................................33

Kryptografia................................................................35

Wartoci (nie)losowe...................................................35

Przenono kodu.......................................................37

Nazwy plikw..............................................................37

Zakoczenie................................................................39
Bibliografia.................................................................40
2

Wstp

Historia tworzenia i testowania oprogramowania jest cile zwizana


z histori elektronicznych maszyn liczcych, ktrej pocztki sigaj lat 30
i 40 poprzedniego wieku, kiedy to sawne postaci komputerowego wiata
takie jak Alan Turing, John von Neumann czy Tommy Flowers tworzyli podwaliny wspczesnej informatyki. Od czasu powstania pierwszej programowalnej maszyny software sta si nieodczn czci kadego komputera,
ktrego rozwj niedugo pniej wyewoluowa do niezwykle rozlegej i skomplikowanej dziedziny nauki w swoich podstawach odrbnej od hardware,
czyli fizycznie istniejcego sprztu, na ktrym jest wykonywany. Ze wzgldu
na ludzk omylno oraz fakt, e programowanie jest pod wieloma wzgldami procesem trudnym, wymagajcym koncentracji, wiedzy oraz dowiadczenia, bdy (tzw. bugi) wszelkich rodzajw towarzyszyy i towarzysz po dzi
dzie twrcom oprogramowania, stajc si wrcz integraln i akceptowan
czci ich pracy.
Bdy znajdujce si w programach komputerowych mona dzieli na wiele rnych kategorii: bdy w skadni lub logice aplikacji, bdy wpywajce
na stabilno lub bezpieczestwo systemu, bdy ujawniajce si w trakcie
pisania kodu, po tygodniach, latach, a nawet dekadach! W historii ostatnich
lat znajdziemy bdy ktre w aden znaczcy sposb nie wpyny na losy
wiata jak rwnie takie, ktrych skutki byy tragiczne, a firmy i pastwowe
organizacje obciyy stratami rzdu milionw, a nawet miliardw dolarw.
Naturalnym wydaje si, e nie sposb cakowicie wyeliminowa wszystkie
usterki w programach sterujcymi aparatami, komrkami, komputerami domowymi, reaktorami jdrowymi czy sztucznymi satelitami; moemy jednak
minimalizowa liczb popenianych pomyek oraz naprawia bdy, zanim
znajd si one w kodzie produkcyjnym. W niniejszym artykule przedstawiamy przykady kilkunastu najciekawszych, zdaniem autorw, rodzin bdw
i programistycznych potkni, wraz z wyjanieniem ich natury, moliwoci
unikania oraz powizanymi przykadami z ycia. Zapraszamy do lektury!

Arytmetyka i obliczenia

Przekroczenie zakresu liczb cakowitych


Zaczniemy od bardzo prostego bdu, ktry spotyka si w wielu jzykach
programowania - przekroczenia zakresu liczb cakowitych, lub czciej
integer overflow (dosownie przepenienie liczby cakowitej). Przykady kodu
zawierajcego bd tego typu w rnych jzykach programowania przedstawione s poniej:
// C, C++
unsigned short dlugosc_tekstu = OdbierzDlugoscTekstu(socket);
char *bufor = (char*)malloc(dlugosc_tekstu + 1);
OdbierzTekst(bufor, dlugosc_tekstu, socket);
bufor[dlugosc_tekstu] = '\0';
// ActionScript
var szerokosc:int = PobierzInt(plik);
var wysokosc:int = PobierzInt(plik);
var wielkosc:int = szerokosc * wysokosc;

W niektrych jzykach programowania takich jak C, C++, Objective-C,


ActionScript czy Java, zmienne typu cakowitego maj ograniczony rozmiar (zazwyczaj wyraany w bitach; np. typ int w ActionScript ma wielko
32 bitw), a co za tym idzie, ograniczony zakres wartoci ktre mona
w nich przechowa. W zasadzie dowolna ksika traktujca o danym jzyku
programowania rozpoczyna opis dostpnych typw zmiennych od podania
zakresu wartoci, ktre mona w nich przechowa; w przypadku wspomnianego typu int w ActionScript bd to wartoci od -231 do 231-1 (czyli od okoo
minus dwch miliardw, do okoo dwch miliardw).
Powstaje wic pytanie - co si stanie, jeli program w toku wykonywania
przekroczy dozwolony zakres zmiennej, w rezultacie wykonanej wanie
operacji arytmetycznej? Moliwoci jest oczywicie kilka i zale one zarwno od konkretnej technologii, jej wersji, typu zmiennej, jak i systemu,
czy architektury procesora na ktrym dany program jest uruchamiany.
W zdecydowanej wikszoci przypadkw do czynienia mamy z tzw. arytmetyk modulo ktra, rozpatrujc kwesti z niskopoziomowej perspektywy,

polega na przyciciu wyniku operacji do dolnych N-bitw, ktre mieszcz


si w zakresie danego typu (dla typw liczb naturalnych jest to rwnowane
z wykonaniem dzielenia modulo przez maksymaln warto, ktr mona
pomieci w zmiennej powikszon o jeden).
Rozwamy ten problem na podanym powyej przykadzie z ActionScript jeli funkcja PobierzInt zwrciaby w obu przypadkach warto 70 000, to
wynikiem mnoenia byoby oczywicie 4 900 000 000 (niecae pi miliardw). Binarnie (w systemie dwjkowym) mona t liczb zapisa jako:
1 0010 0100 0001 0000 0001 0001 0000 0000

Niestety, liczba cakowita tego rzdu wymaga do wyraenia 33 bitw, a zadeklarowana w przykadzie zmienna wielkosc ma rozmiar jedynie 32 bitw.
Z tego powodu najbardziej znaczca cz wyniku zostanie odrzucona:
1 0010 0100 0001 0000 0001 0001 0000 0000

W efekcie otrzymujemy znacznie mniejsz liczb - 605 032 704 - ktra nijak
ma si do oczekiwanego wyniku.
Bdy tego typu wystpuj w oprogramowaniu niezwykle czsto, jednak jedynie w nielicznych przypadkach objawiaj si podczas codziennej pracy z reguy programy w normalnych warunkach nie maj okazji operowa na
danych wystarczajco obszernych, by doprowadzi do przepenienia zmiennej typu wybranego przez programist. Bd tego typu moe zosta jednak
celowo wywoany przez osob o niecnych zamiarach, ktra, bdc w stanie spreparowa nieprzewidziane przez autora warunki dziaania programu,
moe doprowadzi do wykonania kontrolowanego przez ni kodu w kontekcie podatnej aplikacji (czyli do przejcia nad ni kontroli). W zwizku
z tym przekroczenie zakresu zmiennej, szczeglnie w przypadku jzykw
C oraz C++ (cho nie tylko), moe prowadzi do powanych problemw
zwizanych z bezpieczestwem aplikacji, a w konsekwencji caego systemu
komputerowego.

Za przykad moe posuy tutaj exploit zaprezentowany przez hakera o pseudonimie


PinkiePie na konferencji PacSec w Tokio w listopadzie 2013. PinkiePie, wykorzystujc wanie bd przepenienia zmiennej typu cakowitego w przegldarce Google
Chrome (a nastpnie kilka kolejnych bdw), by w stanie wykona dowolny kod na
smarfonach Nexus 4 oraz Samsung Galaxy S4, tym samym zdobywajc nagrod w
wysokoci 50,000 USD [1].

CIEKAWOSTKA

Problemy zwizane z przepenieniami typu cakowitego mona rozwiza na


kilka sposobw:
Niektre technologie umoliwiaj wykrycie przepenienia w momencie jego
wystpienia; na przykad w jzyku ADA w takiej sytuacji zostanie rzucony
wyjtek (w przypadku kompilatora z rodziny GCC wymaga to kompilacji
z opcj -gnato), ktry nastpnie moe by obsuony przez aplikacj. Innym
przykadem jest asembler architektury x86, w ktrym flagi CF (ang. Carry
Flag, tzw. flaga przeniesienia dla liczb naturalnych) oraz OF (ang. Overflow
Flag, tzw. flaga przepenienia dla liczb cakowitych) sygnalizuj wystpienie przepenienia podczas ostatnio wykonanej operacji arytmetycznej.
W innych przypadkach zaleca si korzystanie z odpowiedniej
biblioteki umoliwiajcej wykonywanie oblicze z sygnalizowaniem przepenie. Przykadem moe by stworzona przez firm Microsoft biblioteka SafeInt, przeznaczona dla jzyka C++ [2].
W pewnych sytuacjach najwygodniej jest ograniczy zakres
danych wejciowych do rozsdnych wartoci. Dla rozwaanego przykadu odpowiednia poprawka mogaby wyglda nastpujco:
var szerokosc:uint = PobierzUInt(plik);
var wysokosc:uint = PobierzUInt(plik);
if(szerokosc > 10000 || wysokosc > 10000) {
throw new Error("Obraz jest zbyt duy.");
}
var wielkosc:int = szerokosc * wysokosc;

Naley jednak zachowa szczegln ostrono przy dobieraniu wartoci


progowych, aby faktycznie zabezpieczay one przed wystpieniem przepenienia. Do istotnych wad tego rozwizania naley fakt, e testy tego
typu mog nie przetrwa prby czasu (w kocu za 5 lat moemy przesya
sobie zdjcia o wikszych wymiarach).
Jeli podejrzewamy, e przepenienie typu w danym miejscu moe nastpi wskutek przetwarzania poprawnych danych (np. bardzo duego
obrazka), powinnimy rozway rozszerzenie typu zmiennej, np. zmian
32-bitowego typu int na 64-bitowy typ uint64_t lub long long (dot. popularnych kompilatorw na architekturach x86-32 jak i x86-64). Rozwizanie to mona zastosowa rwnie do zabezpieczenia si przed przepenieniami wskutek przetwarzania specjalnie spreparowanych danych, jeli
jestemy w peni wiadomi wartoci, jakie mog przyjmowa zmienne
podczas wykonywania oblicze i jestemy w stanie dowie, e rozsze-

rzenie zakresu danej zmiennej faktycznie skutecznie zapobiega wszelkim


przepenieniom.
W celu wykrycia wystpienia przepenienia typu cakowitego w trakcie
wykonywania aplikacji napisanej w C lub C++ jako cz procesu jej testowania lub debuggowania mona uy opcji -fsanitize=integer dostpnej w kompilatorze clang w wersji 3.5 i nowszych. Doczenie owej flagi
do opcji kompilacji powoduje, e w momencie wystpienia przepenienia
na standardowy strumie bdw wypisywana jest informacja o zaistniaej
sytuacji, np.:
ioc.c:6:13: runtime error: signed integer overflow: 100000 *
100000 cannot be represented in type 'int'
ioc.c:6:17: runtime error: signed integer overflow:
1410065408 * 100000 cannot be represented in type 'int'

W wydanej przez MicroProse w roku 1994 grze Transport Tycoon mona byo
w prosty sposb doprowadzi do przekroczenia zakresu zmiennej przechowujcej
ilo posiadanych w grze pienidzy, dziki czemu gracz mg w szybki sposb bardzo
si wzbogaci (niestety jedynie wirtualnie).

CIEKAWOSTKA

Bd objawia si w momencie zakupu bardzo drogiego tunelu kolejowego, biegncego przez ca dugo mapy. Na przykad, tunel widoczny na zrzucie ekranu z gry
poniej, kosztowa ponad 2 miliardy wirtualnych funtw, a konkretniej 2 380 014 463.
Niestety, wszystkie operacje finansowe w grze wykonywane byy na zmiennych typu
int (32 bity, liczba ze znakiem), a co za tym idzie, warto ta nie bya moga zosta
wyraona poniewa wykraczaa poza zakres moliwych wartoci - nastpowao przepenienie, a warto bya traktowana jak -1 914 952 833 (wynika to z reprezentacji tych
liczb na poziomie bitowym).
Oczywicie, gracza posiadajcego na pocztku gry 100 000, wedug logiki gry, byo
sta na zakup tunelu kosztujcego okoo minus dwa miliardy, a co za tym idzie, zakup
dochodzi do skutku. Efektem zakupu jest oczywicie odjcie kosztu od salda konta,
a wic w tym przypadku dochodzio do nastpujcych oblicze:
nowe saldo = 100 000 - (-1 914 952 833) = 1 915 052 833
Dziki temu gracz wzbogaca si o niecae dwa miliardy wirtualnych funtw i mg kontynuowa rozgrywk nie martwic si o przyszo swojego przedsibiorstwa transportowego.
Warto doda, e bd zosta poprawiony w wydanym rok pniej Transport Tycoon
Deluxe.

CIEKAWOSTKA

Transport Tycoon.

Obcicie zakresu liczb cakowitych


Kolejny, nie mniej istotny czy rzadziej spotykany rodzaj bdu zwizany z obliczeniami na liczbach cakowitych to rzutowanie i konwersja zmiennych. Znaczna
wikszo tzw. silnie typowanych jzykw programowania takich jak C, C++,
Objective-C, ActionScript czy Java posiada wiele rnych typw zmiennych przeznaczonych do operowania na liczbach cakowitych, ktre rni si od siebie
przechowywaniem informacji o znaku, zakresem moliwych wartoci i co bezporednio z tym zwizane, iloci pamici, ktr taka zmienna zajmuje. W zoonym systemie informatycznym konkretna warto moe by przekazywana
przez bardzo dugi cig zalenych od siebie funkcji, klas i struktur, nierzadko
tworzonych w rnym czasie przez zupenie rne osoby. W zwizku z tym niezwykle wane jest, by ostronie podchodzi do kwestii konwersji wartoci z jednego typu na drugi oraz czynienia jakichkolwiek zaoe na temat tego, co moe
znajdowa si w zmiennej otrzymanej z innej czci systemu. Niepotrzebna lub
nieodpowiednio zaimplementowana konwersja typu moe prowadzi do utraty
czci informacji znajdujcych si w zmiennej, co w efekcie nierzadko skutkuje
luk bezpieczestwa w aplikacji czy systemie, lub w gorszym scenariuszu - niepowodzeniem przedsiwzicia wartego miliardy dolarw.

Wczeniej przyjrzyjmy si jednak poniszemu przykadowemu listingowi


kodu w jzyku C++:
int PobierzWartosc() {
int wartosc;
scanf("%d", &wartosc);
return wartosc;
}
void WypiszWartoscChar() {
char skladnik_1 = PobierzWartosc();
char skladnik_2 = PobierzWartosc();
printf("%d\n", skladnik_1 + skladnik_2);
}
void WypiszWartoscInt() {
int skladnik_1 = PobierzWartosc();
int skladnik_2 = PobierzWartosc();
printf("%d\n", skladnik_1 + skladnik_2);
}

Pomimo faktu, e obie procedury z rodziny WypiszWartosc wykonuj t sam


operacj, tylko jedna z nich jest w peni poprawna. Zauwamy, e w przypadku
procedury WypiszWartoscChar liczba zwrcona przez PobierzWartosc znajdujca
si w 32 bitowej zmiennej typu int zostaje przerzutowana na 8 bitowy typ char,
co automatycznie wie si z utrat grnych 24 bitw danych. Jeli uytkownik
dostarczaby na standardowe wejcie wycznie liczby z dopuszczalnego zakresu
typu char, procedura dobrze speniaaby swoje zadanie; w przeciwnym jednak
razie, wysze bity przekazanych wartoci zostayby zgubione na etapie konwersji, tym samym prowadzc do niewaciwych wynikw na wyjciu.
Niezgodno rozmiaru typw mona w wielu przypadkach wykry na etapie kompilacji; w przypadku C oraz C++, popularne kompilatory z rodziny gcc oraz clang
oferuj flag -Wconversion, ktra aktywuje wypisywanie ostrzee zwizanych
z utrat informacji podczas rzutowania. Ostrzeenia wygenerowane dla powyszego kodu wygenerowane przez clang 3.5 wygldaj nastpujco:
test2.c:10:21: warning: implicit conversion loses integer precision:
'int' to 'char' [-Wconversion]
char skladnik_1 = PobierzWartosc();
~~~~~~~~~~
^~~~~~~~~~~~~~~~
test2.c:11:21: warning: implicit conversion loses integer precision:
'int' to 'char' [-Wconversion]
char skladnik_2 = PobierzWartosc();
~~~~~~~~~~
^~~~~~~~~~~~~~~~
2 warnings generated.

Jeli kompilator wskae nam w kodzie miejsca potencjalnie dotknite problemem utraconej precyzji lub sami takie miejsca zlokalizujemy, nie bjmy
si uywa typw kompatybilnych z tymi, na ktrych operuj uywane przez
nas moduy aplikacji - potencjalne zaoszczdzenie kilku bajtw nie zrobi
w dzisiejszych czasach adnej rnicy, moe za uchroni program przed powanym bdem i jego przyszymi konsekwencjami.

CIEKAWOSTKA

Cho rzutowanie do zmiennej o zakresie mniejszym ni konieczna do przechowania


wartoci wydaje si by kwesti trywialn i atw do wykrycia, historia pokazuje, e
bdy tego typu zdarzay si nawet tam, gdzie w adnym wypadku nie powinny byy
si pojawi. Za pierwszy przykad moe posuy eksplozja jednej z rakiet nalecych do rodziny Ariane 5. W dniu 4 czerwca 1996, 37 sekund po starcie rakieta warta
setki milionw dolarw, wystrzelona przez Europejsk Agencj Kosmiczn nakadem
siedmiu miliardw dolarw, zboczya z objtego kursu i rozbia si na skutek wyjtku
spowodowanego nieudan prb konwersji wartoci zmiennoprzecinkowej zawartej
w 64-bitowej zmiennej do 16-bitowej zmiennej typu cakowitego. Wicej informacji na
temat katastrofy znale mona w licznych internetowych rdach [3] [4] [5] [6].
Wiele lat pniej bd tego samego typu sprawi, e autoryzacja uytkownika przy
pomocy hasa staa si bezuyteczna - 9 czerwca 2012 roku Sergei Golubchik opisa
na licie dyskusyjnej oss-sec sposb na zalogowanie si do dowolnej podatnej bazy
MySQL umoliwiajcej zdalne poczenia przy uyciu istniejcej nazwy uytkownika
(uytkownik root istnieje w znacznej wikszoci baz), bez znajomoci poprawnego
hasa. Atak polega na wykonaniu ok. 300 prb logowania do bazy, z ktrych zazwyczaj conajmniej jedna udawaa si pomimo dostarczenia bdnych danych autoryzacyjnych. Niewiarygodne? A jednak!
Naley nadmieni, e nie wszystkie kompilacje serwera MySQL zostay dotknite
przez podatno - dotyczya ona wycznie wersji korzystajcych z funkcji memcmp
zoptymalizowanej przy uyciu rozszerzenia procesora SSE (Streaming SIMD Extensions), znajdujcej si w bibliotece glibc. Sam bd wystpowa w nastpujcym kodzie:
my_bool
check_scramble(const char *scramble_arg, const char *message,
const uint8 *hash_stage2)
{
[...]
return memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE);
}
Aby zrozumie natur bdu problemu, przyjrzyjmy si deklaracji funkcji standardowej
memcmp:
int memcmp ( const void * ptr1, const void * ptr2, size_t num );

10

Jako, e typ my_bool jest zdefiniowany w kodzie rdowym MySQL jako char,
potencjalny bd ukryty w kodzie staje si oczywisty - w funkcji check_scramble
dochodzi do niejawnej konwersji typw, prowadzc do utraty informacji znajdujcych
si w grnych 24 bitach wartoci zwrconej przez memcmp. Zgodnie z dokumentacj, funkcja ta zwraca jako wynik relacj pomidzy porwnywanymi blokami pamici:
liczb ujemn, zero lub dodatni kolejno kiedy pierwszy region jest leksykograficznie
wczeniej, oba regiony s rwne i pierwszy region jest leksykograficznie pniej. Znamy wic znaczenie poszczeglnych rodzajw liczb zwracanych przez funkcj - nigdzie
nie jest jednak zdefiniowane, jakie konkretnie mog lub powinny by owe ujemne lub
dodatnie wyniki. Wiele istniejcych implementacji memcmp zwraca zwyczajnie -1, 0
lub 1; pozostawienie dowolnoci co do konkretnej wartoci zwracanej pozwolio jednak
na wprowadzenie niskopoziomowych optymalizacji takich jak porwnywanie obszarw pamici w blokach 32-bitowych lub wikszych, zamiast pojedynczych bajtw. Poniewa wynik takiej funkcji jest bezporednio zwizany z wielkoci jednostki danych
na ktrych operuje funkcja, moliwe staj si wartoci zwracane takie jak 0x6f203100,
ktre w dalszym cigu poprawnie (zgodnie ze specyfikacj) sygnalizuj, e drugi region pamici jest mniejszy leksykograficznie. Kiedy jednak liczba ta zostanie skonwertowana do typu char tak, jak miao to miejsce w MySQL, zostaje z niej wycznie
osiem dolnych, zerowych bitw ktre bdnie sugeruj, e cigi s sobie rwne.

CIEKAWOSTKA

W przypadku wspomnianej bazy danych porwnywane byy hashe SHA1, a poniewa


hash poprawnego hasa nie by znany osobie atakujcej, wymagane byo przeprowadzenie prostego ataku siowego ostatecznie doprowadzajcego do sytuacji, w ktrej
najmniej znaczcy bajt wyniku funkcji memcmp byby rwny zero. Dziki waciwociom
algorytmu SHA1 prawdopodobiestwo wystpienia jedynki w kadym z omiu bitw
wartoci zwracanej przez funkcj porwnujc byo rwne 0.5 dla losowego hasa,
a wic wykonanie ponad 256 prb logowania z bardzo duym prawdopodobiestwem
umoliwiao poprawne zalogowanie si do systemu.
Do wykorzystania podatnoci wystarczya zaledwie jedna linia w Bashu, jzyku skryptowym powoki Linuxa, odpowiedzialna za wykonanie tysica prb logowania do bazy
danych zarzdzanej przez podatny serwer:
for i in `seq 1 1000`; do mysql -u root --password=bad -h <host>
2>/dev/null; done
Bd ten przeszed do historii jako jedna z najbardziej absurdalnych luk bezpieczestwa, wygrywajc prestiow nagrod w kategorii Najlepszy bd po stronie serwera
(ang. Pwnie for Best Server-Side Bug). Wkrtce po jego zgoszeniu wydana zostaa
oficjalna atka, polegajca na objciu wywoania funkcji memcmp makrem o nazwie
test, normalizujcym dowoln warto do zera i jedynki:
#define test(a)

((a) ? 1 : 0)

11

Wycieki danych

Gbokie ukrycie
To nieco humorystyczne okrelenie opisuje pewn grup bdw, ktr inaczej mona by okreli jako moliwo znalezienia pewnych danych na stronie WWW (rzadziej w innych technologiach), ktrych pooenie z zaoenia
miao by znane jedynie ograniczonej grupie odbiorcw, ale z uwagi na pewne niedocignicia, dane zostay odnalezione przez inne osoby.
Dobrym przykadem moe by cz serwisu WWW przedsibiorstwa,
w ktrym osoba zainteresowana prac moe zaoy konto oraz przesa
swoje CV (a w pniejszym terminie je np. uaktualni). Niestety czasami si
zdarza, e kandydat, dysponujc linkiem do swojego CV w systemie, moe
odgadn link do CV innych kandydatw. Przykadowy link moe wyglda
nastpujco:
http://example.com/kandydaci/cv/4713.pdf
atwo si domyli, e podmieniajc liczb w linku z 4713 na, na przykad,
4712, mona prawdopodobnie podejrze CV innego kandydata.
CIEKAWOSTKA

Termin gbokie ukrycie zosta spopularyzowany w roku 2010 przez serwis Niebezpiecznik (niebezpiecznik.pl), w artykule o wycieku czci bazy dunikw banku PKO
BP [7]. Przedstawiciel banku wyjaniajc sytuacj mia stwierdzi, e plik zosta zabezpieczony w tak zwanym gbokim ukryciu. Termin gbokie ukrycie zosta wskazany przez redaktora - Macie pomys, co oznacza gbokie ukrycie? ;-) - a nastpnie by uywany w innych newsach o podobnej tematyce, np.:
7 000 polskich CV w gbokim ukryciu [8]
Gbokie ukrycie na video [9]
Ostatecznie termin doczeka si nawet swojej podstrony na polskiej Wikipedii [10];
w kontekcie hasa na Wikipedii warto rwnie przeczyta post Pawa Golenia, pt.
O gbokim ukryciu nieco inaczej [11].

12

Problem gbokiego ukrycia to tak naprawd kilka innych problemw


poczonych razem:
Po pierwsze - brak autoryzacji. Kandydat X nie powinien mie
dostpu do CV kandydata Y - system powinien sprawdzi, czy kandydat X zalogowany na swoje konto ma prawo oglda CV, ktre
chce wywietli (a w przeciwnym wypadku wywietli komunikat
bdu).
Po drugie - w takich wypadkach nazwa zasobu nie powinna by po
prostu numerem porzdkowym (czasami okrela si takie przypadki bdem enumeracji), poniewa niepotrzebnie zdradza to liczb
przesanych CV do danej firmy (co samo w sobie jest wyciekiem
danych, chocia nieznacznym), ale take umoliwia atwe zgadywanie identyfikatorw CV innych kandydatw. Jednym z rozwiza
tego problemu jest uycie np. sumy SHA-2 z numeru CV oraz pewnego niejawnego cigu, lub uycie odpowiednio dugiego, nieprzewidywalnego, unikatowego identyfikatora.
Po trzecie - w niektrych przypadkach, nawet jeli nazwy s losowe, czasami domylna konfiguracja serwera WWW oferuj list
plikw w danym katalogu. Poza szczeglnymi przypadkami, zaleca
si wyczenie tej opcji (np. dla serwera Apache naley ustawi
Options -Indexes).

Uycie niezainicjalizowanej pamici


Natywne, niezarzdzane jzyki programowania takie jak C lub C++ charakteryzuj si bardzo duym stopniem zaufania do programisty - to on,
i tylko on jest odpowiedzialny za unikanie wszelkich bdw implementacyjnych - zwaszcza tych zwizanych z obsug i dostpem do pamici. Podejcie to ma zarwno wady, jak i zalety: dziki brakowi narzutu
zwizanego z poprawnoci wykonywanych operacji (takich jak dostp
do tablic i dynamicznie zaalokowanych obiektw) poprawnie napisane
programy mog osiga bardzo dobre wyniki wydajnociowe, w peni
wykorzystujc potencja obliczeniowy sprztu na ktrym si wykonuj.
Z drugiej strony dowolny, nawet prosty bd stwarza istotne zagroenie
dla bezpieczestwa, pozwalajc potencjalnemu atakujcemu na zmian
struktury lub zawartoci krytycznych regionw pamici odpowiadajcych
za poprawny tok wykonania aplikacji i tym samym na przejcie kontroli
nad procesem lub caym systemem.

13

Obok powszechnie znanych bdw obsugi pamici zwizanych z zapisem (np. przepenienie bufora itd.), ktre w sposb bezporedni
zagraaj bezpieczestwu aplikacji, istnieje jeszcze druga grupa - bdy zwizane z odczytem. Jedn z usterek tego typu jest uycie regionu
pamici, ktry nie zosta wczeniej zainicjalizowany ani automatycznie
(zgodnie ze standardem, np. w przypadku zmiennych globalnych), ani
bezporednio w kodzie (w przypadku zmiennych lokalnych lub alokacji
dynamicznych).
Bdy uycia niezainicjalizowanej pamici mog mie najrniejsze objawy i konsekwencje, w zalenoci od kilku czynnikw: jakie informacje
(semantycznie) przechowuje owa pami, w jaki sposb zosta skompilowany program oraz w jakim rodowisku jest on wykonywany (co
nierzadko determinuje dane, ktre przypadkowo znajduj si w niezainicjalizowanych buforach). Istnieje kilka najczstszych objaww i konsekwencji takich bdw:
Nastpuje naruszenie ochrony pamici, tj. odczyt z niezainicjalizowanej pamici koczy si niedozwolonym zapisem (pod nieistniejcy adres lub poza dozwolone ramy pamici danego obiektu).
Sytuacja taka moe wystpi, jeli niezainicjalizowana zmienna
przechowuje informacje bezporednio uywane do adresowania
pamici, takie jak wskanik, indeks w tablicy lub rozmiar danych
w pamici. Bd taki jest wtedy czsto rwnoznaczny z luk bezpieczestwa w aplikacji.
Program nie narusza zasad dotyczcych zarzdzania pamici,
jednak zachowuje si w sposb niedeterministyczny, zwracajc rne wyniki lub przejawiajc rne zachowania w tych samych warunkach i dla tych samych danych wejciowych. Sytuacja
taka jest charakterystyczna dla niezainicjalizowanych zmiennych, ktre przechowuj informacje na podstawie ktrych podejmowane s decyzje w aplikacji (np. zmienne typu bool uywane
w wyraeniach if).
Niezainicjalizowane pozostaj wycznie regiony pamici zawierajce dane wejciowe. W tym wypadku integralno dziaania
programu nie jest zagroona (o ile potrafi on poprawnie obsuy
dowolne dane), jednak wynik dziaania aplikacji moe by niepoprawny, trudny do przewidzenia i najczciej bezporednio zwizany ze starymi danymi, ktre znajdoway si w niezainicjalizowanej
pamici.

14

W sposb oczywisty usterki tego rodzaju naprawia si poprzez inicjalizowanie kadego obszaru pamici, ktry jest dalej uywany przez program
- wikszym wyzwaniem jest raczej wykrycie ich istnienia. W wielu przypadkach na pomoc moe przyj nam kompilator; spjrzmy na poniszy
przykad:
int liczba;
bool pierwsza;
bool parzysta;
scanf("%d", &liczba);
pierwsza = SprawdzPierwszosc(liczba);
if (pierwsza && liczba != 2) {
parzysta = false;
}
if (parzysta) {
puts("Podana liczba jest parzysta.");
} else {
puts("Podana liczba nie jest parzysta.");
}

Bd znajdujcy si w kodzie polega na tym, e zmienna parzysta wypeniana jest konkretn wartoci tylko w przypadku, gdy podana przez uytkownika liczba jest pierwsza; w przeciwnym wypadku pozostanie ona niezdefiniowana (w praktyce na powszechnych platformach przejmujc warto,
ktra wczeniej znajdowaa si w tym miejscu na stosie). Jeli wic na wejciu pojawi si liczba zoona, nie da si z gry przewidzie wyniku dziaania
programu. Podczas prby skompilowania pliku przy uyciu kompilatora clang
3.5 z opcj -Wuninitialized (wchodzcej w skad opcji -Wall), otrzymujemy
nastpujce ostrzeenia:
[...]
uninit.cc:23:7: warning: variable 'parzysta' is used uninitialized
whenever '&&' condition is false [-Wsometimes-uninitialized]
if (pierwsza && liczba != 2) {
^~~~~~~~
uninit.cc:27:7: note: uninitialized use occurs here
if (parzysta) {
^~~~~~~~
uninit.cc:23:7: note: remove the '&&' if its condition is always true
if (pierwsza && liczba != 2) {
^~~~~~~~~~~
uninit.cc:19:16: note: initialize the variable 'parzysta' to silence
this warning
bool parzysta;
^
= false

15

Wskazano nam wic dokadnie, w jakich warunkach flaga nie zostanie zainicjalizowana oraz w ktrym miejscu jest nastpnie uywana. ledzenie
zalenoci midzy zmiennymi na etapie kompilacji jest niestety moliwe
wycznie w przypadku obiektw statycznych, tj. zdefiniowanych bezporednio w kodzie; jeli zmienimy zmienne pierwsza i parzysta z lokalnych
na dynamicznie alokowane, nie dowiadczymy podobnego komunikatu
pomimo dalszego istnienia usterki:
int liczba;
bool *pierwsza = new bool;
bool *parzysta = new bool;
scanf("%d", &liczba);
*pierwsza = SprawdzPierwszosc(liczba);
if (*pierwsza && liczba != 2) {
*parzysta = false;
}
if (*parzysta) {
puts(Podana liczba jest parzysta.);
} else {
puts(Podana liczba nie jest parzysta.);
}

W tej sytuacji moemy jednak polega na narzdziach o nazwie memcheck (wchodzcy w skad pakietu valgrind) oraz MemorySanitizer.
Pierwsze z nich jest samodzieln aplikacj, ktra emuluje wykonywanie dowolnego programu weryfikujc przy tym, czy kade z odwoa do
pamici jest poprawne, wczajc w to uycie niezainicjalizowanych
danych. Przykadowo, uruchomienie przedstawionego wyej kodu
z uyciem memcheck skutkuje wypisaniem nastpujcego ostrzeenia:
==14387== Conditional jump or move depends on uninitialised value(s)
==14387==
at 0x400742: main (uninit.cc:27)

O ile bardzo skuteczny i dokadny, valgrind posiada jedn, podstawow


wad - wie si on z narzutem czasu wykonania rzdu 4-120x, co
moe by spor przeszkod w regularnym testowaniu zoonych aplikacji wykonujcych znaczn ilo oblicze. Znacznie lepiej radzi sobie na
tym polu projekt MemorySanitizer, ktry zwalnia typowe aplikacje tylko
trzykrotnie dziki temu, e dziaa na etapie kompilacji wprowadzajc do
kodu maszynowego programu dodatkowe instrukcje testujce za kadym
razem, czy region do ktrego nastpuje odwoanie zosta wczeniej po-

16

prawnie zainicjalizowany. MemorySanitizer zosta wczony do kompilatora clang w wersji 3.5, a do jego uycia potrzebujemy flagi -fsanitize=memory:
$ clang++ uninit.cc -fsanitize=memory -g

Po uruchomieniu programu i wpisaniu liczby zoonej powinien ukaza nam


si komunikat podobny do nastpujcego:
==11628== WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x7fdcd96ca8a5 in main uninit.cc:27
#1 0x7fdcd854e76c in __libc_start_main
#2 0x7fdcd96ca23c in _start
SUMMARY: MemorySanitizer: use-of-uninitialized-value uninit.cc:27
main
Exiting

Serdecznie zachcamy do zapoznania si z oboma systemami detekcji uycia niezainicjalizowanej pamici, a take wybrania i regularnego korzystania
z rozwizania uznanego za lepsze w konkretnym przypadku.
Okazuje si, e bdy uycia niezainicjalizowanej pamici mog mie powane oraz
ciekawe konsekwencje z punktu widzenia prywatnoci uytkownika. Wyobramy
sobie nastpujcy scenariusz: uytkownik domowy korzysta z pewnej popularnej
aplikacji klienckiej; w pewnym momencie zostaje nakoniony przez zdalnie atakujc
osob do uycia owego programu do otwarcia pewnego specjalnie spreparowanego
pliku. Plik przygotowany przez osob o niecnych zamiarach wykorzystuje bd uycia
niezainicjalizowanej pamici w programie, w wyniku czego exploit zyskuje dostp do
mieciowych danych znalezionych w przestrzeni adresowej, a nastpnie wysya te
dane z powrotem do serwera adwersarza. Brzmi nierealnie? Powysza sytuacja jest
jak najbardziej moliwa jeli za pewn aplikacj podstawimy przegldark internetow, plikiem wejciowym bdzie plik HTML zawierajcy sprytny kod Javascript, a bd
bdzie polega na renderowaniu przez przegldark bajtw o niezainicjalizowanej
wartoci w formie pikseli na stronie.

CIEKAWOSTKA

Zacznijmy jednak od pocztku - jak dobrze wiemy, wszystkie popularne graficzne


przegldarki internetowe (Internet Explorer, Firefox, Chrome, Opera, Safari) obsuguj wiele podstawowych formatw graficznych takich jak BMP, JPEG, GIF czy TIFF.
Sze lat temu autorzy niniejszego artykuu zidentyfikowali niezalenie bdy w obsudze niektrych z tych formatw (gwnie BMP i TIFF) w przegldarkach Firefox, Opera
i Safari. Kady z nich pozwala na zmuszenie podatnej przegldarki do wywietlenia
od 1 do 256 pikseli opisanych przez wartoci RGB znajdujce si w niezainicjalizowanej pamici dynamicznej alokacji, co na pierwszy rzut oka wygldao jak nic nie
znaczce artefakty. Jeli uywana przegldarka miaa wyczon obsug Javascript,
na artefaktach si koczyo - obrazek (lub ich wiksza liczba umieszczona na stronie)
wypeniony mieciami w pamici wywietla si na ekranie, co jednak w aden nega-

17

CIEKAWOSTKA

tywny sposb nie wpywao na bezpieczestwo czy prywatno uytkownika. Kiedy


jednak obsuga Javascript bya aktywna (co dotyczyo i wci dotyczy przewaajcej
wikszoci uytkownikw), odpowiednio spreparowany skrypt by w stanie odczyta
warto renderowanych pikseli przy uyciu dostpnego w HTML elementu canvas,
a nastpnie wysa trzy bajty opisujce kolor kadego z nich do zdalnego serwera.
Podsumowujc, wywietlanie niezainicjalizowanej pamici w kontekcie wrogiej strony moe prowadzi do ujawnienia fragmentw danych, ktre wczeniej byy przetwarzane przez przegldark. Pozostaje wic pytanie, jakie informacje mogyby dosta
si w niepowoane rce za spraw bdu tego typu?
Odpowied jest zalena od przegldarki - w toku empirycznych testw pokazalimy,
e czci kodu HTML stron wywietlanych w tym samym czasie, urywki komunikacji
HTTP i adresy odwiedzonych stron znajdoway si wrd niezainicjalizowanych buforw we wszystkich dotknitych podatnociami aplikacjach - Firefox, Safari i Opera.
Ponadto wrd pamici wywietlanej w ramach obrazka w Firefox i Opera znajdoway
si wartoci ciasteczek nalecych do zewntrznych domen, umoliwiajc kradzie
sesji uytkownika.

Bd znaleziony przez jednego z autorw niniejszego tekstu (Gynvaela Coldwinda)


polega na nieprawidowej obsudze bitmap, ktre deklaroway istnienie palety o maym rozmiarze (np. jednego koloru), podczas gdy opisy poszczeglnych pikseli odwoyway si do wyszych indeksw palety kolorw. Ze wzgldu na fakt, e alokacja
odpowiadajca 256 kolorom bya inicjalizowana w tym przypadku tylko czciowo, na
ekranie bya wywietlana w wikszoci jej stara, niezdefiniowana zawarto. Wicej

18

informacji na ten temat znale mona w oficjalnym dokumencie advisory [12].

CIEKAWOSTKA

Z kolei podatno zidentyfikowana przez drugiego z autorw (Mateusza Jurczyka) bya


zwizana z obsug kodowania RLE (Run-Length Encoding), prostej metody kompresji stosowanej m.in. w formacie BMP i TIFF. Zachowaniem dekodera steruj zawarte w
sekcji danych obrazu rozkazy; jedn z moliwych komend jest nakazanie parserowi
potraktowanie kolejnych (znajdujcych si w pliku) od jednego do 127 bajtw jako
dane RGB opisujce kolejne piksele. Jeli po owej komendzie nie wystpowaa jednak wystarczajca ilo danych (plik koczy si w tym momencie), dekodery bdnie
wczytyway do danych obrazu bajty znajdujce si poza buforem danych pliku, co w
efekcie prowadzio do konsekwencji analogicznych do omwionego wyej problemu.
Zainteresowanych czytelnikw odsyamy do lektury dokumentu Firefox, Opera, Safari
for Windows BMP file handling information leak [13].
Obie usterki zostay znalezione i zgoszone blisko sze lat temu - nie oznacza to
jednak, e powane bdy uycia niezainicjalizowanej pamici nie byy od tego czasu
znajdowane - wrcz przeciwnie, w roku 2013 moglimy usysze o wielu ciekawych
przypadkach takich problemw - Micha Zalewski opisa podatno w bibliotekach libjpeg6b i libjpeg-turbo (uywanej przez wikszo przegldarek i aplikacji obsugujcych format JPEG) [14], Tavis Ormandy wyjani moliwo podniesienia uprawnie w
systemach Windows przy pomocy niezainicjalizowanego wskanika dynamicznie alokowanej struktury w graficznym komponencie jdra systemu Windows (win32k.sys)
[15], a francuska firma VUPEN wyeksploitowaa luk tej samej klasy w celu przejcia
kontroli nad przegldark Internet Explorer [16].

19

Stabilno i niezawodno

Kolizje w tablicach haszujcych


Tablice haszujce (ang. hash table) s jedn z najpopularniejszych i najczciej uywanych struktur danych w oprogramowaniu wszelkiego rodzaju. Struktura ta pozwala na tworzenie tablic asocjacyjnych o statystycznie
szybkim dostpie do elementw w sytuacjach, w ktrych uniwersum wartoci klucza jest znacznie wiksze od iloci wartoci, ktre przechowywane
s w owej tablicy; na przykad, kiedy kluczem mog by bardzo due liczby (dziesicocyfrowe i wiksze), cigi tekstowe lub zserializowane obiekty.
W najprostszym przypadku tablica haszujca moe mie posta zwykej tablicy t adresowanej liczbami naturalnymi , im wiksza warto n, tym szybszy
dostp do elementw, ale i wiksze zuycie pamici. Aby umoliwi indeksowanie tablicy dowolnymi obiektami, definiuje si tzw. funkcj haszujc h,
ktra w sposb deterministyczny odwzorowuje dowolny cig bajtw w liczb
z przedziau, zachowujc przy tym moliwie rwnomierny rozkad.
Poniewa powyszy zakres liczb jest znacznie mniejszy od liczby rnych
kluczy tablicy haszujcej, funkcja h w sposb oczywisty traci znaczn ilo
informacji o pocztkowym obiekcie. Z zasady szufladkowej Dirichleta wynika
wic, e w dostpie do tablicy t wczeniej czy pniej wystpi kolizje, tj.
rezultatem funkcji h dla dwch rnych obiektw bdzie jednakowa warto.
W celu obsuenia tego przypadku kada z komrek tablicy zamiast pojedynczej wartoci elementu przechowuje list wszystkich wartoci przypisanych
do danego hasha. Oznacza to, e jeli kady z kluczy uytych podczas wstawiania wartoci do tablicy zostanie przetumaczony na inny indeks tablicy t,
odczyt dowolnego elementu zajmie czas rzdu O(1). Z drugiej strony, jeli
zdarzy si, e wszystkie elementy znajd si pod tym samym indeksem,
kada z operacji na takiej tablicy moe wymaga wykonania krokw w liczbie wprost proporcjonalnej do liczby znajdujcej si w niej wartoci, podnoszc zoono pojedynczej operacji do O(n). W wikszoci przypadkw,
kiedy elementw w tablicy haszujcej jest niewiele lub klucze uywane do
ich zaadresowania dobrane s losowo (a przynajmniej nie maj one adnych
szczeglnych waciwoci wzgldem funkcji haszujcej), przecitny koszt
dostpu nie przekracza zazwyczaj rzdu O(lg n).

20

Skoro funkcje haszujce zachowuj si w sposb deterministyczny a dodatkowo sposb ich dziaania jest powszechnie znany dla wielu implementacji
(w szczeglnoci otwartych projektw), moemy wyobrazi sobie sytuacj,
w ktrej kto specjalnie preparuje wartoci kluczy tablicy asocjacyjnej w taki
sposb, by uyta funkcja h odwzorowaa kad z nich na t sam pozycj
w pomocniczej tablicy t. Jeli kod aplikacji nie spodziewa si wystpienia
tego pesymistycznego przypadku i z gry zakada, e kada z operacji na
tablicy jest szybka w zwizku z czym wykonuje takich operacji wiele, potencjalnie staje si moliwe znaczne wyduenie dziaania podatnej aplikacji.
Bd ten moe zosta naprawiony poprzez wprowadzenie pewnego elementu
losowoci - nie moe to by jednak losowy faktor powodujcy rnice w wyniku funkcji h dla tych samych danych wejciowych w obrbie tej samej sesji
programu (gdy jak pamitamy, dla poprawnoci dziaania tablicy haszujcej
wymagany jest determinizm funkcji h); powinien to by raczej element losowy wprowadzony podczas uruchomienia aplikacji i obowizujcy przez cay
czas jej dziaania.
Przede wszystkim naley jednak pamita, e tam, gdzie przetwarzane s
dane dostarczane przez uytkownika, wszystko co moe pj nie tak - pjdzie nie tak, gdy atakujcy bardzo chtnie wykorzysta wszystkie dostpne
moliwoci zaatakowania systemu. Jak si okazuje, zasada ta dotyczy nie
tylko bdw zwizanych bezporednio z jawnie nieprawidowym przetwarzaniem danych wejciowych (kiedy s one uywane w niebezpiecznych operacjach arytmetycznych lub jako cz zapytania do bazy danych), lecz moe
by zastosowana rwnie dla problemw optymalizacyjnych, kiedy aplikacja
czyni niekoniecznie prawidowe zaoenia na temat natury (formatu, struktury, treci) danych wejciowych.

Problem opisany w tej sekcji okazuje si nie by wycznie tworem teoretycznych


rozwaa - pod koniec 2011 roku na konferencji 28C3 badacze Julian Wlde i Alexander Klink zaprezentowali przykady praktycznych atakw przeciwko przewidywalnoci
funkcji haszujcych zaimplementowanych w technologiach i jzykach programowania
takich jak PHP, Java, .NET, v8, Ruby oraz Python, umoliwiajc przeprowadzanie skutecznych atakw typu odmowy usugi (ang. Denial of Service) niewielkim kosztem obliczeniowym oraz przepustowoci sieciowej, poprzez wymuszenie na serwerze przetwarzania zapytania o zoonoci O(n2), tym samym konsumujc nieproporcjonalnie
du ilo czasu serwera i w przypadku wikszej liczby takich zapyta wysyanych na
raz - potencjalnie cakowicie uniemoliwiajc prac serwisu internetowego. Problem
zosta uznany za tak powany i zagraajcy oglnej stabilnoci sieci, e Microsoft ju
nastpnego dnia po publicznym ujawnieniu podatnoci wyda atk naprawiajc bd
w ASP.NET, amic w tym wyjtkowym przypadku regu zbiorczego publikowania

CIEKAWOSTKA

21

CIEKAWOSTKA

poprawek w kady drugi wtorek miesica (dzie znany jako Patch Tuesday - w wolnym
tumaczeniu atkowy Wtorek). Wkrtce za gigantem z Redmond poszy inne projekty oraz producenci, naprawiajc bd poprzez wprowadzenie do implementacji tablic
haszujcych elementu losowoci uniemoliwiajcego przewidzenie, jakie cigi tekstowe spowoduj kolizj funkcji haszujcej. Zainteresowanych czytelnikw zapraszamy
do obejrzenia nagrania ze wspomnianej wczeniej prelekcji [17], a take zajrzenia
do artykuw opisujcych rozwj sytuacji w kilka dni po ogoszeniu informacji o problemie [18] [19].

Wyszukiwanie wszystkiego
Zazwyczaj kady wikszy serwis webowy posiada wyszukiwark, ktra
w zaoeniu ma pozwoli szybko znale podan tre w obrbie danej
strony. Przykadowo, funkcjonalno ta moe by realizowana poprzez
wysanie dania w formacie podobnym do nastpujcego:
http://example.com/szukaj?co=koty&ile=10

Takie danie moe nastpnie trafi do funkcji, ktra na jego podstawie


wykonuje zapytanie do bazy danych i zwraca wyniki. Np.:
# PHP
function Szukaj() {
global $db;
$sql = 'SELECT link, text FROM search_table WHERE text LIKE :co LIMIT
:ile';
$s = $db->prepare($sql);
$s->bindParam(':co', '%' . $_GET['co'] . '%');
$s->bindParam(':ile', $_GET['ile'], PDO::PARAM_INT);
$s->execute();
return $s->fetchAll(PDO::FETCH_ASSOC);
}

O ile na pierwszy rzut oka wszystko wyglda poprawnie, o tyle problem


zaczyna si, jeli atakujcy wykona zapytanie typu "?q=%&ile=1000000",
ktre mona przetumaczy na znajd i wywietl wszystko - obciy to
zarwno baz danych, jak i sam skrypt PHP. Przykadowo, jeli dany serwis posiada 100 000 podstron, to zwrcone zostanie 100 000 wynikw,
ktre musz najpierw zosta przesane z bazy danych do silnika PHP,
nastpnie obrobione przez skrypt, a pniej wysane do uytkownika.
Oczywicie, jedno zapytanie tego typu jest w zasadzie niegrone, ale
naley pamita, e atakujcy moe np. ustawi to zapytanie jako swj
awatar na popularnym forum internetowym - spowoduje to, e przegldarka kadego uytkownika tego forum bezwiednie wyle powysze zapytanie w oczekiwaniu na zwrotny obrazek. Dua liczba takich zapyta

22

moe niestety zarwno znacznie obciy serwer, jak i cze na ktrym


stoi serwis.
Prawidowe podejcie do powyszego problemu zakada:
Ograniczenie liczby wywietlanych wynikw do sensownej liczby
(np. 100).
Wymaganie, aby tekst ktrego si szuka mia przynajmniej kilka
znakw (zazwyczaj 3).
Poprzedzenie znakw % w zapytaniu odpowiednimi sekwencjami
ucieczki (tak, eby % by traktowany po prostu jako znak %,
a nie maska).

23

Wielowtkowo
i wielozadaniowo
Wycigi w systemie
Jednym z najciekawszych bdw popenianych podczas tworzenia kodu dziaajcego w wielowtkowym, wielozadaniowym rodowisku jest tzw. TOCTTOU
(czyt. tok tu). Bd ten polega na bdnym zaoeniu, e wspdzielony zasb
nie zmieni niespodziewanie swoich waciwoci pomidzy odwoaniami do niego
w kontekcie tego samego zadania. Nazwa TOCTTOU (ang. Time Of Check To
Time Of Use), ktr mona dosownie przetumaczy na moment sprawdzenia
kontra moment uycia wywodzi si z typowego, bdnego schematu kodu:
W kroku pierwszym nastpuje sprawdzenie, czy wspdzielony zasb jest
poprawny (jeli nie, nastpuje przerwanie dziaania).
W drugim kroku wspdzielony zasb zostaje uyty.
Przykadowy kod zawierajcy opisany wyej schemat:
# Python
def PrzeliczWalute(kwota):
global kurs
# Czy znamy aktualny kurs?
if kurs == 0:
return False
DodajDoLogow("PrzeliczWalute", kwota, kurs)
return kwota / kurs

W powyszym kodzie, ktry mgby by czci wikszego systemu (np. obsugujcego kantor internetowy), mamy globaln zmienn kurs, ktra jest cigle
uaktualniana przez inny, istniejcy w systemie wtek, pobierajcy aktualny kurs
waluty z zewntrznych serwerw. Szczeglnym przypadkiem jest bdny kurs
rwny 0, ustawiany gdy ostatnia prba pobrania kursu zakoczya si bdem
(np. w wyniku chwilowego braku cznoci).
Kod na pierwszy rzut oka moe wydawa si poprawny - najpierw nastpuje
sprawdzenie czy aktualny kurs jest dostpny, a dopiero pniej dochodzi do

24

wykonania oblicze. I tu wanie tkwi problem - pomidzy sprawdzeniem, a


faktycznym uyciem zmiennej, inny wtek moe zmieni jej warto na 0. W
takim wypadku dojdzie do dzielenia przez zero i zostanie rzucony potencjalnie nieprzewidziany wyjtek.
Z TOCTTOU mona poradzi sobie na kilka sposobw (w zalenoci od konkretnej sytuacji):
Zazwyczaj najlepiej jest synchronizowa dostp do wspdzielonego
zasobu, tak aby tylko jeden klient na raz mg na nim operowa.
W niektrych przypadkach (jeli ograniczamy uycie zasobu do jego
odczytw) wystarczy wykona lokaln kopi wartoci danego zasobu
i operowa jedynie na kopii - dziki temu zapobiegamy niespodziewanej zmianie wanoci.

Jednym z problemw wystpujcych na dzielonych hostingach oferujcych PHP by


dostp do plikw, ktrych wacicielem nie by waciciel skryptu PHP. Wynika to m.in.
z uywanej czasami konfiguracji, w ktrej silnik PHP dziaa z uprawnieniami serwera
WWW i jako taki musi mie dostp do plikw stron WWW (wraz ze skryptami PHP)
wszystkich uytkownikw na danym hostingu.

CIEKAWOSTKA

Jednym z (nienajlepszych) rozwiza jest uycie tzw. funkcjonalnoci open_basedir w konfiguracji PHP - jest to opcja okrelajca, do jakich katalogw silnik PHP
ma zezwala na dostp - opcje t mona ustawi np. dla konkretnej domeny lub konkretnego uytkownika. W takim przypadku, jeli skrypt prbuje otworzy pewien plik
nastpuje najpierw sprawdzenie, czy w plik ley w katalogu znajdujcym si na licie
open_basedir.
Fragment przykadowej konfiguracji serwera Apache z PHP oraz opcj open_basedir moe wyglda nastpujco:
<VirtualHost *:80>
...
ServerName alice.example.com
php_admin_value open_basedir /home/alice/alice.example.com/
<Directory /home/alice/alice.example.com/>
...
allow from all
</Directory>
...
</VirtualHost>
<VirtualHost *:80>
...
ServerName mallory.example.com

25

CIEKAWOSTKA

php_admin_value open_basedir /home/mallory/mallory.example.


com/
<Directory /home/mallory/mallory.example.com/>
...
allow from all
</Directory>
...
</VirtualHost>
W padzierniku 2006 roku znany badacz Stefan Esser znalaz prost luk typu TOCTTOU, pozwalajc omin restrykcje zwizane z open_basedir [20]. Bd wynika z
prostego faktu, e pomidzy sprawdzeniem, czy dana cieka prowadzi do pliku (lub
katalogu), ktry ley w drzewie wymienionym w open_basedir, a faktycznym otwarciem danego pliku, mija troch czasu. W zwizku z tym, jeli cieka w danym momencie wskazywaaby na zasb do ktrego skrypt powinien mie dostp, tym samym
przechodzc test, a nastpnie zostaaby zmieniona (korzystajc z mechanizmu linkw
symbolicznych) by wskazywa na np. plik innego uytkownika, ostatecznie otwarty
zostaby wanie plik innego uytkownika.
Badacz zaproponowa, e mona osign to uruchamiajc jednoczenie dwa skrypty
PHP. Pierwszy prbowaby (a do skutku) odczyta zawarto pliku innego uytkownika, np. xxx/home/alice/tajne.dane. Drugi natomiast skadaby si z nastpujcego
kodu PHP:
mkdir("a/a/a/a/a/a");
while(1) {
symlink("a/a/a/a/a/a", "dummy");
symlink("dummy/../../../../../../", "xxx");
unlink("dummy");
symlink(".", "dummy");
}
W przypadku wygranego wycigu (tj. gdy podmiana linku symbolicznego nastpi
w odpowiednim momencie) test open_basedir widziaby prb dostpu do pliku
a/a/a/a/a/a/../../../../../../../home/alice/tajne.dane, czyli po prostu ./home/alice/tajne.
dane - a to jest jak najbardziej zgodne z open_basedir. Kilka krokw pniej otwarty zostaby plik ./../../../../../../home/alice/tajne.dane - czyli plik tajne.dane w katalogu
domowym uytkownika Alice.
Co ciekawe, bd ten by o tyle specyficzny, e jego rozwizaniem bya sugestia wyczenia funkcji symlink w konfiguracji PHP [21], oraz stwierdzenie, e open_basedir
nigdy nie mia by barier midzy uytkownikami dziaajcymi na tym samym serwerze [22].

26

Dane wejciowe

Deserializacja niezaufanych danych


Tworzc serwisy WWW w niektrych sytuacjach wygodnie jest wymienia
z przegldark dane w postaci zserializowanej. Dziki takiemu rozwizaniu
po stronie serwera wystarczy dane zdeserializowa i od razu mona zacz
ich uywa, bez wczeniejszej konwersji typw, tworzenia tablic czy obiektw - wszystko to ma miejsce automatycznie podczas procesu deserializacji.
W takich przypadkach oczywicie skrypt po stronie klienta albo musi odpowiednio zserializowa dane, albo przekaza serwerowi zserializowane dane,
ktre otrzyma od niego na przechowanie poprzednio (mog to by np.
wybrane preferencje uytkownika).
Przykadowy kod realizujcy odbir danych:
# Python
def OdbierzDane(parametry):
if "obiekt" not in parametry:
return False
return pickle.loads(parametry["obiekt"])
// PHP
function OdbierzDane() {
if(!isset($_POST["obiekt"]))
return false;
return unserialize($_POST["obiekt"]);
}

Metody serializacji mona podzieli na proste, ktre obsuguj jedynie podstawowe typy i struktury (np. JSON), oraz bardziej zoone, ktre mog
przechowywa rwnie obiekty rnych klas (np. uyte wyej Pickle i PHP serialize/unserialize). Serializacja i deserializacja obiektw to proces bardziej
skomplikowany - wynika z faktu, e obiekt to nie tylko zbir wartoci, ale
czsto rwnie rne dodatkowe meta-informacje, ktre nie wynikaj bezporednio z wartoci pl obiektu (takie jak np. aktywne poczenie sieciowe,
czy uchwyt otwartego pliku). Z tego te powodu przy deserializacji obiektu
nie wystarczy odtworzy wartoci zmiennych; trzeba rwnie obiekt obudzi - czyli np. otworzy odpowiednie pliki, wznowi poczenia sieciowe itp.

27

Poniewa niemoliwym jest aby kod funkcji deserializujcej umia obudzi


obiekty wszystkich istniejcych klas, zadanie to spada na sam klas, a konkretniej, na specjalne metody, ktre s wywoywane podczas deserializacji.
Nazwy oraz budowa metod zalene s oczywicie od konkretnego serializera; przykadowo, podczas deserializacji:
Pickle wywouje metod __setstate__ dla danego obiektu (oczywicie, o ile
takowa istnieje).
PHP unserialize wywouje metod __wakeup.
Gdyby spojrze na ten problem z perspektywy deserializacji niezaufanych
danych, okazuje si, e skoro potencjalny atakujcy moe kontrolowa typy
danych w zserializowanym pakiecie, to moe on rwnie spowodowa wywoanie metod budzcych dany obiekt na danych kontrolowanych przez siebie.
Co wicej, skoro przy deserializacji dany obiekt zostaje na nowo stworzony,
to w pewnym momencie dziaania skryptu zostanie on rwnie zniszczony, a
wtedy wywoany zostanie oczywicie destruktor (dla naszych przykadowych
jzykw jest to: metoda __del__ w Pythonie, oraz __destruct w PHP), ktry
rwnie bdzie operowa na wartociach pl wybranych przez atakujcego.
Czy takie sprowokowanie wywoania funkcji budzcych oraz destruktorw
powoduje powaniejsze problemy? Okazuje si, e tak.

CIEKAWOSTKA

W lutym 2013 Egidio Romano opublikowa informacj o bdzie zwizanym z deserializacj niezaufanych danych w popularnym silniku CMS Joomla! [23]. Badacz wskaza
destruktor klasy plgSystemDebug, ktry w pewnym momencie wykonywa nastpujcy
kod:
$filterGroups = (array) $this->params->get('filter_groups',
null);
Z uwagi na to, e atakujcy kontrolowa rwnie typ pola params w obiekcie, mg on
doprowadzi do wywoania metody get w dowolnej innej istniejcej klasie (oczywicie
pod warunkiem, e metoda get w danej klasie istniaa). Badacz wskaza dwie moliwoci przeprowadzenia ataku dalej:
Metod get w klasie JInput, ktra wywouje metod clean na innym kontrolowanym obiekcie. Metod clean mona byo znale w klasie JCacheStorageFile i pozwalaa ona na usunicie dowolnego katalogu, wraz z zawartoci, co
mogo spowodowa utrat danych.
Jeszcze ciekawsza metoda get zostaa odnaleziona w klasie JCategories
- doprowadzenie do jej wywoania pozwalao atakujcemu na wykonanie
czciowo kontrolowanego zapytania do bazy SQL, a w konsekwencji do
wycieku danych z bazy.

28

O ile w przypadku PHP powaga potencjalnych konsekwencji deserializacji


niezaufanego cigu w znacznym stopniu zaley od tego, jakie klasy s obecne w aplikacji, o tyle w przypadku jzyka Python oraz biblioteki Pickle sytuacja przedstawia si znacznie gorzej. Wynika to z metody dziaania Pickle
- zserializowane dane s w zasadzie mini-programem, ktry ma na celu odbudowanie danych do ich pierwotnej postaci (tj. tej sprzed serializacji). Podczas deserializacji niewielki interpreter wykonuje w mini-program, a jego
rezultatem s listy, obiekty itp. Oczywicie w takim wypadku konsekwencje
zale gwnie od moliwoci dopuszczanych przez interpreter - a te, jak si
okazuje, s znaczce z uwagi na instrukcj R. W tym miejscu warto wspomc si rdami interpretera Pythona (Python 2.7.3, Lib/pickle.py):
REDUCE
= 'R'
# apply callable to argtuple, both on stack
...
def load_reduce(self):
stack = self.stack
args = stack.pop()
func = stack[-1]
value = func(*args)
stack[-1] = value
dispatch[REDUCE] = load_reduce

Jak mona wywnioskowa z powyszego kodu, instrukcja R ciga ze stosu


maszyny wirtualnej funkcj do wywoania (nazw funkcji oraz moduu mona umieci na stosie za pomoc instrukcji c), oraz jej argumentu, po czym
j wywouje. W rezultacie deserializacja niezaufanych danych moe doprowadzi do wykonania dowolnego kodu przez atakujcego, a w konsekwencji
do przejcia przez niego kontroli nad aplikacj.

Deserializacja niezaufanych danych nie jest domen tylko i wycznie aplikacji webowych. W roku 2011 Marco Slaviero zgosi bd w systemie serwerowym Red Hat dziki
ktremu, wanie za pomoc spreparowanych danych, by wstanie podnie uprawnienia swojego uytkownika do penych uprawnie konta root [24].

CIEKAWOSTKA

Bd znajdowa si w backendzie graficznego interfejsu sucego do zarzdzania firewallem - system-config-firewall, a konkretniej w skrypcie system-config-firewall-mechanism.py, ktry dziaa z uprawnieniami root. Podatny kod wyglda nastpujco [25]:
@dbus.service.method(DBUS_DOMAIN, in_signature='s', out_signature='i')
def write(self, rep):
try:
args = pickle.loads(rep.encode('utf-8'))
except:
return -1

W powyszym kodzie argument wyeksportowanej przez DBUS metody write by bez-

29

CIEKAWOSTKA

porednio poddawany deserializacji. Poniewa dowolny uytkownik systemu mia prawa (korzystajc z DBUS) do wywoania metody write, mg rwnie doprowadzi do
wykonania zdefiniowanego przez siebie kodu (np. nadajcego mu pene uprawnienia
administratora).
Bd zosta naprawiony poprzez zastpienie Pickle duo prostszym formatem JSON.

Podsumowujc - w kodzie, w ktrym zaley nam na bezpieczestwie, powinno unika si wykonywania zoonych deserializacji. Na przykad, zamiast
Pickle w Pythonie czy serialize/unserialize w PHP moemy uy formatu JSON
(ktry jest duo prostszy i sam w sobie nie oferuje serializacji zoonych
obiektw) co automatycznie eliminuje wszystkie opisane wyej problemy.
W przypadku w ktrym klient podaje nam jedynie zserializowane dane, ktre
wczeniej otrzyma od serwera, mona zastosowa HMAC w celu upewnienia
si, e dane nie zostay zmienione przez uytkownika.

30

Logika aplikacji

Oscylatory walutowe
Jednym z ciekawszych bdw logiki aplikacji bankowych s bdy zaokrglenia, czasem nazywane oscylatorami walutowymi. Przykadowy schemat takiego
oscylatora wyglda nastpujco (na potrzeby przykadu zamy, e kurs EUR/
PLN wynosi 4.00):
1. Atakujcy zakada dwa konta w banku: walutowe (w EUR) oraz w natyw2.
3.
4.
5.
6.
7.

nej walucie (PLN).


Przelewa na konto PLN niewielk sum pienidzy (wystarczy kilka groszy).
Przelewa 3 grosze z konta w PLN na konto walutowe w EUR.
(jeli bd wystpuje) Na koncie EUR pojawia si 1 eurocent (0.01 EUR)
z uwagi na zaokrglenie w gr.
Nastpnie atakujcy przelewa 0.01 EUR z konta walutowego na konto
w PLN.
(jeli bd wystpuje) Na koncie w PLN pojawiaj si 4 grosze (a wic
o 33% wicej).
Punkty 3-6 s powtarzane w nieskoczono, a atakujcy za kadym
razem zyskuje jeden grosz).

Dziaanie powyszego oscylatora mona utrudni na kilka sposobw:


Wprowadzajc niewielk, sta, opat od wymiany walut, jeli transakcja

jest poniej pewnej kwoty.


Blokujc moliwo robienia niewielkich przeleww.
Mona rwnie zlicza rnic wynikajc z zaokrglenia i j wyrwnywa
(a wic jeli w danej transakcji klient zyska np. 1 grosz, to byyby on odejmowany przy nastpnej transakcji w drug stron).

Bardzo dobry opis oscylatorw walutowych bazujcych na bdzie zaokrglenia przedstawi, na odbywajcej si w Paryu konferencji Nuit du Hack 2013 (a pniej na odbywajcej si w Moskwie konferencji ZeroNights 2013), badacz Adrian Furtuna [26] [27].
Oprcz obszernego wytumaczenia tematu, badacz zaprezentowa rwnie wasnej

CIEKAWOSTKA

31

CIEKAWOSTKA

produkcji urzdzenie pozwalajce zautomatyzowa dokonywanie przeleww wymagajcych potwierdzenia tokenem. Urzdzenie wprowadzao kod transakcji w tokenie, po
czym odczytywao go za pomoc kamery sprzonej z OCR; nastpnie kod mg zosta uyty do zatwierdzenia przelewu.

Fotografia: Adrian Furtun, Practical exploitation of rounding vulnerabilities


in internet banking applications
Wedug przedstawionych wylicze, urzdzenie pozwalao na wykonanie do 14400
zautomatyzowanych transakcji dziennie, co w przypadku opisanym przez badacza,
mogo generowa do 68 USD (korzystajc tylko z jednego konta).

CIEKAWOSTKA

32

Warto rwnie przeczyta artyku EURO page: Conversion Arithmetics autorstwa Keesa Vuika [28], w ktrym autor wyjania problemy zwizane z zaokrgleniem przy przejciu danego kraju z lokalnej waluty na EURO.

Dziwactwa

Nierwne rwnoci
Jednym z problemw wystpujcych w jzykach o sabym typowaniu jest porwnywanie zmiennych o rnych typach - wymaga to zazwyczaj konwersji
danych, a nie zawsze jest oczywiste w jaki sposb to zrobi. Czasami dochodzi wic do sytuacji, ktre mog zaskoczy niejednego programist - a co za
tym idzie, doprowadzi do zaistnienia bdu. Z tego powodu jzyki programowania tego typu posiadaj czsto dwa rne operatory porwnania - tzw.
operator rwnoci wartoci (zazwyczaj zapisywany jako ==), oraz operator
rwnoci wartoci i typu (zazwyczaj zapisywany jako ===). Przykadami takich jzykw mog by JavaScript oraz PHP.
Poniej znajduje si kilka przykadw pochodzcych z jzyka PHP - wszystkie
ponisze porwnania daj w wyniku warto true, a wic porwnane wartoci
s uznawane za rwne [29]:
"1000" == "0x3e8"
"1234" == "
\t\r\n 1234"
"1234512345123451234512345" == "1234512345123451234512346"

(dla wersji 5.4.3 oraz starszych)

5 == "5 tysiecy"
9223372036854775807 == 9223372036854775808 (dla 64-bitowych wersji

PHP)

0 == "ala ma kota"
fopen('plik', 'w') == "0.002e3" (pod warunkiem, e fopen zwrci

zasb o ID rwnym #2)

Najlepszym sposobem na uniknicie nieprzewidzianych problemw zwizanych z porwnaniami jest konsekwentne stosowanie operatora silnego porwnania (===), z wyjtkiem konkretnych miejsc, w ktrych sabe porwnanie dziaa dokadnie tak, jak tego oczekujemy.

33

CIEKAWOSTKA

W sierpniu roku 2012 Arseny Reutov, badacz z Positive Research Center, znalaz
powan luk w popularnym silniku forum internetowego Simple Machines Forum,
pozwalajc na przejcie konta dowolnego uytkownika, w tym administratora.
Bd znajdowa si w kodzie, ktrego zadaniem bya weryfikacja wygenerowanego
wczeniej kodu pozwalajcego zresetowa zapomniane haso do konta. Kod korzysta z operatora sabej rwnoci (a raczej nierwnoci w tym wypadku) i wyglda
nastpujco:
if (/* ... */ || substr($realCode, 0, 10) != substr(md5($_POST['code']),
0, 10))
// ... kod si nie zgadza; poka bd ...

Powyszy kod sprawdza, czy pierwsze dziesi znakw kodu jest rwne pierwszym dziesiciu znakom sumy MD5 z podanego przez uytkownika (atakujcego)
kodu. W tym przypadku celem atakujcego byo wylosowanie takiego $realCode
(poprzez wielokrotne prby odzyskania hasa - a wic wielokrotne re-generowania
$realCode), eby zaczyna si on od znakw 0e lub 1e, a po nich nastpoway
jedynie cyfry dziesitne, np.:
0e71264128 lub 1e95723510
Oczywicie, atakujcy nie zna poprawnego kodu, ale i nie musia go zna. Naley
zwrci uwag, e z punktu widzenia PHP oraz sabego porwnania, powysze
wartoci to jedynie liczby typu float w notacji naukowej, ktre s rwne 0 (w kocu
0 * 1071264128 to po prostu 0) lub 1. Wystarczao wic, aby atakujcy w pole code
wpisa dowolny cig, ktrego pierwsze dziesi znakw sumy MD5 rwnie miao
form 0e<cyfry> lub 1e<cyfry>.
Na przykad, dla podanej wyej wartoci (0e71264128) wystarczyo poda kod
astronavigation, poniewa, pierwsze dziesi znakw sumy MD5 tego sowa
to 0e86666438 (czyli rwnie warto 0).
> php -a
Interactive shell
php > var_dump("0e71264128" == substr(md5("astronavigation"), 0, 10));
bool(true)

Bd zosta naprawiony w lutym ubiegego roku [30].

34

Kryptografia

Wartoci (nie)losowe
Podczas tworzenia serwisw webowych oraz podobnych aplikacji dziaajcych po stronie serwera, czasem zachodzi konieczno wygenerowania
losowego, trudnego do zgadnicia cigu znakw. Taki cig moe zosta
uyty jako np.:
Identyfikator sesji uytkownika.
Pocztkowe haso do konta uytkownika (ustalane przy tworzeniu



konta).
Kod pozwalajcy zresetowa haso uytkownika.
CAPTCHA.
Unikatowa nazwa pliku lub podobnego rodzaju identyfikator
zasobu.
Token anti-XSRF [31].

Przykadowy, bdny kod generujcy losowy cig w PHP moe wyglda


nastpujco:
function WygenerujToken($dlugosc) {
$token = "";
$alfabet = "abcdefghijklmnopqrstuvwxyz";
for($i = 0; $i < $dlugosc; $i++)
$token .= $alfabet[mt_rand(0,25)];
}

return $token;

Problem w powyszym kodzie polega na uyciu tzw. kryptograficznie niebezpiecznego generatora liczb losowych (w tym wypadku jest to mt_rand
korzystajcy z algorytmu Mersenne Twister [32]). Atakujcy dysponujcy jednym lub kilkoma tokenami moe sprbowa zrekonstruowa wewntrzny stan generatora, a co za tym idzie, odtworzy wygenerowane
wczeniej oraz/lub pniej tokeny (na wspczesnym komputerze jest to
w przypadku Mersenne Twister kwestia kilku sekund).

35

Do generowania losowych cigw, na ktrych ma opiera si bezpieczestwo systemu, powinno uywa si tzw. kryptograficznie bezpiecznych
generatorw. Wikszo technologii udostpnia programistom odpowiednie mechanizmy pozwalajce na wygenerowanie bezpiecznych liczb losowych, na przykad:





CIEKAWOSTKA

PHP: openssl_random_pseudo_bytes
Python: os.urandom
Java: java.security.SecureRandom
Ruby: SecureRandom
Windows: CryptoGenRandom
GNU/Linux: pseudo-urzdzenia /dev/random lub /dev/urandom

Niestety zdarza si, e bdy pojawiaj si rwnie w funkcjach, ktre z zaoenia miay
generowa kryptograficznie bezpieczne wartoci.
W roku 2008 znaleziono bd w generatorze liczb losowych biblioteki OpenSSL dystrybuowanej z systemami z rodziny Debian [33]. Okazao si, e z uwagi na niewielkie
zmiany w kodzie entropia generatora liczb losowych spada do 16-bitw, przez co np.
OpenSSH generujcy klucz SSH RSA by w stanie wygenerowa jedynie 65536 rnych, przewidywalnych par kluczy. W takim wypadku wystarczyo aby atakujcy wygenerowa wszystkie moliwe klucze u siebie, a nastpnie mg uzyska dostp do konta
uytkownika, ktry mia ustawion autoryzacje na jeden z wadliwych kluczy.
Inny powany przypadek odkryty w zeszym roku dotyczy platformy Android. W tym wypadku generator liczb losowych biblioteki OpenSSL by nieprawidowo inicjalizowany,
przez co generowane klucze stay si przewidywalne [34]. Niestety, podobno doprowadzio to do kradziey pewnej sumy kryptowaluty Bitcoin przechowywanej na portfelach,
do ktrych klucze zostay wygenerowane wadliwym generatorem.

36

Przenono kodu

Nazwy plikw
Przenoszenie kodu midzy rnymi platformami jest z jednej strony atwe - caa logika pozostaje niezmieniona - ale z drugiej strony natrafia si
na drobne rnice sprawiajce, e kod zachowuje si inaczej na rnych
systemach. Jedn z oczywistych rnic midzy systemami operacyjnymi
jest kwestia systemu plikw, a w szczeglnoci nazw plikw. Chodzi tutaj
zarwno o proste kwestie jak np. czy dany znak moe wystpi w nazwie
pliku lub katalogu, jak i bardziej skomplikowane, takie jak dodatkowe
moliwoci niektrych systemw plikw.
Ponisza tabela zawiera kilka przykadowych rnic pomidzy typowymi
systemami plikw uywanymi na systemach GNU/Linux (np. ext3) oraz
Windows (NTFS):

Windows

GNU/Linux

Separatorem nazw katalogw i plikw


moe by zarwno znak / (slash) jak i \
(backslash).

Separatorem nazw katalogw i plikw jest


znak / (slash).

Znaki < > oraz \ nie mog wystpi


w nazwie pliku lub katalogu.

Znaki < > oraz \ mog wystpi w nazwie


pliku lub katalogu.

Do pliku XYZ mona odwoa si uywajc Pliki XYZ oraz xyz to dwa rne pliki.
nazwy xyz, jak i xYz, itd. Co wicej, mona te skorzysta z nazwy xyz...................,
xyz
, jak i (w przypadku NTFS)
xyz::$DATA.
Maksymalna dugo cieki to 32767
znakw.

Brak limitu dugoci cieki.

Tylko administrator moe tworzy linki symboliczne.

Dowolny uytkownik moe tworzy linki symboliczne.

37

Powysze rnice staj si niesamowicie istotne w przypadku programw,


ktre musz podj decyzj bazujc na nazwie pliku (lub ciece) otrzymanej od zewntrznego uytkownika. Przykadem moe by poniszy kod:
def CzyMoznaWyswietlicPlik(nazwa):
return nazwa.find("config") == -1

Powyszy kod ma decydowa, czy dany plik moe zosta wywietlony


uytkownikowi - w tym przypadku jedynym ograniczeniem jest zabronienie
wywietlenia dowolnego pliku, ktry ma w nazwie (pliku lub cieki) sowo
config. Oczywicie, o ile funkcja ta bdzie poprawnie dziaa na systemach
z rodziny GNU/Linux, to w przypadku Windowsa uytkownik moe po prostu
zada pliku CoNfIg i to wystarczy aby obej ten filtr.
W poprawnym kodzie zamiast zabrania dostpu do konkretnych plikw,
pozwolibymy na dostp jedynie do niektrych, uniemoliwiajc dostp do
wszystkich innych. W innym wypadku naleaoby zaproponowa oddzieln
logik dla rnych systemw operacyjnych.

CIEKAWOSTKA

38

Na bd tego typu natrafili twrcy serwera WWW Lighttpd. Okazao si, e o ile odwoanie typu http://example.com/index.php dziaao zgodnie z zaoeniami (tj. skrypt PHP
by wykonywany), o tyle http://example.com/index.php::$DATA powodowao wywietlenie rde skryptu PHP [35] - wynikao to z zasady dziaania alternatywnych strumieni
(ADS) w systemie plikw NTFS. Ostatecznie bd nie zosta poprawiony, pojawia si
jedynie sugestia, aby na platformie Windows nie zezwala na pojawienie si dwukroptka w nazwie zasobu. Warto nadmieni, e podobne problemy wystpiy w roku 1998
w serwerze Microsoft IIS [36].

Zakoczenie

Jak pokazalimy w artykule, bdy towarzyszyy programistom ju dziesitki


lat temu, i towarzysz im wci po dzi dzie, zmieniajc jedynie natur oraz
technologie zgodnie z najnowszymi trendami w wiatku rozwoju oprogramowania. Biorc pod uwag olbrzymi liczb ludzi zajmujcych si zawodowo programowaniem oraz zwyczajn ludzk omylno, mona pokusi si o
stwierdzenie, e wszystkie moliwe pomyki w kodzie zostay ju popenione
- niektre z nich miay jednak zaskakujce objawy oraz konsekwencje, nierzadko czynic systemy informatyczne podatnymi na rnego rodzaju ataki zagraajce bezpieczestwu danych uytkownikw lub powodujc inne,
znaczce straty. Pamitajmy wic, by starannie pisa kod starajc si przewidzie wszelkie przypadki brzegowe, w adnym wypadku nie ufa danym
pochodzcym od (potencjalnie wrogiego) uytkownika, a przede wszystkim
wszechstronnie i wyczerpujco testowa i audytowa rozwijane oprogramowanie - w przeciwnym wypadku ryzykujemy znalezieniem si w kolejnym
opracowaniu najciekawszych bdw w historii software, czego sobie ani Czytelnikowi oczywicie nie yczymy.

Mateusz (po lewej) od wielu lat pasjonuje si tematyk bezpieczestwa komputerowego - specjalizuje si w metodach odnajdowania oraz
wykorzystywania podatnoci w popularnych aplikacjach klienckich oraz systemach operacyjnych.
Na codzie pracuje w firmie Google na stanowisku
Information Security Engineer, w wolnych chwilach
prowadzi bloga zwizanego z bezpieczestwem
niskopoziomowym (http://j00ru.vexillium.org).

AUTORZY

Gynvael na co dzie pracuje w firmie Google na stanowisku Information Security


Engineer. Po godzinach prowadzi bloga oraz nagrywa podcasty o programowaniu
(http://gynvael.coldwind.pl/). Hobbystycznie programuje od ponad 20 lat.

39

Bibliografia

[1] Goudey H. (2013). Chrome on a Nexus 4 and Samsung Galaxy S4 falls.


http://h30499.www3.hp.com/t5/HP-Security-Research-Blog/Chrome-on-a-Nexus-4-andSamsung-Galaxy-S4-falls/ba-p/6268679
[2] Microsoft Corporation. SafeInt. http://safeint.codeplex.com/
[3] Kees Vuik. Some disasters caused by numerical errors.
http://ta.twi.tudelft.nl/users/vuik/wi211/disasters.html
[4] James Gleick. A Bug and a Crash (Sometimes a Bug Is More Than a Nuisance).
http://www.around.com/ariane.html
[5] Wikipedia. Cluster (spacecraft). http://en.wikipedia.org/wiki/Cluster_(spacecraft)
[6] Jean-Marc Jezequel (IRISA), Bertrand Meyer (ISE).
Design by Contract: The Lessons of Ariane.
http://archive.eiffel.com/doc/manuals/technology/contract/ariane/
[7] Niebezpiecznik. Gbokie ukrycie danych w PKO BP.
http://niebezpiecznik.pl/post/glebokie-ukrycie-danych-w-pko-bp/
[8] Niebezpiecznik. 7 000 polskich CV w gbokim ukryciu.
http://niebezpiecznik.pl/post/7-000-cv-w-glebokim-ukryciu/
[9] Niebezpiecznik. Gbokie ukrycie na video.
http://niebezpiecznik.pl/post/glebokie-ukrycie-na-video
[10] Wikipedia. Gbokie ukrycie. http://pl.wikipedia.org/wiki/G%C5%82%C4%99bokie_ukrycie
[11] Pawe Gole. O gbokim ukryciu nieco inaczej.
http://wampir.mroczna-zaloga.org/archives/1084-o-glebokim-ukryciu-nieco-inaczej.html
[12] Gynvael Coldwind. FireFox 2.0.0.11 and Opera 9.50 beta Remote Memory Information
Leak. http://vexillium.org/?sec-ff
[13] Mateusz j00ru Jurczyk. Firefox, Opera, Safari for Windows BMP file handling information leak.
http://gynvael.vexillium.org/ext/vc/shadow_002/mateusz_j00ru_jurczyk_memory_leak_2008.pdf
[14] Michal Zalewski. Bugs in IJG jpeg6b & libjpeg-turbo.
http://seclists.org/fulldisclosure/2013/Nov/83
[15] Tavis Ormandy. Introduction to Windows Kernel Security Research.
http://blog.cmpxchg8b.com/2013/05/introduction-to-windows-kernel-security.html
[16] Nicolas Joly (VUPEN). Advanced Exploitation of IE MSXML Remote Uninitialized Memory
(MS12-043 / CVE-2012-1889).
http://www.vupen.com/blog/20120717.Advanced_Exploitation_of_Internet_Explorer_XML_
CVE-2012-1889_MS12-043.php
[17] Alexander alech Klink, Julian zeri Wlde. Efficient Denial of Service Attacks on Web
Application Platforms. http://www.youtube.com/watch?v=R2Cq3CLI6H8
[18] Mike Lennon (SECURITYWEEK). Hash Table Vulnerability Enables Wide-Scale DDoS Attacks.
http://www.securityweek.com/hash-table-collision-attacks-could-trigger-ddos-massive-scale
[19] Jon Brodkin (Ars Technica). Huge portions of the Web vulnerable to hashing denial-ofservice attack.
http://arstechnica.com/business/2011/12/huge-portions-of-web-vulnerable-to-hashing-denialof-service-attack/
[20] Stefan Esser. Advisory 08/2006: PHP open_basedir Race Condition Vulnerability.
http://www.hardened-php.net/advisory_082006.132.html

40

[21] Mandriva. MDKSA-2006:185.


http://www.mandriva.com/en/support/security/advisories/advisory/MDKSA2006:185/?name=MDKSA-2006:185
[22] Red Hat Bugzilla. Bug 169857.
http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=169857#c1
[23] Egidio Romano. Analysis of the Joomla PHP Object Injection Vulnerability.
http://karmainsecurity.com/analysis-of-the-joomla-php-object-injection-vulnerability
[24] Red Hat Bugzilla. Bug 717985.
https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2011-2520
[25] Thomas Woerner. (Patch) Replace pickle by json.
https://bugzilla.redhat.com/attachment.cgi?id=511508
[26] Adrian Furtuna. Practical exploitation of rounding vulnerabilities in internet banking applications.
http://www.youtube.com/watch?v=t4Er3Jwhr6Y
[27] Adrian Furtuna. Practical exploitation of rounding vulnerabilities in internet banking applications.
http://2013.zeronights.org/includes/docs/Adrian_Furtuna_-_Practical_exploitation_of_
rounding_vulnerabilities_in_internet_banking_applications.pdf
[28] Kees Vuik. Some disasters caused by numerical errors - EURO page: Conversion Arithmetics.
http://ta.twi.tudelft.nl/users/vuik/wi211/disasters.html#euro
[29] Gynvael Coldwind. PHP equal operator ==. http://gynvael.coldwind.pl/?id=492
[30] Security Lab. PT-2012-29: Administrator Privilege Gaining in Simple Machines Forum.
http://en.securitylab.ru/lab/PT-2012-29
[31] Wikipedia. Cross-site request forgery.
http://pl.wikipedia.org/wiki/Cross-site_request_forgery#Tw.C3.B3rcy_stron
[32] Wikipedia. Mersenne twister. http://en.wikipedia.org/wiki/Mersenne_twister
[33] Debian (wiki). SSLkeys. https://wiki.debian.org/SSLkeys
[34] Alex Klyubin. Some SecureRandom Thoughts.
http://android-developers.blogspot.com.au/2013/08/some-securerandom-thoughts.html
[35] Lighttpd. Bug #1335. http://redmine.lighttpd.net/issues/1335
[36] Microsoft. Microsoft Security Bulletin MS98-003 - File Access Issue with Windows NT
Internet Information Server (IIS). http://technet.microsoft.com/en-us/security/bulletin/ms98-003

41

You might also like