Zapraszamy do włamania

Użytkownik, rzecz względna

Aplikacja jest z reguły interfejsem użytkownika do bazy danych. Klient ukrywa przed użytkownikiem rzeczywiste operacje odbywające się w bazie, jednak aplikacja wykonuje tylko na bazie polecenia SQL/DML z uprawnieniami jakiegoś użytkownika. Zgodnie z zasadą najmniejszych przywilejów, uprawnienia tego użytkownika (lub użytkowników) powinny być jak najmniejsze, co stoi, niestety, w jaskrawym kontraście z rzeczywistością codzienną. Paradoksalnie, często bardziej chronione są aplikacje i systemy, niż to co jest najcenniejsze, a więc dane. Problem stosowania zasady najmniejszych przywilejów w serwerze baz danych jest więc szczególnie ważny.

Większość twórców aplikacji przyjmuje, że skoro użytkownik aplikacji korzysta jedynie z tych operacji bazodanowych, które są udostępniane za pomocą interfejsu aplikacji, to nie jest w stanie wykonać żadnych innych operacji w bazie. Co za szkolny błąd! A może raczej lenistwo. Rezultat jest taki, że aplikacja działa w bazie danych z uprawnieniami administratora bazy danych lub zbliżonymi. Jeśli intruz wykryje w aplikacji taką podatność, co nie jest specjalnie trudne, będzie mógł z bazą danych zrobić bez mała co tylko zechce, w szczególności wykonywać na niej zapytania SQL z uprawnieniami aplikacji... W przypadku aplikacji WWW aż się prosi o atak typu SQL injection, ale jeśli w aplikacji istnieją inne podatności, czarnym scenariuszom może nie być końca.

Jedną z przyczyn skutkujących zbyt dużymi uprawnieniami konta aplikacji w bazie danych jest to, że o prawach użytkownika decyduje w dużej mierze przyjęta przez projektanta aplikacji wizja konfiguracji standardowej instalacji bazy danych. Przykładowo, w Oracle istnieje pseudogrupa PUBLIC, do której należą wszyscy użytkownicy. Przywileje nadane tej grupie automatycznie są dostępne wszystkim użytkownikom. Standardowe przywileje tej grupy są po zainstalowaniu serwera baz danych dobierane tak, by były uniwersalne dla większości scenariuszy wykorzystania bazy. Ta przemożna chęć do skonfigurowania bazy raz na zawsze, a więc z uwzględnieniem możliwości zmiany charakterystyki jej pracy, to kolejny duży błąd.

Najczęściej zalecaną strategią przydzielania uprawnień do operacji bazodanowych jest wykonywanie wszystkich operacji na danych za pośrednictwem procedur składowanych i nadawanie użytkownikowi, z którego prawami działa aplikacja w bazie, przywilejów wyłącznie do wykonywania tych procedur. Bezpośredni dostęp do danych w prawidłowo napisanej aplikacji powinien być zabroniony. Przy założeniu, że procedury są poprawnie zaimplementowane, taka konstrukcja aplikacji uniemożliwia wykonanie większości nieuprawnionych operacji na danych. Co więcej, ze względu na swoją przewidywalność, procedury składowane chronią przed atakami typu SQL injection - nie ma bowiem możliwości "wklejenia" własnego kodu SQL.

Bardzo ważnym problemem w kontekście stosowania zasady najmniejszych przywilejów w aplikacjach jest sposób, w jaki aplikacja jest sprzężona z bazą danych. W większości przypadków, pomimo tego, że w aplikacji istnieją konta użytkowników, aplikacja w bazie danych działa na jednym koncie. W naturalny sposób ułatwia to manipulacje danymi innych użytkowników, o ile intruzowi uda się przełamać zabezpieczenia na poziomie aplikacji. Idealne rozwiązanie polegałoby na tym, że kontekst użytkownika podąża za tokiem wykonywania operacji przez wszystkie warstwy. Jeżeli użytkownik jest zalogowany do aplikacji jako KOWALSKI, to również w bazie danych istnieje konto KOWALSKI z adekwatnym poziomem uprawnień i w ich ramach KOWALSKI jako użytkownik aplikacji może się poruszać.

Taka strategia - przy założeniu stosowania zasady najmniejszych przywilejów dla uprawnień użytkownika w bazie - pozwala skutecznie chronić dane innych użytkowników bazy. To jednak teoria. Kojarzenie kont aplikacyjnych z bazodanowymi jest w praktyce trudne w implementacji, zwłaszcza w modelu trójwarstwowym. Problem polega na tym, że konieczne jest tworzenie oddzielnych połączeń serwera aplikacji z bazą dla każdej sesji użytkownika, co miałoby fatalny wpływ na wydajność rozwiązania jako całości.

Dobra praktyka w tym przypadku polega na stosowaniu rozwiązania hybrydowego, polegającego na przypisaniu użytkowników aplikacji do pewnych ról (np. nieuwierzytelniony użytkownik, typowy użytkownik, operator, administrator) i stworzeniu w bazie danych osobnych kont dla każdej z tych grup użytkowników. Taka strategia nie obniża wydajności, a jednocześnie oferuje możliwość zabezpieczenia bazy przed wykonywaniem operacji na danych z uprawnieniami osób z grupy o wyższych przywilejach.

Część serwerów aplikacji oferuje w nowszych wersjach możliwość przełączania kontekstu użytkownika bazy w trakcie trwania połączenia z bazą (coś w rodzaju komendy su obecnej w systemach unixowych). W ten sposób aplikacja może korzystać z tej samej puli połączeń z bazą, a jednocześnie działać w bazie na koncie konkretnego użytkownika. Przykładem takiego rozwiązania jest funkcjonalność Proxy Authentication obecna w Oracle Application Server.

Podsumowanie

Stosowanie zasady najmniejszych przywilejów, choć wydaje się "niepozorne", jest w stanie uodpornić całość systemu informatycznego. Skutki wykorzystania konkretnej podatności zależą od tego, co jej uruchomienie umożliwia, w sensie do jakich uprawnień daje dostęp. Im uprawnienia te będą węższe, tym lepiej. Stosowanie się do tej zasady na wszystkich poziomach (sieć, system operacyjny, aplikacja, baza danych) sprawia, że całość systemu staje się odporna nawet na ataki kombinowane, wykorzystujące różne drobne podatności na różnych poziomach.

Dobrze jest być mądrym po szkodzie, choć to akurat powoduje z reguły dodatkowe wydatki. Znacznie taniej i bezpieczniej jest być mądrym przed szkodą, a więc uwzględniać zasadę najmniejszych przywilejów w całym cyklu życia aplikacji; na etapie formułowania wymagań, projektowania, testowania prototypu, wdrożenia i eksploatacji.

Wojciech Dworakowski jest ekspertem ds. bezpieczeństwa IT w firmie SecuRing. Zajmuje sięm.in. testowaniem bezpieczeństwa aplikacji.

Dobrowolne ograniczenie wolności

Zasada najmniejszych przywilejów powinna zostać wzięta pod uwagę już na etapie projektowania aplikacji. Kluczowy jest tu proces identyfikacji minimalnych uprawnień niezbędnych dla każdej z grup (ról) użytkowników (i procesów). Najłatwiej posłużyć się macierzą uprawnień. W uproszczeniu, jest to tabela, w której w opisie kolumn występują nazwy poszczególnych obiektów (zasobów), zaś w opisie wierszy - nazwy poszczególnych grup użytkowników lub procesów (np. nieuwierzytelniony, gość, typowy użytkownik, operator aplikacji, administrator aplikacji).

W polach tabeli należy wpisać przywileje do poszczególnych obiektów niezbędne poszczególnym grupom. Macierz uprawnień powinna być wypełniana wraz z projektowaniem kolejnych funkcji aplikacji. Po zakończeniu etapu projektowania cała macierz powinna zostać zweryfikowana, a następnie służyć jako źródło przypadków testowych podczas testów funkcjonalnych.

Obiektami w macierzy uprawnień mogą być różne zasoby, np. interfejsy aplikacji, ścieżki URL lub ich wzorce, funkcje języka programowania, tabele i procedury w bazie danych, adresy IP serwera aplikacji itd. Z reguły sensowne jest stworzenie osobnych macierzy uprawnień dla różnych warstw (sieć, system, serwer aplikacji, aplikacja) i związanych z nimi typów zasobów, np. ścieżki URL, funkcje aplikacji, zasoby bazy danych, zasoby sieciowe itp. Jest to wskazane, ponieważ możliwe typy uprawnień są inne dla każdej z warstw. Poza tym uprawnienia na różnych warstwach są implementowane zgodnie z różnymi filozofiami i przy pomocy różnych technologii.


TOP 200