You are on page 1of 42

1

2

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
Spis treci
3
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 pod-
waliny wspczesnej informatyki. Od czasu powstania pierwszej programo-
walnej maszyny software sta si nieodczn czci kadego komputera,
ktrego rozwj niedugo pniej wyewoluowa do niezwykle rozlegej i skom-
plikowanej dziedziny nauki w swoich podstawach odrbnej od hardware,
czyli fzycznie istniejcego sprztu, na ktrym jest wykonywany. Ze wzgldu
na ludzk omylno oraz fakt, e programowanie jest pod wieloma wzglda-
mi procesem trudnym, wymagajcym koncentracji, wiedzy oraz dowiadcze-
nia, 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 wie-
le 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 frmy 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 do-
mowymi, reaktorami jdrowymi czy sztucznymi satelitami; moemy jednak
minimalizowa liczb popenianych pomyek oraz naprawia bdy, zanim
znajd si one w kodzie produkcyjnym. W niniejszym artykule przedstawia-
my 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!
Wstp
4
Przekroczenie zakresu liczb cakowitych
Zaczniemy od bardzo prostego bdu, ktry spotyka si w wielu jzykach
programowania - przekroczenia zakresu liczb cakowitych, lub czciej
integer overfow (dosownie przepenienie liczby cakowitej). Przykady kodu
zawierajcego bd tego typu w rnych jzykach programowania przedsta-
wione 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 roz-
miar (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 wspomnia-
nego typu int w ActionScript bd to wartoci od -2
31
do 2
31
-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 za-
rwno 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. arytme-
tyk modulo ktra, rozpatrujc kwesti z niskopoziomowej perspektywy,
Arytmetyka i obliczenia
5
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 miliar-
dw). 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 za-
deklarowana 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 je-
dynie 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 zmien-
nej typu wybranego przez programist. Bd tego typu moe zosta jednak
celowo wywoany przez osob o niecnych zamiarach, ktra, bdc w sta-
nie spreparowa nieprzewidziane przez autora warunki dziaania programu,
moe doprowadzi do wykonania kontrolowanego przez ni kodu w kon-
tekcie 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.
CIEKAWOSTKA Za przykad moe posuy tutaj exploit zaprezentowany przez hakera o pseudonimie
PinkiePie na konferencji PacSec w Tokio w listopadzie 2013. PinkiePie, wykorzystu-
jc 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].
6
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 fagi CF (ang. Carry
Flag, tzw. faga przeniesienia dla liczb naturalnych) oraz OF (ang. Overfow
Flag, tzw. faga przepenienia dla liczb cakowitych) sygnalizuj wyst-
pienie przepenienia podczas ostatnio wykonanej operacji arytmetycznej.
W innych przypadkach zaleca si korzystanie z odpowiedniej
biblioteki umoliwiajcej wykonywanie oblicze z sygnalizowa-
niem przepenie. Przykadem moe by stworzona przez fr-
m Microsoft biblioteka SafeInt, przeznaczona dla jzyka C++ [2].
W pewnych sytuacjach najwygodniej jest ograniczy zakres
danych wejciowych do rozsdnych wartoci. Dla rozwaanego przy-
kadu odpowiednia poprawka mogaby wyglda nastpujco:








Naley jednak zachowa szczegln ostrono przy dobieraniu wartoci
progowych, aby faktycznie zabezpieczay one przed wystpieniem prze-
penienia. 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 na-
stpi 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. popu-
larnych kompilatorw na architekturach x86-32 jak i x86-64). Rozwiza-
nie to mona zastosowa rwnie do zabezpieczenia si przed przepe-
nieniami 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-
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;
7
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 te-
stowania lub debuggowania mona uy opcji -fsanitize=integer dostp-
nej w kompilatorze clang w wersji 3.5 i nowszych. Doczenie owej fagi
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 overfow: 100000 *
100000 cannot be represented in type 'int'
ioc.c:6:17: runtime error: signed integer overfow:
1410065408 * 100000 cannot be represented in type 'int'
CIEKAWOSTKA 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).
Bd objawia si w momencie zakupu bardzo drogiego tunelu kolejowego, biegn-
cego 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 fnansowe 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 prze-
penienie, 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 kon-
tynuowa rozgrywk nie martwic si o przyszo swojego przedsibiorstwa trans-
portowego.
Warto doda, e bd zosta poprawiony w wydanym rok pniej Transport Tycoon
Deluxe.
8
CIEKAWOSTKA
Transport Tycoon.
Obcicie zakresu liczb cakowitych
Kolejny, nie mniej istotny czy rzadziej spotykany rodzaj bdu zwizany z obli-
czeniami 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 prze-
znaczonych do operowania na liczbach cakowitych, ktre rni si od siebie
przechowywaniem informacji o znaku, zakresem moliwych wartoci i co bez-
porednio z tym zwizane, iloci pamici, ktr taka zmienna zajmuje. W zo-
onym 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 nie-
zwykle wane jest, by ostronie podchodzi do kwestii konwersji wartoci z jed-
nego 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 - nie-
powodzeniem przedsiwzicia wartego miliardy dolarw.
9
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 konwer-
sji, tym samym prowadzc do niewaciwych wynikw na wyjciu.
Niezgodno rozmiaru typw mona w wielu przypadkach wykry na etapie kom-
pilacji; w przypadku C oraz C++, popularne kompilatory z rodziny gcc oraz clang
oferuj fag -Wconversion, ktra aktywuje wypisywanie ostrzee zwizanych
z utrat informacji podczas rzutowania. Ostrzeenia wygenerowane dla powysze-
go 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.
10
Jeli kompilator wskae nam w kodzie miejsca potencjalnie dotknite pro-
blemem 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 po-
wanym 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 nale-
cych 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 zazwy-
czaj conajmniej jedna udawaa si pomimo dostarczenia bdnych danych autoryza-
cyjnych. 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 Exten-
sions), 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 );
11
CIEKAWOSTKA Jako, e typ my_bool jest zdefniowany 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 dokumenta-
cj, funkcja ta zwraca jako wynik relacj pomidzy porwnywanymi blokami pamici:
liczb ujemn, zero lub dodatni kolejno kiedy pierwszy region jest leksykografcznie
wczeniej, oba regiony s rwne i pierwszy region jest leksykografcznie pniej. Zna-
my wic znaczenie poszczeglnych rodzajw liczb zwracanych przez funkcj - nigdzie
nie jest jednak zdefniowane, 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 obsza-
rw pamici w blokach 32-bitowych lub wikszych, zamiast pojedynczych bajtw. Po-
niewa 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 specyfkacj) sygnalizuj, e drugi re-
gion pamici jest mniejszy leksykografcznie. Kiedy jednak liczba ta zostanie skon-
wertowana 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.
W przypadku wspomnianej bazy danych porwnywane byy hashe SHA1, a poniewa
hash poprawnego hasa nie by znany osobie atakujcej, wymagane byo przeprowa-
dzenie 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 skryp-
towym 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 bezpiecze-
stwa, wygrywajc prestiow nagrod w kategorii Najlepszy bd po stronie serwera
(ang. Pwnie for Best Server-Side Bug). Wkrtce po jego zgoszeniu wydana zostaa
ofcjalna atka, polegajca na objciu wywoania funkcji memcmp makrem o nazwie
test, normalizujcym dowoln warto do zera i jedynki:
#defne test(a) ((a) ? 1 : 0)
12
Gbokie ukrycie
To nieco humorystyczne okrelenie opisuje pewn grup bdw, ktr ina-
czej mona by okreli jako moliwo znalezienia pewnych danych na stro-
nie WWW (rzadziej w innych technologiach), ktrych pooenie z zaoenia
miao by znane jedynie ograniczonej grupie odbiorcw, ale z uwagi na pew-
ne 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.
Wycieki danych
CIEKAWOSTKA Termin gbokie ukrycie zosta spopularyzowany w roku 2010 przez serwis Niebez-
piecznik (niebezpiecznik.pl), w artykule o wycieku czci bazy dunikw banku PKO
BP [7]. Przedstawiciel banku wyjaniajc sytuacj mia stwierdzi, e plik zosta za-
bezpieczony w tak zwanym gbokim ukryciu. Termin gbokie ukrycie zosta wska-
zany przez redaktora - Macie pomys, co oznacza gbokie ukrycie? ;-) - a nastp-
nie 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].
13
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 kan-
dydat 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 przypad-
ki 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 zgady-
wanie identyfikatorw CV innych kandydatw. Jednym z rozwiza
tego problemu jest uycie np. sumy SHA-2 z numeru CV oraz pew-
nego niejawnego cigu, lub uycie odpowiednio dugiego, nieprze-
widywalnego, unikatowego identyfikatora.
Po trzecie - w niektrych przypadkach, nawet jeli nazwy s lo-
sowe, 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++ cha-
rakteryzuj si bardzo duym stopniem zaufania do programisty - to on,
i tylko on jest odpowiedzialny za unikanie wszelkich bdw implemen-
tacyjnych - zwaszcza tych zwizanych z obsug i dostpem do pami-
ci. 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.
14
Obok powszechnie znanych bdw obsugi pamici zwizanych z za-
pisem (np. przepenienie bufora itd.), ktre w sposb bezporedni
zagraaj bezpieczestwu aplikacji, istnieje jeszcze druga grupa - b-
dy 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 ob-
jawy i konsekwencje, w zalenoci od kilku czynnikw: jakie informacje
(semantycznie) przechowuje owa pami, w jaki sposb zosta skom-
pilowany program oraz w jakim rodowisku jest on wykonywany (co
nierzadko determinuje dane, ktre przypadkowo znajduj si w nieza-
inicjalizowanych buforach). Istnieje kilka najczstszych objaww i kon-
sekwencji takich bdw:
Nastpuje naruszenie ochrony pamici, tj. odczyt z niezainicjali-
zowanej pamici koczy si niedozwolonym zapisem (pod nieist-
niejcy 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 bez-
pieczestwa w aplikacji.
Program nie narusza zasad dotyczcych zarzdzania pamici,
jednak zachowuje si w sposb niedeterministyczny, zwraca-
jc rne wyniki lub przejawiajc rne zachowania w tych sa-
mych warunkach i dla tych samych danych wejciowych. Sytuacja
taka jest charakterystyczna dla niezainicjalizowanych zmien-
nych, ktre przechowuj informacje na podstawie ktrych podej-
mowane s decyzje w aplikacji (np. zmienne typu bool uywane
w wyraeniach if).
Niezainicjalizowane pozostaj wycznie regiony pamici zawie-
rajce 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 niepo-
prawny, trudny do przewidzenia i najczciej bezporednio zwiza-
ny ze starymi danymi, ktre znajdoway si w niezainicjalizowanej
pamici.
15
W sposb oczywisty usterki tego rodzaju naprawia si poprzez inicjalizo-
wanie kadego obszaru pamici, ktry jest dalej uywany przez program
- wikszym wyzwaniem jest raczej wykrycie ich istnienia. W wielu przy-
padkach 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 wypenia-
na jest konkretn wartoci tylko w przypadku, gdy podana przez uytkow-
nika liczba jest pierwsza; w przeciwnym wypadku pozostanie ona niezde-
fniowana (w praktyce na powszechnych platformach przejmujc warto,
ktra wczeniej znajdowaa si w tym miejscu na stosie). Jeli wic na wej-
ciu 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
16
Wskazano nam wic dokadnie, w jakich warunkach faga nie zostanie za-
inicjalizowana oraz w ktrym miejscu jest nastpnie uywana. ledzenie
zalenoci midzy zmiennymi na etapie kompilacji jest niestety moliwe
wycznie w przypadku obiektw statycznych, tj. zdefniowanych bezpo-
rednio 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 mem-
check (wchodzcy w skad pakietu valgrind) oraz MemorySanitizer.
Pierwsze z nich jest samodzieln aplikacj, ktra emuluje wykonywan-
ie dowolnego programu weryfkujc 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 val-
ue(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 aplik-
acji 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-
17
prawnie zainicjalizowany. MemorySanitizer zosta wczony do kompi-
latora clang w wersji 3.5, a do jego uycia potrzebujemy fagi -fsani-
tize=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 uy-
cia niezainicjalizowanej pamici, a take wybrania i regularnego korzystania
z rozwizania uznanego za lepsze w konkretnym przypadku.
CIEKAWOSTKA 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 interneto-
w, 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.
Zacznijmy jednak od pocztku - jak dobrze wiemy, wszystkie popularne grafczne
przegldarki internetowe (Internet Explorer, Firefox, Chrome, Opera, Safari) obsu-
guj wiele podstawowych formatw grafcznych takich jak BMP, JPEG, GIF czy TIFF.
Sze lat temu autorzy niniejszego artykuu zidentyfkowali niezalenie bdy w obsu-
dze 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 niezainicjalizo-
wanej 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-
18
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 stro-
ny moe prowadzi do ujawnienia fragmentw danych, ktre wczeniej byy przetwa-
rzane 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 bufo-
rw 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 ma-
ym rozmiarze (np. jednego koloru), podczas gdy opisy poszczeglnych pikseli od-
woyway 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, niezdefniowana zawarto. Wicej
19
CIEKAWOSTKA informacji na ten temat znale mona w ofcjalnym dokumencie advisory [12].
Z kolei podatno zidentyfkowana przez drugiego z autorw (Mateusza Jurczyka) bya
zwizana z obsug kodowania RLE (Run-Length Encoding), prostej metody kompre-
sji 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 jed-
nak 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 fle 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 li-
bjpeg6b i libjpeg-turbo (uywanej przez wikszo przegldarek i aplikacji obsuguj-
cych format JPEG) [14], Tavis Ormandy wyjani moliwo podniesienia uprawnie w
systemach Windows przy pomocy niezainicjalizowanego wskanika dynamicznie alo-
kowanej struktury w grafcznym komponencie jdra systemu Windows (win32k.sys)
[15], a francuska frma VUPEN wyeksploitowaa luk tej samej klasy w celu przejcia
kontroli nad przegldark Internet Explorer [16].
20
Kolizje w tablicach haszujcych
Tablice haszujce (ang. hash table) s jedn z najpopularniejszych i naj-
czciej uywanych struktur danych w oprogramowaniu wszelkiego rodza-
ju. Struktura ta pozwala na tworzenie tablic asocjacyjnych o statystycznie
szybkim dostpie do elementw w sytuacjach, w ktrych uniwersum war-
toci klucza jest znacznie wiksze od iloci wartoci, ktre przechowywane
s w owej tablicy; na przykad, kiedy kluczem mog by bardzo due licz-
by (dziesicocyfrowe i wiksze), cigi tekstowe lub zserializowane obiekty.
W najprostszym przypadku tablica haszujca moe mie posta zwykej ta-
blicy t adresowanej liczbami naturalnymi , im wiksza warto n, tym szybszy
dostp do elementw, ale i wiksze zuycie pamici. Aby umoliwi indekso-
wanie tablicy dowolnymi obiektami, defniuje 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 szufadkowej 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 pojedyn-
czej wartoci elementu przechowuje list wszystkich wartoci przypisanych
do danego hasha. Oznacza to, e jeli kady z kluczy uytych podczas wsta-
wiania 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 licz-
bie wprost proporcjonalnej do liczby znajdujcej si w niej wartoci, pod-
noszc 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).
Stabilno i niezawodno
21
Skoro funkcje haszujce zachowuj si w sposb deterministyczny a dodat-
kowo 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, poten-
cjalnie 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 wy-
niku 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 loso-
wy 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 - pj-
dzie 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 przetwa-
rzaniem danych wejciowych (kiedy s one uywane w niebezpiecznych ope-
racjach 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, struk-
tury, treci) danych wejciowych.
CIEKAWOSTKA Problem opisany w tej sekcji okazuje si nie by wycznie tworem teoretycznych
rozwaa - pod koniec 2011 roku na konferencji 28C3 badacze Julian Wlde i Alexan-
der 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 sku-
tecznych atakw typu odmowy usugi (ang. Denial of Service) niewielkim kosztem ob-
liczeniowym oraz przepustowoci sieciowej, poprzez wymuszenie na serwerze prze-
twarzania zapytania o zoonoci O(n
2
), 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
22
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 traf 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 ser-
wis 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 przegl-
darka kadego uytkownika tego forum bezwiednie wyle powysze za-
pytanie w oczekiwaniu na zwrotny obrazek. Dua liczba takich zapyta
CIEKAWOSTKA poprawek w kady drugi wtorek miesica (dzie znany jako Patch Tuesday - w wolnym
tumaczeniu atkowy Wtorek). Wkrtce za gigantem z Redmond poszy inne projek-
ty oraz producenci, naprawiajc bd poprzez wprowadzenie do implementacji tablic
haszujcych elementu losowoci uniemoliwiajcego przewidzenie, jakie cigi teksto-
we 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 proble-
mie [18] [19].
23
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).
24
Wycigi w systemie
Jednym z najciekawszych bdw popenianych podczas tworzenia kodu dzia-
ajcego 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. obsu-
gujcego 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
Wielowtkowo
i wielozadaniowo
25
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 potencjal-
nie nieprzewidziany wyjtek.
Z TOCTTOU mona poradzi sobie na kilka sposobw (w zalenoci od kon-
kretnej 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 niespodziewa-
nej zmianie wanoci.
CIEKAWOSTKA 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 konfguracji, 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.
Jednym z (nienajlepszych) rozwiza jest uycie tzw. funkcjonalnoci open_base-
dir w konfguracji PHP - jest to opcja okrelajca, do jakich katalogw silnik PHP
ma zezwala na dostp - opcje t mona ustawi np. dla konkretnej domeny lub kon-
kretnego 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 konfguracji serwera Apache z PHP oraz opcj open_base-
dir 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
26
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 TOCT-
TOU, 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 otwar-
ciem danego pliku, mija troch czasu. W zwizku z tym, jeli cieka w danym mo-
mencie 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 uytkow-
nika, 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 otwar-
ty zostaby plik ./../../../../../../home/alice/tajne.dane - czyli plik tajne.dane w katalogu
domowym uytkownika Alice.
Co ciekawe, bd ten by o tyle specyfczny, e jego rozwizaniem bya sugestia wy-
czenia funkcji symlink w konfguracji PHP [21], oraz stwierdzenie, e open_basedir
nigdy nie mia by barier midzy uytkownikami dziaajcymi na tym samym serwe-
rze [22].
27
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 obiek-
tw - wszystko to ma miejsce automatycznie podczas procesu deserializacji.
W takich przypadkach oczywicie skrypt po stronie klienta albo musi odpo-
wiednio 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 pod-
stawowe typy i struktury (np. JSON), oraz bardziej zoone, ktre mog
przechowywa rwnie obiekty rnych klas (np. uyte wyej Pickle i PHP se-
rialize/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 bez-
porednio 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 obu-
dzi - czyli np. otworzy odpowiednie pliki, wznowi poczenia sieciowe itp.
Dane wejciowe
28
Poniewa niemoliwym jest aby kod funkcji deserializujcej umia obudzi
obiekty wszystkich istniejcych klas, zadanie to spada na sam klas, a kon-
kretniej, na specjalne metody, ktre s wywoywane podczas deserializacji.
Nazwy oraz budowa metod zalene s oczywicie od konkretnego serialize-
ra; 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 wywo-
anie 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 deseria-
lizacj niezaufanych danych w popularnym silniku CMS Joomla! [23]. Badacz wskaza
destruktor klasy plgSystemDebug, ktry w pewnym momencie wykonywa nastpujcy
kod:
$flterGroups = (array) $this->params->get('flter_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 moli-
woci przeprowadzenia ataku dalej:
Metod get w klasie JInput, ktra wywouje metod clean na innym kontrolo-
wanym obiekcie. Metod clean mona byo znale w klasie JCacheStorage-
File 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.
29
O ile w przypadku PHP powaga potencjalnych konsekwencji deserializacji
niezaufanego cigu w znacznym stopniu zaley od tego, jakie klasy s obec-
ne w aplikacji, o tyle w przypadku jzyka Python oraz biblioteki Pickle sy-
tuacja przedstawia si znacznie gorzej. Wynika to z metody dziaania Pickle
- zserializowane dane s w zasadzie mini-programem, ktry ma na celu od-
budowanie danych do ich pierwotnej postaci (tj. tej sprzed serializacji). Pod-
czas 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 wspo-
mc 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 mo-
na umieci na stosie za pomoc instrukcji c), oraz jej argumentu, po czym
j wywouje. W rezultacie deserializacja niezaufanych danych moe dopro-
wadzi 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 webo-
wych. W roku 2011 Marco Slaviero zgosi bd w systemie serwerowym Red Hat dziki
ktremu, wanie za pomoc spreparowanych danych, by wstanie podnie uprawnie-
nia swojego uytkownika do penych uprawnie konta root [24].
Bd znajdowa si w backendzie grafcznego interfejsu sucego do zarzdzania f-
rewallem - system-confg-frewall, a konkretniej w skrypcie system-confg-frewall-me-
chanism.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-
CIEKAWOSTKA
30
porednio poddawany deserializacji. Poniewa dowolny uytkownik systemu mia pra-
wa (korzystajc z DBUS) do wywoania metody write, mg rwnie doprowadzi do
wykonania zdefniowanego przez siebie kodu (np. nadajcego mu pene uprawnienia
administratora).
Bd zosta naprawiony poprzez zastpienie Pickle duo prostszym formatem JSON.
CIEKAWOSTKA
Podsumowujc - w kodzie, w ktrym zaley nam na bezpieczestwie, powin-
no 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.
31
Oscylatory walutowe
Jednym z ciekawszych bdw logiki aplikacji bankowych s bdy zaokrgle-
nia, 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 natyw-
nej walucie (PLN).
2. Przelewa na konto PLN niewielk sum pienidzy (wystarczy kilka groszy).
3. Przelewa 3 grosze z konta w PLN na konto walutowe w EUR.
4. (jeli bd wystpuje) Na koncie EUR pojawia si 1 eurocent (0.01 EUR)
z uwagi na zaokrglenie w gr.
5. Nastpnie atakujcy przelewa 0.01 EUR z konta walutowego na konto
w PLN.
6. (jeli bd wystpuje) Na koncie w PLN pojawiaj si 4 grosze (a wic
o 33% wicej).
7. 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 odej-
mowany przy nastpnej transakcji w drug stron).
Logika aplikacji
Bardzo dobry opis oscylatorw walutowych bazujcych na bdzie zaokrglenia przed-
stawi, na odbywajcej si w Paryu konferencji Nuit du Hack 2013 (a pniej na odby-
wajcej si w Moskwie konferencji ZeroNights 2013), badacz Adrian Furtuna [26] [27].
Oprcz obszernego wytumaczenia tematu, badacz zaprezentowa rwnie wasnej
CIEKAWOSTKA
32
produkcji urzdzenie pozwalajce zautomatyzowa dokonywanie przeleww wymaga-
jcych potwierdzenia tokenem. Urzdzenie wprowadzao kod transakcji w tokenie, po
czym odczytywao go za pomoc kamery sprzonej z OCR; nastpnie kod mg zo-
sta uyty do zatwierdzenia przelewu.
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
Fotografa: Adrian Furtun, Practical exploitation of rounding vulnerabilities
in internet banking applications
Warto rwnie przeczyta artyku EURO page: Conversion Arithmetics autorstwa Ke-
esa Vuika [28], w ktrym autor wyjania problemy zwizane z zaokrgleniem przy przej-
ciu danego kraju z lokalnej waluty na EURO.
CIEKAWOSTKA
33
Nierwne rwnoci
Jednym z problemw wystpujcych w jzykach o sabym typowaniu jest po-
rwnywanie zmiennych o rnych typach - wymaga to zazwyczaj konwersji
danych, a nie zawsze jest oczywiste w jaki sposb to zrobi. Czasami docho-
dzi wic do sytuacji, ktre mog zaskoczy niejednego programist - a co za
tym idzie, doprowadzi do zaistnienia bdu. Z tego powodu jzyki progra-
mowania 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 ta-
kich 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 zwiza-
nych z porwnaniami jest konsekwentne stosowanie operatora silnego po-
rwnania (===), z wyjtkiem konkretnych miejsc, w ktrych sabe porw-
nanie dziaa dokadnie tak, jak tego oczekujemy.
Dziwactwa
34
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 korzy-
sta 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 pierw-
szym 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 * 10
71264128
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].
CIEKAWOSTKA
35
Wartoci (nie)losowe
Podczas tworzenia serwisw webowych oraz podobnych aplikacji dziaa-
jcych po stronie serwera, czasem zachodzi konieczno wygenerowania
losowego, trudnego do zgadnicia cigu znakw. Taki cig moe zosta
uyty jako np.:
Identyfkator sesji uytkownika.
Pocztkowe haso do konta uytkownika (ustalane przy tworzeniu
konta).
Kod pozwalajcy zresetowa haso uytkownika.
CAPTCHA.
Unikatowa nazwa pliku lub podobnego rodzaju identyfkator
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. kryptografcznie nie-
bezpiecznego generatora liczb losowych (w tym wypadku jest to mt_rand
korzystajcy z algorytmu Mersenne Twister [32]). Atakujcy dysponuj-
cy jednym lub kilkoma tokenami moe sprbowa zrekonstruowa we-
wntrzny 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).
Kryptografa
36
Do generowania losowych cigw, na ktrych ma opiera si bezpiecze-
stwo systemu, powinno uywa si tzw. kryptografcznie bezpiecznych
generatorw. Wikszo technologii udostpnia programistom odpowied-
nie mechanizmy pozwalajce na wygenerowanie bezpiecznych liczb loso-
wych, na przykad:
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 kryptografcznie bezpieczne wartoci.
W roku 2008 znaleziono bd w generatorze liczb losowych biblioteki OpenSSL dys-
trybuowanej 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 r-
nych, przewidywalnych par kluczy. W takim wypadku wystarczyo aby atakujcy wyge-
nerowa 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 wy-
padku generator liczb losowych biblioteki OpenSSL by nieprawidowo inicjalizowany,
przez co generowane klucze stay si przewidywalne [34]. Niestety, podobno doprowa-
dzio to do kradziey pewnej sumy kryptowaluty Bitcoin przechowywanej na portfelach,
do ktrych klucze zostay wygenerowane wadliwym generatorem.
CIEKAWOSTKA
37
Nazwy plikw
Przenoszenie kodu midzy rnymi platformami jest z jednej strony a-
twe - caa logika pozostaje niezmieniona - ale z drugiej strony natrafa 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):
GNU/Linux Windows
Separatorem nazw katalogw i plikw jest
znak / (slash).
Separatorem nazw katalogw i plikw
moe by zarwno znak / (slash) jak i \
(backslash).
Znaki < > oraz \ mog wystpi w nazwie
pliku lub katalogu.
Znaki < > oraz \ nie mog wystpi
w nazwie pliku lub katalogu.
Pliki XYZ oraz xyz to dwa rne pliki. Do pliku XYZ mona odwoa si uywajc
nazwy xyz, jak i xYz, itd. Co wicej, mo-
na te skorzysta z nazwy xyz...................,
xyz , jak i (w przypadku NTFS)
xyz::$DATA.
Brak limitu dugoci cieki. Maksymalna dugo cieki to 32767
znakw.
Dowolny uytkownik moe tworzy linki sym-
boliczne.
Tylko administrator moe tworzy linki sym-
boliczne.
Przenono kodu
38
Powysze rnice staj si niesamowicie istotne w przypadku programw,
ktre musz podj decyzj bazujc na nazwie pliku (lub ciece) otrzyma-
nej od zewntrznego uytkownika. Przykadem moe by poniszy kod:
def CzyMoznaWyswietlicPlik(nazwa):
return nazwa.fnd("confg") == -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
confg. 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 fltr.
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.
Na bd tego typu natrafli twrcy serwera WWW Lighttpd. Okazao si, e o ile odwoa-
nie typu http://example.com/index.php dziaao zgodnie z zaoeniami (tj. skrypt PHP
by wykonywany), o tyle http://example.com/index.php::$DATA powodowao wywie-
tlenie 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 dwukropt-
ka w nazwie zasobu. Warto nadmieni, e podobne problemy wystpiy w roku 1998
w serwerze Microsoft IIS [36].
CIEKAWOSTKA
39
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 oprogra-
mowania. Biorc pod uwag olbrzymi liczb ludzi zajmujcych si zawodo-
wo 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, nie-
rzadko czynic systemy informatyczne podatnymi na rnego rodzaju ata-
ki zagraajce bezpieczestwu danych uytkownikw lub powodujc inne,
znaczce straty. Pamitajmy wic, by starannie pisa kod starajc si prze-
widzie wszelkie przypadki brzegowe, w adnym wypadku nie ufa danym
pochodzcym od (potencjalnie wrogiego) uytkownika, a przede wszystkim
wszechstronnie i wyczerpujco testowa i audytowa rozwijane oprogramo-
wanie - w przeciwnym wypadku ryzykujemy znalezieniem si w kolejnym
opracowaniu najciekawszych bdw w historii software, czego sobie ani Czy-
telnikowi oczywicie nie yczymy.
Zakoczenie
Mateusz (po lewej) od wielu lat pasjonuje si te-
matyk bezpieczestwa komputerowego - spe-
cjalizuje si w metodach odnajdowania oraz
wykorzystywania podatnoci w popularnych apli-
kacjach klienckich oraz systemach operacyjnych.
Na codzie pracuje w frmie Google na stanowisku
Information Security Engineer, w wolnych chwilach
prowadzi bloga zwizanego z bezpieczestwem
niskopoziomowym (http://j00ru.vexillium.org).
Gynvael na co dzie pracuje w frmie 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.
AUTORZY
40
[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-and-
Samsung-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 fle 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. Effcient 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-of-
service attack.
http://arstechnica.com/business/2011/12/huge-portions-of-web-vulnerable-to-hashing-denial-
of-service-attack/
[20] Stefan Esser. Advisory 08/2006: PHP open_basedir Race Condition Vulnerability.
http://www.hardened-php.net/advisory_082006.132.html
Bibliografa
41
[21] Mandriva. MDKSA-2006:185.
http://www.mandriva.com/en/support/security/advisories/advisory/MDKSA-
2006: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

You might also like