Bezpieczne programowanie
Cele prezentacji
- Zwrócenie uwagi na ilość błędów w oprogramowaniu, które prowadzą do obniżenia bezpieczeństwa programów, a przez długi czas mogą pozostać niewykryte
- Omówienie najważniejszych typów błędów popełnianych przez programistów i analityków systemowych
- Omówienie technik wykorzystywania błędów w programach w celu włamania się do systemu
- Przedstawienie źródeł informacji na temat unikania błędów w programach
Wstęp
- Na listach dyskusyjnych poświęconych błędom w oprogramowaniu takich jak Bugtraq czy Microsoft Security Bulletin pojawiają się regularnie powiadomienia o kolejnych błędach i kolejne uaktualnienia oprogramowania.
- Czasami ilość takich powiadomień dochodzi do kilkunastu dziennie.
- Biorąc pod uwagę obecny stopień skomplikowania tworzonych programów, uzasadnione jest stwierdzenie, że błędów w programach nie da się uniknąć.
- Najczęściej takie błędy prowadzą do nieprawidłowego wykonania się programu czyli awarii, ale możliwe jest też wykorzystanie ich do włamania się do systemu czyli uzyskania uprawnień większych niż przewidziane przez administratora systemu.
- W tej prezentacji skupię się na błędach, które są niebezpieczne ze względu na możliwość wykorzystania ich w celu włamania się do systemu.
Najczęstsze źródła błędów w programach
Blędy implementacyjne
- najważniejszy błąd, którego w zasadzie nie da się wyeliminować - PRZEPEŁNIENIE BUFORA (ang. Buffer Overflow)
- synchronizacja wątków wykonywanych współbieżnie
- niedostateczne sprawdzenie danych wejściowych (ew. całkowity brak sprawdzenia).
- nieskuteczny algorytm generowania liczb losowych
Błędy związane z projektowaniem
- w językach obiektowych (tu na przykładzie Javy, która postrzegana jest jako bardzo bezpieczny język w porównaniu z C) możliwość jest ominięcie mechanizmów związanych ze sprawdzaniem bezpieczeństwa klas przez zastosowanie deserializacji oraz klonowania obiektów.[Javaworld 1]
- Nieprawidłowe korzystanie z mechanizmów dziedziczenia (np. umożliwienie przeciążania metod w podklasach) i enkapsulacji (atrybuty publiczne i prywatne klas). Są to błędy dość subtelne, ale potencjalnie mogą być niebezpieczne
- Wbudowywanie w program informacji poufnych
Omówienie przepełnienia bufora
Błąd ten omówię na przykładzie języka C, ale może się on zdarzyć się w każdym języku, który pozwala na zapis w pamięci, do której program nie powienien mieć normalnie dostępu.
Istnieje wiele wariantów tego błędu, ale generalnie polega on na skopiowaniu danych z jednego obiektu do innego, bez sprawdzenia czy obiekt nadpisywany jest wystarczająco duży, żeby zmieścić wszystkie kopiowane dane. Do kopiowania używana jest funkcja taka jak sprintf.
Przykład programu, który zawiera ten błąd:
void main (int argc, char *argv[]){
p(argv[1]);
}
void p (char *str){
char bufor[16];
strcpy(bufor,str);
}
Błąd ten można wykorzystać, kiedy program zawierający błąd wykonuje się w atakowanym systemie. Błędny program można wykorzystać do uruchomienia dowolnego kodu z uprawnieniami użytkownika, który ten program uruchomił. Jeśli jest to administrator, atakujący uzyskuje pełną kontrolę nad systemem.
Wykorzystywany jest mechanizm zapisywania argumentów funkcji i adresu powrotnego na stosie w momencie wywołania funkcji. Dokładniej, w momencie wołania funkcji na stosie zapisywane są: argumenty funkcji, adres powrotu, wskaźnik ramki stosu (SFP) i miejsce na zmienne lokalne funkcji.
Na przykład w momencie wywołania funkcji:
void function(char *str) {
char bufor[16];
strcpy(bufor,str);
}
Stos będzie wyglądał następująco:
Błąd ten pojawia się bardzo często i mimo faktu, że jest powszechnie znany i wiele jego wariantów zostało dogłębnie przeanalizowane. W zeszłym roku w produktach firmy Microsoft zostało zgłoszonych oficjalnie 28 błędów typu BO, z czego ponad połowa o najwyższej randze (Critical). Najświeższy z nich z 18 grudnia pozwalał użytkownikowi dowolnej wersji Windows XP uruchomić shella z uprawnieniami administratora. [Microsoft 1] Tylko w grudniu na liście Bugtraq pojawiło się 18 zgłoszeń takich błędów.