Testowanie bezpieczeństwa kodu

Published: February 16, 2004 | Updated: March 18, 2005

Wprowadzenie

Bezpieczeństwo oprogramowania to jeden z największych problemów w branżach zaawansowanych technologii. Przepełnienie bufora to błąd, wywołujący największe obawy, ale również błąd, którego istota często jest błędnie pojmowana. W dzisiejszych czasach samo wspomnienie o przepełnieniu bufora wywołuje powszechne zainteresowanie. Niestety, często nie mówi się o szczegółach technicznych tego dość podstawowego problemu, dlatego jest on odbierany w sposób przesadzony. Aby pomóc programistom w wyszukiwaniu przepełnień bufora, w Visual C++ .NET wprowadzono specjalne testy bezpieczeństwa.

 

Co to jest przepełnienie bufora?

Bufor to blok pamięci, zazwyczaj w formie tablicy. Jeśli przy zapisywaniu do bufora nie zostanie sprawdzony rozmiar tablicy, możliwe jest zapisanie danych poza zaalokowanym obszarem pamięci (buforem). Zdarzenie, w którym dane zapisywane są pod adresem wyższym niż zaalokowany bufor, nazywa się przepełnieniem bufora (buffer overflow). Podobny problem istnieje w przypadku zapisywania danych pod adresem niższym, niż zaalokowany bufor (buffer underflow). Zapisywanie przed tablicą, choć występuje znacznie rzadziej niż zapisywanie za tablicą, także się zdarza, co zostanie opisane w dalszej części tego artykułu. Przepełnienie bufora, które umożliwia wprowadzenie obcego kodu do działającego procesu, nazywane jest przepełnieniem bufora możliwym do wykorzystania.

Stosowanie pewnej grupy dobrze opisanych funkcji (do których można zaliczyć strcpy, gets, scanf, sprintf, strcat i inne) zwiększa ryzyko powstawania przepełnień bufora, dlatego ich stosowanie jest gorąco odradzane. Oto prosty przykład ilustrujący niebezpieczeństwo związane ze stosowaniem tych funkcji:

int ryzykowna1(char * pLancuch)
{
   int nLicznik = 0;
   char pBufor[_MAX_PATH];

   strcpy(pBufor, pLancuch);

   for(;pBufor; pBufor++)
   if (*pBufor == '\\') nLicznik++;

   return nLicznik;
}

W powyższym kodzie od razu widać słaby punkt - parametr pBufor może zostać przepełniony, jeśli bufor wskazywany przez pLancuch jest dłuższy niż _MAX_PATH. Aby wychwycić ten błąd w czasie wykonywania, wystarczy w wersji roboczej (debug build) - ale nie wersji ostatecznej programu (release build) - wstawić warunek assert(strlen(pLancuch) < _MAX_PATH).

Brandon Bray

Ciąg dalszy artykułu w dokumencie do pobrania (Plik *.doc 134 KB) (12 stron)