W tym samouczku omówimy przepełnienie bufora (Przepełnienie bufora), usterka, która istnieje od dłuższego czasu, występuje, gdy dane, które są kopiowane w obszarze pamięci (który został wcześniej zarezerwowany) nie są poprawnie sprawdzane, może się zdarzyć, że aplikacja działa poprawnie, jeśli użytkownik wstawi dane z odpowiedni rozmiar, ale jeśli zarezerwujemy pamięć na 15 znaków, a użytkownik wstawi 20 znaków, wpłynie to na inny obszar pamięci, który może, ale nie musi być zarezerwowany.
Może to sprawić, że nasz program się zawiesi, ale może być też znacznie gorzej, użytkownik o złych zamiarach może wykorzystać ten błąd i wpłynąć na działanie aplikacji lub wykonać dowolny kod na komputerze (zwykle ten kod otworzy interpreter poleceń ). Również jeśli program działa z podwyższonymi uprawnieniami, mamy poważną lukę w zabezpieczeniach. Innym atakiem, który może zmienić działanie aplikacji lub wstrzyknąć kod, jest XSS.
NotatkaEgzekucje, które zobaczysz w tym samouczku, zostały wykonane w 32-bitowym systemie operacyjnym Ubuntu 16.04.
Zobaczmy Prosty przykład kodu C, który jest podatny na ten atak, przy uruchamianiu programu musimy przekazać parametr aplikacji spodziewaj się otrzymać ciąg nie dłuższy niż 15 znaków, jeśli jest to oczekiwany ciąg, będzie to udany dostęp, jeśli nie, zostanie "odrzucony". Kod jest taki, jak pokazano poniżej:
#include #include #definiuj hasło "Test" void test (char * str) {char buffer [15]; int n = 0; strcpy (bufor, str); if (strcmp (bufor, hasło) == 0) {n = 1; } if (n) {printf ("Sukces \ n"); wyjście (0); } else {printf ("Odmowa dostępu \ n"); }} int main (int argc, char * argv []) {if (argc <2) {printf ("Aplikacja wymaga parametru \ n"); wyjście (-1); } test (argv [1]); }Nazwa programu pochodzi od przelew.c, a do kompilacji wykorzystano:
gcc overflow.c -o overflow -fno-stack-protectorOstatnia część: -fno-stack-protector Jest używany po to, aby kompilator nie nakładał ochrony i możemy pokazać na przykładzie. Jeśli użytkownik wprowadzi poprawne dane, czyli ciąg maksymalnie 15 znaków, program działa dobrze, jeśli wprowadzimy niepoprawne „hasło” to nam pokaże Brak dostępu, a jeśli wstawimy "Test„Postawi nas Sukces. Zobaczmy zapis wykonujący program 2 razy, raz z niepoprawnym dostępem, a drugi z poprawnym ciągiem znaków:
Widzimy, że wszystko działa poprawnie. Ale co jeśli wstawimy górny ciąg, zobaczmy, co się stanie:
Uruchomiliśmy program z 20 literami Ai pokazuje nam Sukces. W tej aplikacji nie mamy nic, po prostu wychodzimy z aplikacji, ale uzyskaliśmy dostęp do zastrzeżonego obszaru bez znajomości hasła. Jeśli podstawimy następującą funkcję:
strcpy (bufor, str);W następujący sposób:
strncpy (bufor, str, 15);Tak wykonujemy kod z 20 literami A, mamy następujące wyjście:
Widać również, że korzystamy z strcmp, zamiast tego powinniśmy użyć strncmp, więc kontrolujemy również rozmiar. Kontrolowaliśmy, że można skopiować maksymalnie 15 znaków, więc nie ma to wpływu na nasz program, jeśli wstawią więcej. Jeśli po wyświetleniu komunikatu Sukces wykonujemy polecenie systemowe (w tym przypadku kim jestem), uzyskujemy informacje:
Powyżej nie jesteśmy rootami, ale jeśli wykonamy to za pomocą sudo, otrzymamy:
Jedyne, co dodaliśmy, to wiersz w kodzie, który widzieliśmy powyżej, poniżej wiersza kodu:
printf ("Sukces \ n");Umieściliśmy:
system („whoami”);Aby trochę zrozumieć, co się stało, zmodyfikuję program, aby pokazać 2 zmienne, które mamy (bufor Tak n) bez względu na to, czy jest poprawne, czy nie, a poniżej znajduje się wyjście, jako pierwszy wstawiamy ciąg, który będzie traktowany jako poprawny („Test”), następnie niepoprawny, nieprzekraczający długości, a na końcu 20 liter A:
Widzimy, że w pierwszym wykonaniu warto 1 Zmienna n, bo łańcuch zdany jest prawidłowy, w drugim warto 0, bo źle, ale w tym ostatnim warto 1094795585, co powoduje pominięcie warunku, który stawiamy jeśli (n), będzie to prawda, dopóki n jest różne od 0. Nie jest to dobry warunek, chociaż nie musiałby zawieść, gdyby reszta kodu była poprawna. Jeśli włożymy 16 liter A jako parametr zobaczymy, że wartość zmiennej n To jest 65:
Jeśli spojrzymy na kod ASCII, liczba 65 odpowiada literze DO, widzieliśmy, że pamięć zmiennej n została przez nas przypadkowo dotknięta, że dodatkowa litera, którą przekazaliśmy jako parametr, trafiła do zmiennej n. Pamięć mielibyśmy w następujący sposób:
Jeśli wyjdziemy poza znaki, może się zdarzyć, że wyśle nam wiadomość o naruszeniu segmentu (jeśli wyeliminujemy wyjście (0) co mamy w jeśli (n)), widzimy to na poniższym obrazku:
To ostrzeżenie jest spowodowane próbą uzyskania dostępu do obszaru pamięci, który wykracza poza granice obszaru przypisanego przez system operacyjny do aplikacji. Jeśli skompilowaliśmy przykład w następujący sposób:
gcc overflow.c -o overflow -fstack-protectorLub po prostu usuwam -fno-stack-protector Z kompilacji, którą widzieliśmy po raz pierwszy, a wykonujemy kod z przepełnieniem, otrzymujemy następujący wynik:
Dodatkowa ochrona, którą zapewnia nam gcc.
NotatkaGdybyśmy chcieli wykonać kod (kod powłoki) musielibyśmy nadpisać adres powrotu adresem naszego szelkodu, jest to nieco bardziej złożone niż przykład widziany w samouczku i dlatego wymaga więcej pracy.
Jeśli komuś uda się wykorzystać tę lukę, może wyrządzić ci wiele szkód. Unikanie tego typu awarii i tego, że złośliwy użytkownik może z tego skorzystać, jest bardzo łatwe, zaprogramuj poprawnie, musisz dobrze znać używany język programowania, wiedzieć, jakich funkcji użyć, a czego nie, przetestować aplikację cóż, nie tylko z poprawnymi danymi, musi również działać poprawnie, gdy mamy do czynienia z nieprzewidzianymi danymi.
Inne ataki, które możesz przejrzeć i mieć świadomość, aby nie miały na Ciebie wpływu ani nie minimalizowały ryzyka, to: DoS i Brute Force. I nie zapomnij sprawdzić strony CVE pod kątem luk w zabezpieczeniach.
Podobał Ci się i pomógł ten samouczek?Możesz nagrodzić autora, naciskając ten przycisk, aby dać mu pozytywny punkt