Zależy to od tego, co rozumie się pod pojęciem „bezpieczna analiza kodu źródłowego”. Można zrobić wszystko, co mu się podoba. Przypuszczam, że problem polega na tym, że ktoś inny poprosił o coś, co nazywa się „bezpieczną analizą kodu źródłowego” i można się zastanawiać, dlaczego nie można się do tego kwalifikować.
W wielu przypadkach taką analizę musi przeprowadzić ekspert merytoryczny (SME). W końcowym produkcie MŚP dostarczy oświadczenie zasadniczo mówiące „Deklaruję ten kod jako bezpieczny”, ze zrozumieniem, które jest głębsze niż stwierdzenie „Szukałem kilku znanych wzorców i nie znalazłem żadnych problemów”.
Gdybyś był zainteresowany autentycznym tłumaczeniem chińskiej filozofii, czy zaufałbyś osobie, która dużo znała filozofię i miała kilka ściągawek do jej rozszyfrowania, ale tak naprawdę nie znała chińskiego ?
Świetnym przykładem, który przychodzi na myśl, jest błąd, który uderzył w silnik SQL. Wybaczcie, że nie mam nazwy silnika, ani wersji, żebyście mogli zweryfikować, od tego czasu mam problemy ze znalezieniem. Jednak błąd był przejmujący. Błąd był w kodzie, który wyglądał tak:
int storeDataInCircularBuffer (Buffer * dest, const char * src, size_t length) {if (dest->putPtr + length < dest->putPtr) return ERROR ; // zapobiegaj przepełnieniu bufora spowodowanemu przepełnieniem if (dest->putPtr + length > dest->endPtr) {... // zapisz dane w dwóch częściach return OK; } else {... // zapisz dane w jednej części return OK; }}
Ten kod miał być częścią bufora cyklicznego. W buforze kołowym po osiągnięciu końca bufora zawijasz się. Czasami zmusza to do podzielenia przychodzącej wiadomości na dwie części, co jest w porządku. Jednak w tym programie SQL byli zaniepokojeni przypadkiem, w którym length
może być wystarczająco duży, aby spowodować przepełnienie dest->putPtr + length
, stwarzając okazję do przepełnienia bufora ponieważ następne sprawdzenie nie zadziała prawidłowo. Dlatego wprowadzili test: if (dest->putPtr + length < dest->putPtr)
. Ich logika była taka, że jedynym sposobem, w jaki to stwierdzenie może kiedykolwiek być prawdziwe, jest wystąpienie przepełnienia, a więc wyłapujemy przepełnienie.
Stworzyło to lukę w zabezpieczeniach, która faktycznie została wykorzystana i musiała zostać załatana. Czemu? Cóż, bez wiedzy oryginalnego autora, specyfikacja C ++ deklaruje, że przepełnienie wskaźnika jest niezdefiniowanym zachowaniem, co oznacza, że kompilator może zrobić wszystko, co chce. Tak się złożyło, że kiedy oryginalny autor testował to, gcc faktycznie wyemitował poprawny kod. Jednak kilka wersji później, gcc miał optymalizacje, aby to wykorzystać. Okazało się, że nie ma zdefiniowanego zachowania, w którym instrukcja if
mogłaby przejść test i zoptymalizowała go!
Zatem dla W kilku wersjach ludzie mieli serwery SQL, które miały exploita, mimo że kod miał jawne kontrole, aby zapobiec temu exploitowi!
Zasadniczo języki programowania są bardzo potężnymi narzędziami, które mogą z łatwością gryźć programistę. Analiza, czy tak się stanie, wymaga solidnych podstaw w danym języku.
(Edycja: Greg Bacon był na tyle świetny, aby wykopać ostrzeżenie CERT dotyczące tego: Uwaga o luce w zabezpieczeniach VU # 162289 kompilatory C może po cichu odrzucić niektóre kontrole otaczające., a także ten powiązany. Dzięki Greg!)