Security jest walką, więc zmieniaj klucze dla szatana!



O fatalnej pomyłce w Debianowym openssl pisano już wszędzie, np. w LWN oraz na wiki samego Debiana. Nie będę więc powtarzał szczegółów. W skrócie, jeden z deweloperów zakomentował linijkę, która w pewnych sytuacjach mogła korzystać z niezainicjowanej pamięci. Korzystanie z pamięci o nieznanej zawartości jest zazwyczaj błędem programistycznym, w tym przypadku jednak celem było zasianie (ang. seed) generatora liczb pseudolosowych.

Generator jest implementacją algorytmu, który na podstawie jakiś danych, czyli własnie seeda, daje różne liczby losowe. Po zmianie wprowadzonej przez Debianowca jedynym źródłem początkowej losowości był wynik funkcji getpid(), zwracającej identyfikator procesu. W typowym systemie linuksowym ograniczało to możliwą liczbę pierwotnych danych — a co za tym idzie, liczbę możliwych wygenerowanych liczb pseudolosowych — do około 32 tysięcy. Zaledwie! Tak mała liczba kombinacji umożliwia odtworzenie w kilka godzin wszystkich możliwych kluczy kryptograficznych wygenerowanych tak zasianym generatorem.

[demotivator, debian, entropy]
obrazek z xkcd, wykonanie desp, pomysł ja.

Użycie jako początkowego ziarna zawartości niezainicjowanej pamięci jest rozwiązaniem sprytnym. Przynajmniej na pierwszy rzut oka. Gdzieś w głębi zaczęły się jednak pojawiać wątpliwości.

Pytanie pierwsze: jak to możliwe, że zawartość niezaincjalizowanej pamięci miała tak duży wpływ na działanie generatora PRNG? Wpływ kluczowy, bo usunięcie jej spowodowało gigantyczną porażkę.

Pytanie drugie: czy inne dystrybucje są podatne w podobny sposób?

Zaczynając od pytanie drugiego. Korzystanie z niezaincjalizowanej pamięci jako źródła losowych danych jest złym pomysłem. Nie ma żadnej gwarancji, że znajdujące się tam dane są nieprzewidywalne. Linuksowy glibc realizuje przydział pamięci na dwa sposoby. Dla małych obszarów używany jest sbrk(), większe (powyżej 128KiB z dokładnością do autotuningu) zdobywane są przez mmap(). W wyniku mmap() zwracany jest obszar wyzerowany przez jądro. Czyli całkowicie przewidywalny, w 100% wypełniony wartością 0. O losowości nie ma co marzyć, sytuacja jest analogiczna do złej łaty w Debianie, a sytuacja dotyczy wszystkich dystrybucji!

To jednak dotyczy tylko dużych alokacji, bufor w openssl może być dużo mniejszy, mniejszy od progu zerowania przeze jądro. Tu należy sobie zadać pytanie: co jest w niezainicjowanej pamięci? Dane, które były tam wcześniej, wpisane kiedy jeszcze pamięć ta należała do innego programu. Łatwo sobie wyobrazić, że różnego rodzaju łatki typu hardening, czyli ,,zwiększające bezpieczeństwo” zerują każdą pamięć przekazywaną programom. W celu uniknięcia wycieku informacji z wcześniej działajacych programów. Tak więc nawet mały, niezainicjowany obszar pamięci może być wyzerowany i jako taki zupełnie nie nadawać się do inicjowania pracy generatora pseudolosowego.

Zerować obszar miała też pierwotna wersja debianowej łaty:

+ /* Keep valgrind happy */
+ memset(tmpbuf, 0, sizeof tmpbuf);

Została zastąpiona wykomentowanie generującej ostrzeżeni linijki.

Cóż więc z podatnością? Czy openssl zawsze działa na przewidywalnych, zerowych danych i jako takie stanowi zagrożenie na wszystkich linuksach? Odpowiadam: nie, a twierdzenie zawarte w początkowych akapitach tej jest nie do końca prawdziwe.

Poza numerem procesu, niezainicjowana pamięć nie jest jedynym źródłem entropii dla openssl. Więc nawet jeśli jest zerowa, PRNG jest zasiewany innymi losowymi bitami. Przynajmniej w oryginalnym kodzie. Deweloper Debiana usunął zasiewanie niezależnie od sposobu. Z powodu tego, że jedna z metod pozyskiwania entropii powodowała ostrzeżenia, debianowiec zablokował wszystkie. Klasyczny przykład wylania dziecka z kąpielą.

Powstające wątpliwości zostały ugaszone, a openssl na Linuksie jest w porządku. Mój błąd polegał na uznaniu niezaincjowanej pamięci za jedynego źródła entropii, gdy tymczasem jest ono jednym z kilku.


Archived comments:

amag 2008-05-16 18:15:46

Fajny opis. Przyznam, że sam się zastanawiałem w jednym z komentarzy czy nie istnieją łaty na jądro zerujące porzucane/inicjowane obszary pamięci. Nie wiedziałem nic o tym, że oryginalnie była to tylko jedna z metod.

Za ten tytuł powinieneś dostać jakieś piwo- świetne!

Zal 2008-05-16 19:13:11

Nie tylko interesujące, ale i przekomiczne ;D Świetny demotywator :]

zdz 2008-05-16 22:23:15

Wiesz Zal, cholernie nam z kumplem przykro z powodu tych motywatorów. Nigdzie się nie podpisaliśmy, nawet w EXIFie, a obrazki zaczynają krążyć --> http://metasploit.com/users/hdm/tools/debian-openssl/

#!/bin/nwkr devblog 2008-06-17 00:19:10

Bezpieczeństwo SSH to walka, więc ulepsz sshd_config dla szatana!

Bardzo wiele serwerów korzysta z protokołu SSH do udostępniania powłoki. Wszyscy wiedzą, że jest to protokół bardzo bezpieczny. Mniej osób zdaje sobie sprawę z tego, że najsłabszym ogniwem w systemie zabezpieczeń systemów jest użytkow[...]

eversesseaste 2012-11-15 12:32:56

<a href=http://buyviagraonlineds.com/#16060>generic viagra</a> - <a href=http://buyviagraonlineds.com/#19824>buy viagra online</a> , http://buyviagraonlineds.com/#8263 buy viagra

insepterilelo 2012-11-16 21:43:15

<a href=http://buyviagraonlineds.com/#14365>buy generic viagra</a> - <a href=http://buyviagraonlineds.com/#8341>buy viagra</a> , http://buyviagraonlineds.com/#20339 generic viagra

Comments


Comments powered by Disqus