Forum The World na Goldenline.pl Twitter Facebook Kanał RSS

Buffer overflow – niebezpieczny błąd programisty

Przepełnienie bufora to błąd polegający na zapisaniu do wyznaczonego obszaru pamięci danych zajmujących więcej miejsca niż zostało zarezerwowane przez programistę. Taka sytuacja prowadzi do nadpisania danych znajdujących się bezpośrednio za buforem, co może spowodować błędne działanie programu lub przejęcie kontroli nad nim (i systemem) przez atakującego.

Przypuśćmy, że używamy programu, który podaje nam jakieś informacje po wprowadzeniu poprawnego hasła. Uproszczony kod takiej aplikacji (pokazujący jedynie czy hasło jest poprawne) znajduje się poniżej:

#include <stdio.h>

int main() {
    char pass[] = "moje_haslo", buff[11]; // 1

    gets(buff); // 2

    if(!strcmp(buff, pass)) // 3
        printf("Poprawne haslo");
    else
        printf("Bledne haslo");

    printf("\n%s / %s", buff, pass); // 4

    return 0;
}

Ważniejsze linijki:

  1. Deklaracja dwóch tablic znakowych; jedna z nich zostaje wypełniona ciągiem, który stanie się hasłem do programu
  2. Użytkownik podaje hasło
  3. Porównanie czy ciągi są identyczne
  4. Linijka, która nie znalazłaby się normalnie w programie, ale przyda się do pokazania, co zaszło w pamięci – drukuje ona ciąg znaków wpisany przez użytkownika i ten znajdujący się w pamięci programu

Zasada działania tego kodu jest na tyle prosta, że raczej nie trzeba jej tłumaczyć.

Normalne działanie programu

Przejdźmy, zatem do rzeczy. Widząc strukturę programu możemy stwierdzić, że przepełnienie bufora przeznaczonego na hasło użytkownika nastąpi po wpisaniu więcej niż 11 znaków (10 z klawiatury + NULL). Spróbujmy podać dłuższy string.

Naruszenie drugiej z tablic

Widzimy, że tablica przechowująca hasło zapisane w programie została naruszona. Wykorzystując to, możemy włamać się do programu podając odpowiednio spreparowany ciąg znaków, który wypełni całą tablicę użytkownika, wstawi znak NULL (zakończenie stringa) oraz zastąpi stare hasło tym, które zostało wpisane do poprzedniej tablicy. Proste? Jedyną trudność możemy mieć z wstawieniem znaku NULL w konsoli, więc stworzymy specjalny plik wejściowy, który podamy na standardowe wejście programu. Możemy to zrobić chociażby w programie Notepad++ lub każdym innym obsługującym znaki z zakresu 0-32 (upierając się można to napisać w systemowym notatniku).

Zawartość spreparowanego pliku wejściowego

Teraz podajemy stworzony plik na standardowe wejście programu.

Podajemy spreparowany plik na wejście programu

Udało się. Nadpisaliśmy tablicę z hasłem i dostaliśmy się do programu.

Zapobieganie

Sposobów na zapobiegnięcie takiej sytuacji jest wiele. Niektóre z nich to:

  • Ustawienie tablicy z hasłem przed buforem – musimy sprawdzić jak obie tablice są ustawione w pamięci i napisać kod tak, aby ta przechowująca już jakieś dane została umieszczona przed buforem zapisu. W ten sposób użytkownik nie będzie miał możliwości jej (przypadkowego) nadpisania (przynajmniej w powyższy sposób).
  • Sprawdzajmy czy ciąg znaków podany przez użytkownika nie przekroczył długości, jaka została zarezerwowana przez programistę (walidujmy dane wejściowe).

Łomem go potraktuj

Odbiegając od tematu przepełnienia bufora chciałbym jeszcze wspomnieć o tym, że nie zawsze trzeba wyważać otwartych drzwi, aby dostać się do środka. W programach takich jak ten hasło może być zapisane po prostu w źródle pliku (można tam znaleźć także inne ciekawe informacje).

Źródło programu

Skompilowany kod można skompresować programem UPX, lecz nawet wtedy program nie jest zabezpieczony, ponieważ atakujący może odwrócić działanie kompresji.


Facebook Twitter Delicious Digg Reddit

Podobne wpisy

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

Możesz użyć następujących tagów oraz atrybutów HTML-a: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Current month ye@r day *

CommentLuv badge