Obecnie w ramach przewodnika po bezpieczeństwie aplikacji internetowych udostępnione jest 18 przykładów. Przykłady dotyczą różnych aspektów bezpieczeństwa oraz testowania aplikacji internetowych, po części po to, by pokazać, że testy penetracyjne wcale nie są gwarancją bezpieczeństwa. Ten temat poruszałem zresztą wiele razy na blogu i jeszcze kilka razy pewnie poruszę.
Dziś chciałem podsumować to, co pokazałem w przykładach, a przy okazji zapytać się, co pokazać jeszcze. Jeśli ktoś ma sugestie odnośnie tematu, na który chciałby się czegoś więcej dowiedzieć - proszę bardzo.
Zacząć trzeba od podstaw
Jak to zwykle bywa, zacząć trzeba od podstaw. Może nie całkowicie od zera, ale od pokazania podstaw protokołu HTTP, sposobu przekazywania parametrów i sposobów manipulowania wysyłanymi przez przeglądarkę danymi. Właśnie temu służy pierwsza lekcja poruszająca absolutne podstawy testowania aplikacji internetowych. Kilka razy spotkałem się z tłumaczeniami firm developerskich, które "tłumacząc się" z podatności używały argumentacji typu "(...) to jest bardzo trudne do wykorzystania i wymaga specjalistycznych narzędzi (...)". Cóż, te specjalistyczne narzędzia są wyjątkowo łatwo dostępne. Fałszowanie (w sensie - wysłanie żądań takich jak chce atakujący, a nie takich, jak chce programista) żądań HTTP przy pomocy choćby CURL (Python i httplib lub dowolnego innego sposobu) również nie jest wiedzą tajemną. Programiści muszą przyjąć do wiadomości fakt, że wszystko, co przychodzi od klienta może zostać zmodyfikowane przez tego klienta. Pomóc może w tym pojęcie trust boundary oraz prosty schemat pokazujący gdzie data flow przekracza trust boundary.
Błędy kontroli dostępu
Testowanie kontroli dostępu może być istotniejsze, niż wyszukiwanie kolejnych przykładów cross-site scripting, których scenariusze wykorzystania są co najmniej wątpliwe. Znaczna część błędów związanych z kontrolą dostępu wynika z błędnego założenia, że klient może wygenerować tylko takie żądania HTTP, jakie udostępnione są przez programistę na prezentowanej użytkownikowi stronie. To oczywiście jest błąd, co zostało pokazane w przykładach:
W przypadku błędów dostępu do danych istotną rolę odgrywają identyfikatory globalne. Dobrym sposobem rozwiązania tych problemów jest wykorzystanie identyfikatorów pośrednich, czego przykład został pokazany w Lekcja 13: Demonstracja koncepcji identyfikatorów pośrednich.
Cross-Site Request Forgery
Błędy CSRF zyskują na popularności, być może dlatego, że inne, popularne jeszcze jakiś czas temu podatności spotyka się nieco rzadziej. Świadomość programistów jednak rośnie, choć nie zawsze tak szybko, jak powinna. Temu tematowi poświęcone są dwa przykłady:
Moim zdaniem sama koncepcja stojąca za CSRF jest bardzo prosta, pewne problemy mogą natomiast sprawiać konkretne przykłady jej wykorzystania. Ciekawymi przykładami tej podatności mogą być przypadki CSRF w domowych routerach.
SQL Injection
Lekcja 7: (blind) SQL injection wprowadza w temat dość istotnej podatności, jaką jest SQL Injection. W dodatku podatności bardzo uciążliwej przy testowaniu, bo skutki SQLi z reguły są ZŁE, niezależnie od tego, czy podatność występuje na głównej stronie w formatce używanej przez 99,8% użytkowników, czy w zapomnianej, zakurzonej formatce, do której trafia tylko 0,01%... Przykład ten pozwala testować zarówno "klasyczne" SQL Injection, jak i blind SQL Injection.
Temat SQLi wraca jeszcze w kilku innych przykładach, między innymi w:
Przykłady różne
Lekcja 6: Home-brewed Crypto ma na celu pokazanie, że wymyślanie własnej kryptografii jest złym pomysłem. W tym przypadku zadanie polega na znalezieniu metody dekodowania haseł, które są przechowywane w postaci "hasha". Zamiast użycia sprawdzonych metod przechowywania hasła, tu "hashe" generowane są w oparciu o "własny" algorytm. Smutne jest to, że tego typu wynalazki są wykorzystywane w rzeczywistych aplikacjach, podobnie jak przechowywanie haseł "zaszyfrowanych" przy pomocy XOR.
Temat właściwego encodingu danych został poruszony w przykładzie Lekcja 9: Właściwy encoding danych. W tym przykładzie dane wpisane przez użytkownika są wypisywane następnie w kilku różnych kontekstach na stronie. Można sprawdzić w praktyce, że nie każdy typ kodowania jest właściwy/skuteczny w każdym przypadku. Sposób kodowania danych musi być właściwy dla kontekstu, w którym dane będą użyte.
Inne przykłady dotyczą:
(Nie)skuteczność testów penetracyjnych
Dwa przykłady, które w zamierzeniu mają pokazać, jak łatwo w trakcie testów penetracyjnych jest pominąć istotne podatności:
W temacie nie tak bardzo oczywistych podatności: Podatności stają się oczywiste III. Komentarz do więcej niż jednej ścieżki wykonania pojawi się wkrótce.
Wyzwania
Do tej pory przygotowane zostały również dwa raczej proste wyzwania, w których można sprawdzić swoje umiejętności: