Przejdź do zawartości

Format string attack

Z Wikipedii, wolnej encyklopedii
To jest stara wersja tej strony, edytowana przez Jagger (dyskusja | edycje) o 20:33, 17 wrz 2006. Może się ona znacząco różnić od aktualnej wersji.

Format string attack - Atak komputerowy będący względnie nową techniką wykorzystywania błędów programistycznych w aplikacjach. Błędnie napisana aplikacja może być przy wykorzystaniu tej techniki usunięta z listy procesów przez system operacyjny (tzw. crash) lub zmuszona do wykonania kodu dostarczonego przez napastnika.

Historia

Pierwsze informacje na temat błędnego wykorzystania funkcji wykorzystujących ciągi formatujące pojawiły się w wynikach analizy kodu źródłowego powłoki csh w 1990 przy wykorzystaniu techniki automatycznego testowania aplikacji (tzw. fuzzingu) na Uniwersytecie Wisconsin ([Miller,Fredriksen,So 1990]).

Przez wiele lat niewłaściwe wykorzystanie funkcji operujących na ciągach formatujących było uważane za błąd, nie umożliwiający jednak przejęcia kontroli nad aplikacją. W 2000 roku Przemysław Frasunek przedstawił na liście dyskusyjnej Bugtraq po raz pierwszy exploit wykorzystujący błędy tego typu w szeroko stosowanym serwerze usługi FTP [1]. Kod źródłowy exploita pokazywał technikę umożliwiającą przejęcie kontroli nad aplikacją przy wykorzystaniu błędnego wywołania funkcji syslog().

Pierwsze, udane wykorzystanie tego błędu programistycznego szybko zaowocowało kolejnymi exploitami wykorzystującymi błędy w instniejących implementacjach aplikacji. Podatnymi na atak z wykorzystaniem błędu format bug okazały się tak szeroko stosowane w internecie aplikacje, jak: ProFTPD, su czy też serwer SSH[2].

Obecnie format bugi są coraz rzadziej spotykane w dostępnym oprogramowaniu ze względu na znacznie rozpowszechnienie wiedzy o skutkach i unikaniu tego typu błędów oraz dosyć łatwe techniki wykrywania tej klasy błędów.

Szczegóły techniczne

Atakujący wykorzystuje błędny sposób przekazywania argumentów do funkcji operujących na ciągach formatujących, takich jak printf(), w języku C. W przypadku posiadania przez napastnika kontroli nad ciągiem formatującym może on wykorzystać niektóre z dyrektyw takiego ciągu do zapisania dowolnych obszarów pamięci procesu. Zwykle wykorzystywana jest tutaj mało znana i sporadycznie wykorzystwana dyrektywa %n, zapisująca pod obszar pamięci wskazywany przez kolejny argument (który powinien znajdować się na stosie procesu) liczbę dotychczas zapisanych przez atakowaną funkcję znaków. Umiejętne użycie dyrektywy %n oraz dyrektyw określających liczbę znaków do wypisania, np. %<liczba>s, spowoduje odwołanie się pod z pozoru przypadkowy adres z obszaru stosu programu, i w wielu sytuacjach pozwoli na nadpisanie odpowiednio wybranych obszarów pamięci, w tym danych kontrolnych procesu.

Najczęstszy schemat wykorzystania podatności polega na nadpisaniu wskaźnika powrotu z funkcji (wartości na stosie), zastępując go wskaźnikiem do kodu (znajdującego na stosie, stercie lub w sekcji kodu procesu). W takim przypadku atak ten jest bardzo podobny do sposobu wykorzystania błędu przepełnienia bufora. Możliwe jest także nadapisanie danych (zmiennych), co może prowadzić do korzystnych z punktu widzenia atakującego zmian w przepływie sterowania procesu (np. eskalacji uprawnień).

Błędy tego typu mogą zostać w pewnych sytuacjach pośrednio wykorzystane bez wykorzystania dyrektywy %n. Wykorzystanie dyrektywy %s może doprowadzić do ujawnienia zawartości pamięci procesu uprzywilejowanego, w tym np. haseł; w innym scenariuszu, możliwe jest doprowadzenie do skopiowania do bufora (np. funkcją sprintf()) więcej danych, niż przewidział programista.

Najpopularniejsze z podatnych na atak funkcji i rodzin funkcji:

  • printf()
  • syslog()
  • err()
  • warn()
  • setproctitle()

Obrona

Sposób obrony przez tego typu atakiem jest bardzo prosty. W tworzonym kodzie należy unikać przekazywania ciągów formatujących dostarczonych przez użytkownika do funkcji wykorzystujących ciągi formatujące (np. printf()) oraz takich, które takie funkcje wewnętrznie wykorzystują (np. syslog()). W ogólnym przypadku sprowadza się to zamiany wywołań typu:

printf(string);

na

printf("%s", string);

Dodatkowo, możliwe jest zabezpieczenie zamkniętego oprogramowania przez taką zmianę funkcji bibliotecznych, by odrzucać relatywnie mało przydatną dyrektywę %n we wszystkich odwołaniach do biblioteki. Zmniejsza to znacznie ryzyko pomyślnego ataku, chociaż - jak zaznaczono wcześniej - nie chroni przed wszystkimi jego wariantami. W niektórych przypadkach pomocne mogą być algorytmy ochrony stosu przed wykonywaniem znajdującego się na nim kodu na architekturach sprzętowych, które tego nie uniemożliwiają (np. IA-32), a także inne sposoby utrudniające wykonywanie przemyconego do pamięci procesu kodu (np. losowe ułożenie wirtualnej przestrzeni adresowej procesu).

Przypisy

Zobacz też

Linki zewnętrzne