Terapia zamiast łat
Luki w oprogramowaniu można niwelować na poziomie systemu operacyjnego. Najlepsze efekty przynosi jednak kontrola kodu przed lub w trakcie kompilacji.
Luki w oprogramowaniu można niwelować na poziomie systemu operacyjnego. Najlepsze efekty przynosi jednak kontrola kodu przed lub w trakcie kompilacji.
Zagrożenia związane z atakami sieciowymi czy wirusami zostały w większości firm zauważone i w dużej mierze zażegnane. Tymczasem na "niewidzialne", choć z pewnością istniejące, luki w oprogramowaniu dobrego rozwiązania na razie nie ma. Być może dlatego że problem leży w dużej mierze po stronie wytwórców oprogramowania, a nie administratorów - przynajmniej tam, gdzie ci ostatni nie mają dostępu do kodu źródłowego.
Na czym tak naprawdę polega problem z lukami w oprogramowaniu i co można zrobić, by mu zapobiec?
Luka przez duże C
Większość języków programowania nie była projektowana z myślą o bezpieczeństwie kodu. Jeden z najpopularniejszych języków programowania - język C jest tak naprawdę estetyczniejszą i bardziej czytelną implementacją języka maszynowego (assemblera). Widać to w każdym jego detalu - działaniach na wskaźnikach, łańcuchach, operatorach itd. Ma to oczywiste zalety. Programy pisane w C szybko pracują i są relatywnie mało "pamięciożerne" ze względu na prostą konstrukcję kodu wynikowego. Są też zwykle bardzo wydajne i w związku z tym właśnie, choć coraz więcej programistów korzysta z języków nowszej generacji jak Java czy C#, w pewnych zastosowaniach język C nadal jest niezastąpiony.
Programista piszący w języku C musi pamiętać o organizacji pamięci podczas działania programu, starannej obsłudze błędów i wyjątków. Każda pomyłka lub niedopatrzenie może spowodować lukę powodującą w najlepszym przypadku niestabilne działanie programu, a w najgorszym - naruszenie bezpieczeństwa przetwarzanych przez niego danych.
Są jednak języki programowania, których mankamenty języka C w ogóle nie dotyczą. Przykładem jest Ada - język o składni zbliżonej do Pascala z bardzo ścisłą kontrolą typów już na poziomie kompilatora. Tworząc program za pomocą języka Ada, wielu błędów po prostu nie da się popełnić, ze względu na to że już projektując struktury danych, programista będzie zmuszony zrobić to w sposób bezpieczny, np. z góry określając maksymalną długość bufora znakowego. Z kolei Perl praktycznie nie absorbuje programisty operacjami na buforach pamięci, zajmując się automatycznie ich przydzielaniem i zmianą ich rozmiaru w zależności od potrzeb.
Niestety, ani Windows, ani Linux, ani większości pozostałych systemów nie napisano ani w Adzie, ani w Perlu, lecz w C i C++. W językach tych powstaje także większość aplikacji dla Windows i Linux.
Jak powstaje dziura
Najczęściej popełnianym błędem jest nadpisanie bufora (buffer overrun), czyli sytuacja, kiedy program próbuje skopiować do bufora dane o większej objętości, niż zarezerwowany dla nich obszar pamięci. Wykorzystanie przepełnienia bufora polega na zapisaniu do niego danych dłuższych od przewidzianego przez programistę rozmiaru tak, by dane te nadpisały stos (kolejkę danych przewidzianych do przetworzenia), w tym także adresy powrotów z funkcji (adresy pamięci przewidziane dla wyników przetwarzania). Atakujący może np. nadpisać adres powrotu z bieżącej funkcji tak, aby wskazywał na jego kod (np. kod wirusa lub konia trojańskiego), znajdujący się w wysłanym przez niego bloku danych.
Program operujący bezpośrednio na pamięci wykorzystuje wiele zmiennych będących liczbami całkowitymi, określającymi wielkość bufora, ilość wczytanych danych itd. Zmienne te są deklarowane jako liczby całkowite (integer) ze znakiem (signed) lub bez (unsigned). Każdy z tych typów ma wyrażone w bitach długości minimalne i maksymalne.
W jednym i drugim przypadku możliwe jest, że w wyniku niewystarczającej kontroli ze strony programisty zmienna, wbrew jego intencjom, zmieni typ - z oznaczonego na nieoznaczony lub odwrotnie. Większość kompilatorów C i C++ zezwala na mieszanie typów ze znakiem i bez znaku - funkcja zdeklarowana jako przyjmująca argument bez znaku przyjmie także liczbę ze znakiem. Wywoła to, co prawda, ostrzeżenie kompilatora, ale mimo to taki kod zostanie skompilowany. Co gorsza, dla wygody programisty kompilator zaproponuje w takim przypadku automatyczną konwersję typu. Wtedy liczba ujemna -10000 typu short int (krótka liczba całkowita) zmieni się w 55536, liczbę ponad pięć razy większą i to dodatnią, co może mieć katastrofalne skutki.
Stosowanie wielu zabezpieczeń ma sens, nawet jeśli każde z nich nie jest stuprocentowo skuteczne. W wielu przypadkach znalezienie błędu umożliwiającego przepełnienie bufora to dopiero pierwszy krok do właściwego ataku, polegającego na wykorzystaniu programu-ofiary do uruchomienia złośliwego kodu. Samo załadowanie tego kodu może się okazać dla atakującego niemożliwe, np. dzięki wprowadzonemu przez zabezpieczenia kompilatora limitowi długości pobieranych danych.
Oceń artykuł
Komentarze (0)
Najpopularniejsze
- Pierwsze w Polsce testy transmisji danych z...
- Magdalena Gaj została Przewodniczącą Rady...
- Asseco wątpi w obiektywny wybór dostawcy w...
- Raport Państwo 2.0, czyli nowa wizja...
- Sygnity: wezwanie Asseco i sezonowość...
- Ogromna liczba komputerów Mac wciąż...
- Nasza Klasa uruchomiła inkubator...
- Google prezentuje okulary z Augmented Reality
- Oracle daje klientom bezpłatny system do...
- CBA kontroluje przetargi związane z CEPiK
Rekomendacje
Serwisy IDG - Warunki obsługi - Kontakt - Redakcja - Regulamin - O nas - Polityka prywatności - Serwis zgodny z ASME
Reklama - Licencjonowanie treści - Prenumerata: Computerworld, Networld, PC World
Computerworld Polska i Computerworld Polska online są znakami towarowymi IDG Poland SA.
© Copyright 2012 International Data Group Poland S.A. 04-204 Warszawa ul. Jordanowska 12 tel.(+4822)321-78-00 fax(+4822)321-78-88






