Błędy, testy i okolice

Nie jest możliwe stworzenie w pełni bezpiecznego oprogramowania, tak jak nie jest możliwe napisanie całkiem niezawodnego programu. Nie zwalnia to jednak projektantów i programistów z takiego kierowania pracą, by minimalizować zagrożenia.

Nie jest możliwe stworzenie w pełni bezpiecznego oprogramowania, tak jak nie jest możliwe napisanie całkiem niezawodnego programu. Nie zwalnia to jednak projektantów i programistów z takiego kierowania pracą, by minimalizować zagrożenia.

Niestety, na razie programiści nie dopracowali się narzędzia, które gwarantowałoby tworzenie zawsze bezpiecznego kodu.

Namiastką takich narzędzi są tzw. bezpieczne biblioteki udostępniane dla najpopularniejszych i najczęściej wykorzystywanych języków programowania. Należą do nich różne implementacje operacji na łańcuchach znaków w C/C++, które chronią przed błędem przepełnienia bufora, czy biblioteki zapewniające bezpieczne zarządzanie pamięcią. Biblioteki te są bezpieczne tak długo, jak długo programista nie wpadnie na pomysł, by ręcznie modyfikować pamięć czy zmieniać wskaźniki, ponieważ wydaje mu się, że dzięki temu jego rozwiązanie stanie się szybsze lub wygodniejsze.

Spora część współczesnych aplikacji powstaje przy użyciu różnych pakietów RAD, gotowych bibliotek i komponentów. Częstokroć rola programisty sprowadza się do złożenia aplikacji z mniejszych lub większych gotowych "klocków". Narzędzia RAD radykalnie skracają czas tworzenia aplikacji, ale niestety często kosztem bezpieczeństwa kodu. Ono zależy bowiem zarówno od sposobu łączenia "klocków" (np. wywoływania funkcji, sprawdzania parametrów przekazywanych pomiędzy komponentami itp.), jak i od jakości elementów składowych, z których jest wykonana aplikacja. Jest znanych co najmniej kilkanaście przykładów bibliotek, powszechnie dostępnych i chętnie wykorzystywanych przez informatyków, które zawierają poważne błędy (w tym kilka znanych bibliotek open source).

Na ogół autor z góry określa przeznaczenie tworzonego przez siebie fragmentu oprogramowania i nie dostrzega "ukrytych" możliwości we własnym kodzie. Podczas pracy nie analizuje, czy tego kodu można użyć w innym celu niż założony w projekcie. Późniejsza rewizja w poszukiwaniu potencjalnych luk bezpieczeństwa będzie mało skuteczna bez dysponującego odpowiednim doświadczeniem zespołu i olbrzymiej ilości czasu. Co gorsza, nie ma narzędzi, które skutecznie wspierałyby testowanie bezpieczeństwa. Są tylko programy, które pozwalają sprawdzić system pod kątem znanych błędów, ale raczej sprowadza się to do analizy, czy np. na danym serwerze aplikacyjnym zostały zainstalowane wszystkie niezbędne poprawki.

Wiele przedsiębiorstw wychodzi z założenia, że zapory ogniowe są wystarczającym zabezpieczeniem ich infrastruktury informatycznej. Zapomina, że jeżeli w aplikacji lub serwerze Web występuje błąd, to nie ochroni przed nim żaden firewall. Aby jakakolwiek aplikacja internetowa działała poprawnie, musi być otwarty port 80 (standardowy port WWW). Tą drogą włamywacz może dostać się do systemu i przy użyciu błędnie napisanej aplikacji wykonać zaplanowane działania. Można stosować dodatkowe filtry, które np. będą eliminować znane sekwencje pakietów służące do włamań, ale jest to tylko pozorne rozwiązanie problemu - znacznie efektywniejsze jest samodzielne poprawienie programu łączącego się z Internetem lub zainstalowanie odpowiedniej łaty dostarczonej przez producenta.

Wzorce projektowe

Wadliwe projekty coraz rzadziej są źródłem błędów w aplikacji. Rośnie znajomość różnych metodologii projektowych, zdobywa popularność UML (jeden z języków do modelowania aplikacji). Diagramy są na tyle czytelne, że każdy programista jest w stanie zrozumieć diagram stanu, dany przypadek użycia czy strukturę klas. Ponadto istnieje spory wybór narzędzi, które na podstawie UML generują szkielet aplikacji lub nawet - jak Rational XDE - umożliwiają bieżącą synchronizację kodu i modelu.

Wiele projektów bazuje na podobnych wzorcach. Pracując nad danym problemem, często okazuje się, że składowe rozwiązania mogą być określone jako ogólne "klasy" algorytmów czy podrozwiązań. Przykładowo, chcąc stworzyć klasę, która będzie mogła mieć tylko jedną instancję w systemie, można skorzystać z jednego z wielu wzorców Singleton. Jeżeli zachodzi konieczność zabezpieczenia dostępu do Singleton w środowisku wielowątkowym, można dodatkowo zastosować schemat (wzorzec) Double-Checked Locking. Projektując interfejs użytkownika, można oprzeć się na wzorcu mode-widok-kontroler, któremu towarzyszy wiele przykładów implementacji. Po zidentyfikowaniu wzorców w modelu, można wybierać wiele równorzędnych rozwiązań - dany schemat (np. wspomniany Singleton) ma kilka różnych implementacji i wzorców do realizacji tej samej funkcjonalności. Dzięki wzorcom sprawny projektant może szybko przygotować model, a równocześnie, dzięki temu, że każdy wzorzec jest dobrze opisany i przetestowany, projektant wie, że zastosował optymalny mechanizm.

Na stroniehttp://www.hillside.net/patterns/ umieszczono katalog wzorców.

W celu komercyjnej reprodukcji treści Computerworld należy zakupić licencję. Skontaktuj się z naszym partnerem, YGS Group, pod adresem [email protected]

TOP 200