Weryfikacja poprawności kontroli dostępu do danych oraz do funkcji jest jednym z bardziej istotnych elementów testów bezpieczeństwa aplikacji. Tematowi temu były poświęcone między innymi dwa przykłady w przewodniku po bezpieczeństwie aplikacji internetowych (Lekcja 2: Nieprawidłowa kontrola dostępu do danych oraz Lekcja 3: Nieprawidłowa kontrola dostępu do funkcji). Dziś spojrzenie na temat z nieco innej strony.
O testowaniu kontroli dostępu (do funkcji)
Przygotowanie do testów
W celu przetestowania kontroli dostępu do danych i funkcji dobrze jest najpierw ustalić jak ta kontrola dostępu powinna działać. W niektórych przypadkach reguły przyznawania/odmawiania dostępu są tak skomplikowane, że zrozumienie ich jest sporym wyzwaniem. Warto jednak skupić się na dość prostym przypadku, który chciałem już pokazać w drugim z dostępnych wyzwań.
W przykładzie tym w aplikacji założone są konta należące do trzech rożnych grup/roli. W zależności od roli, do której należy użytkownik, uzyskuje on dostęp do różnych funkcji. Jednym z elementów wyzwania było znalezienie błędu w kontroli dostępu, ale aspekt ten nie spotkał się z większym zainteresowaniem. Warto jednak poświęcić mu nieco uwagi, ponieważ jest to dobry przykład jak testować kontrolę dostępu, oraz jak przygotować środowisko do testów.
Ponieważ aplikacja zakłada istnienie trzech ról, czyli:
- gość,
- użytkownik,
- administrator.
Należy przygotować po jednym koncie należącym do każdej z tych grup. W tym przypadku konta takie istnieją w aplikacji, dane uwierzytelniające użytkowników należących do poszczególnych grup znajdują się w drugiej części wyjaśnienia do zadania.
Czy tego typu przygotowanie jest niezbędne? Tak i nie. Nie, bo można oprzeć się na zgadywaniu. Można wyjść z założenia, że atakujący/intruz też będzie zgadywał i być może nie zgadnie. Moim zdaniem kontrola dostępu nie polega na tym, by udziwnić nazwę funkcji tak, by atakujący jej nie znalazł, ale na tym, by aplikacja zweryfikowała, czy dany użytkownik ma prawo do wywołania określonej funkcji. By wiedzieć jak wywołanie danej funkcji powinno wyglądać, dobrze jest posiadać użytkowników z różnymi grupami uprawnień (najlepiej jeśli są to typowe role wykorzystywane w aplikacji). Dlatego uważam, że takie przygotowanie jednak jest potrzebne.
Kto co może
Kolejnym etapem powinno być ustalenie jakie funkcje dostępne są w aplikacji i ustalenie do których z nich dostęp posiadają poszczególne grupy. W przypadku wykorzystywanej jako przykład aplikacji dostępne są następujące funkcje:
- Dane użytkownika (A, U, G),
- Przeglądanie danych (A, U),
- Administracja (A),
- Wyloguj (A, U, G).
W nawiasach oznaczone zostały grupy, które mają dostęp do poszczególnych funkcji. W tym przypadku grupy reprezentowane przez użytkowników Admin, User oraz Guest.
Lista przypadków testowych
Następnym krokiem jest stworzenie listy przypadków testowych, w których aplikacja powinna odmówić dostępu do danej funkcji. W tym przykładzie są dwie takie funkcje:
- Przeglądanie danych,
- Administracja,
Lista przypadków testowych wyglądać może mniej więcej tak:
- próba wywołania Administracja przez guest,
- próba wywołania Administracja przez user,
- próba wywołania Przeglądanie danych przez guest,
Można się zastanawiać czy dwa pierwsze przypadki nie powinny zostać zredukowane do jednego. Teoretycznie założenie, że jeśli aplikacja prawidłowo sprawdza dostęp dla user powinna również prawidłowo sprawdzić i przypadek dla guest. Niestety, to jak działają aplikacje nie zawsze kieruje się logiką i zdrowym rozsądkiem. Dlatego zanim takie przypadki można zacząć redukować warto kilka losowo wybranych przypadków tego typu sprawdzić czy aby na pewno nasze założenia co do spójności działania mechanizmów bezpieczeństwa są uzasadnione.
Test empiryczny
Skoro wiadomo już co trzeba sprawdzić i przynajmniej mniej więcej wiadomo jak należy to zrobić, pozostaje przeprowadzenie eksperymentu, czyli wykonanie testu. Dowód pozostawiam czytelnikowi, jest trywialny (hint: AGH, algebra, jedno z najbardziej irytujących stwierdzeń w "niebieskiej(?) książce", przynajmniej za moich czasów) :)
I to wszystko?
W zasadzie tak, przynajmniej jeśli chodzi o ogólną zasadę postępowania. Oczywiście im głębiej w las, tym więcej drzew, ale o tym może już przy innej okazji. Może w końcu zbiorę się w sobie i przygotuję kolejny odcinek bootcamp.
Tu przy okazji można wspomnieć o zapomnianym już chyba projekcie: OWASP Access Control Rules Tester Project. Przyznam, że chciałem kiedyś korzystać z tego narzędzia z czystej ciekawości, ale cierpliwości mi nie starczyło. Jeśli uwzględnić czas, który należy poświęcić na przygotowanie narzędzia do testów, okazuje się, że zrobienie testów kontroli dostępu ręcznie jest jednak szybsze. Jest to przypadek nieco zbliżony do fuzzerów - są przydatne, ale stosowanie typowych fuzzerów w trakcie typowego testu jest umiarkowanie efektywne (patrz: Po spotkaniu OWASP - fuzzery).
Jeśli komuś znudzi się "świąteczna atmosfera" albo świąteczne obżarstwo, może zająć się kilkoma wyzwaniami. O większości z nich już wspominałem, ale postanowiłem wspomnieć jeszcze raz.Testowanie kontroli dostępu do funkcji Pierwszy temat związany jest z
Przesłany: Apr 02, 13:09
Zadania związane z obfuskowanym kodem JavaScript zostały rozwiązane, głównie przez Krzysztofa Kotowicza. Planowałem przygotować jeszcze jedną mutację tego zadania, ale ostatecznie chyba ją sobie odpuszczę, przynajmniej na razie. Do rozwiązania pozostają j
Przesłany: May 04, 09:24
Bardzo wiele zapytań ofertowych dotyczących "audytu bezpieczeństwa" (w rzeczywistości przedmiot zamówienia z audytem ma niewiele wspólnego) zawiera założenie/wymaganie odnośnie zastosowania "metodologii black box". Moim zdaniem w zdecydowanej większości w
Przesłany: Aug 18, 21:50