Postanowiłem nieco rozwinąć temat sandboxa i sensowności tego typu rozwiązania w przypadku przeglądarek internetowych. Bezpośrednią inspiracją jest ten komentarz.
Dlaczego sandbox ma sens
Błędy były, są i będą
Oprogramowanie jest tworzone przez ludzi, którzy popełniają błędy i będą popełniać je nadal. Inżynieria oprogramowania to dziedzina, która ma zaledwie kilkadziesiąt lat. Historia budownictwa jest zdecydowanie dłuższa, a wciąż zdarzają się katastrofy budowlane. Oczywiście, można stosować różne praktyki, które zmniejszają prawdopodobieństwo popełnienia błędu. Zmniejszają, ale nie eliminują. Można też stosować techniki, które powodują, że wykorzystanie błędów staje się trudniejsze lub często nawet niemożliwe.
Przy okazji warto zastanowić się co to jest "błąd". Czy jest to (tylko) błąd implementacyjny? A co, na przykład, z błędami projektowymi? A może założenia, które zostały przyjęte przy projektowaniu aplikacji z czasem okazały się błędne. Czasami "czas życia" aplikacji okazuje się większy, niż pierwotnie przewidzieli jego twórcy. Na przykład był dopiero rok 1972, a tu już się zbliża rok 2000 i okazuje się, że pojawia się millenium bug. Hash Lan Manager kiedyś też wydawał się wystarczająco bezpieczny, jak to wygląda teraz, każdy wie. Ze względów kompatybilności (wstecznej) dopiero w Windows Vista hash LM jest wyłączany domyślnie, ale hash NTLM, który "pozostał" do najbezpieczniejszych nie należy.
Co się zmienia
Sposób projektowania aplikacji
Ważnym elementem projektowania aplikacji, z punktu widzenia bezpieczeństwa, jest modelowanie zagrożeń. W procesie tym stara się spojrzeć na tworzoną aplikację oczami intruza. Chodzi tu nawet nie tyle o identyfikację wszystkich możliwych zagrożeń, ale o określenie wymaganych (wskazanych) zabezpieczeń. Nawet jeśli w tym procesie nie pojawi się konkretny scenariusz ataku (cel intruza), to może okazać się, że "przypadkiem" wprowadzone zostało zabezpieczenie, które taki atak skutecznie uniemożliwi, lub przynajmniej skutecznie utrudni. Modelowanie zagrożeń staje się coraz częściej elementem procesu tworzenia aplikacji, dzięki czemu rażących błędów projektowych jest coraz mniej.
Lepsi programiści, pomocne narzędzia, zmieniane kompilatory, testy
Sytuacja poprawia się również w kwestiach implementacyjnych. Zakres działań w tym temacie jest bardzo szeroki. Pierwsza kwestia to szkolenia dla programistów (takie szkolenia są integralną częścią procesu SDL stosowanego w Microsoft), dzięki czemu świadomość kwestii związanych z bezpieczeństwem osób tworzących kod jest większa, niż jeszcze kilka lat temu. Używane są różne narzędzia służące do analizy statycznej i dynamicznej tworzonego kodu, dzięki czemu udaje się wyłapać wiele typowych błędów. Modyfikowane są wreszcie same kompilatory po to, by generowany przez nie kod (maszynowy) zawierał dodatkowe zabezpieczenia na wypadek, gdyby programista jednak popełnił jakiś błąd. Swoją drogą sam kompilator może spowodować podatność w trakcie optymalizacji kodu, czego przykładem może być ten przypadek: A new fascinating Linux kernel vulnerability.
Całość działań dopełniają testy, które uwzględniają również testy bezpieczeństwa. Wykorzystywanie fuzzerów czy testy bezpieczeństwa (testy penetracyjne) w trakcie tworzenia oprogramowania jest coraz częstszą praktyką.
Sprzęt, system operacyjny...
Wsparcie dla technologii NX w sprzęcie (CPU) stało się obecnie normą, systemy operacyjne implementują mechanizmy ochrony typu DEP czy W^X dzięki czemu wykorzystanie typowych błędów buffer overflow staje się trudniejsze. Na poziomie systemu operacyjnego modyfikowane są mechanizmy zarządzania pamięcią po to, by ewentualne błędy były trudniejsze do wykorzystania. OpenBSD w tym celu zmodyfikowało sposób działania funkcji malloc (man malloc), ciekawą lekturą mogą być również artykuły pojawiające się na blogu Security Research & Defense, choćby jeden z ostatnich: Preventing the exploitation of user mode heap corruption vulnerabilities.
Zmian wiele, a błędy nadal są
Skoro wszystko idzie tak doskonale do przodu, dlaczego ciągle istnieją błędy bezpieczeństwa? Dlatego, że ataki nigdy nie stają się "gorsze", zawsze stają się lepsze. Innymi słowy to, co było wystarczające wczoraj, wcale nie musi być wystarczająco bezpieczne dziś lub jutro. Dlatego tak ważne jest stosowanie defence-in-depth (swoją drogą oglądając ostatnio kilka filmów ze scenami ataku na zamki, w którym atakujący niszczyli bramę przy pomocy tarana, zacząłem się zastanawiać dlaczego zamki były budowane w taki właśnie sposób by brama była dostępna "frontalnie", przez co dość łatwa do zaatakowania przy pomocy dość sporego tarana; umieszczenie bramy "z boku" między murami układającymi się na przykład w literę L po pierwsze mogłoby utrudnić podprowadzenie odpowiednio dużego tarana pod bramę, a i umożliwiłoby wykazanie należytej gościnności wobec wpadających bez zapowiedzi wojów, przy pomocy gorącej smoły na przykład).
Dzięki takiemu podejściu szansa na udany atak spada, ponieważ nawet w przypadku, gdy jeden mechanizm obrony zawodzi, zawsze jest szansa, że zadziała inny. Podatność nadal istnieje, ale nie jest możliwa do wykorzystania, lub jej wykorzystanie jest trudne. Oczywiście zdarzają się również przypadki, w których wszystkie mechanizmy zawodzą.
Wszystkie wymienione wyżej mechanizmy nadal mogą być rozwijane i udoskonalane, w pewnej chwili jednak dalsze ich modyfikacje (kosztujące potencjalnie dużo, nie tylko w sensie pieniędzy, ale również choćby w znaczeniu dodatkowego narzutu mającego niekorzystny wpływ na wydajność) będą przynosiły niewielki efekt rozumiany jako realny wzrost bezpieczeństwa. Wtedy trzeba sięgnąć po coś nowego, jakiś dodatkowy mechanizm. I sandbox jest jednym z takich mechanizmów.
Szczególny przypadek przeglądarek internetowych
Przeglądarki internetowe są przypadkiem szczególnie interesującym. Są powszechnie wykorzystywane, mają kontakt z potencjalnie niebezpiecznymi stronami Wild World Web, a co więcej ich funkcjonalność może być rozszerzana przez zewnętrzne moduły, nad których jakością twórcy przeglądarki w żaden sposób nie panują. Wystarczy wspomnieć o ostatniej serii błędów w produktach Adobe, a przecież taki Flash jest zainstalowany na większości komputerów.
Im mniej (przywilejów), tym lepiej
Jedną z podstawowych zasad bezpieczeństwa jest zasada minimalnych przywilejów. Proces powinien posiadać dostęp jedynie do tych zasobów, które są mu niezbędne do wykonania swojej pracy. Co więcej określone zadanie można rozbić na wiele "elementów składowych", które różnych uprawnień potrzebują. W OpenBSD (zresztą nie tylko tam) wykorzystywana jest koncepcja privilege separation. Te zadania, które są najbardziej niebezpieczne i najbardziej wystawione na atak, realizowane są przez procesy z najmniejszymi uprawnieniami. Podobna koncepcja została wykorzystana przy Microsoft Office Isolated Conversion Environment, w tym wypadku "niebezpiecznym zadaniem" jest parsowanie "starych" binarnych formatów Office zwłaszcza w przypadku, gdy pliki pochodzą z niezaufanych źródeł.
Sposób realizacji tego sandboxa opisany jest w serii Practical Windows Sandboxing:
- Practical Windows Sandboxing – Part 1,
- Practical Windows Sandboxing – Part 2,
- Practical Windows Sandboxing – Part 3,
W analogiczny sposób został zaimplementowany sandbox wykorzystywany w Chrome: Chromium Developer Documentation: Sandbox. Nieco w inny sposób (przy okazji skutecznie wykluczający działanie na systemach starszych niż Windows Vista) wykorzystany został w IE Protected Mode.
Co daje sandbox
Piszę tu głównie o środowisku Windows, choć podobny model bezpieczeństwa obowiązuje również w innych systemach operacyjnych. Uprawnienia są przyznawane w nim użytkownikom, a nie (przykładowo) programom. Programy uruchamiane przez użytkownika "dziedziczą" jego uprawnienia, co oznacza tyle, że mogą uzyskać one dostęp do wszystkich zasobów (danych), do których dostęp ma użytkownik. Model ten co prawda zapewnia separację użytkowników, ale kompletnie się nie sprawdza w sytuacji, gdy sposobem ataku jest podsunięcie użytkownikowi "złego" programu (malware), lub gdy w kontekście uruchomionego przez użytkownika programu wykonuje się "obcy kod" (np. exploit). Środowisko .NET zawiera mechanizm Code Access Security, który pozwala na określenie co dany program/kod będzie robił i jakie potrzebuje do tego uprawnienia, o ile się nie mylę również w przypadku Java istnieje podobny mechanizm. W przypadku systemu Linux można zastosować na przykład SELinux, Windows sam w sobie analogicznego mechanizmu nie posiada.
Co daje sandbox? Przede wszystkim to, że przeglądarka (lub jej fragmenty) nie pracuje z pełnymi prawami, jakie normalnie mają procesy danego użytkownika. Dysponują ograniczoną możliwością zapisu do rejestru oraz do systemu plików, ograniczone są również tworzone przez nie procesy potomne. W rezultacie zniszczenie, którego może dokonać exploit uruchomiony w kontekście tak chronionego procesu, jest mocno ograniczone.
Nie tylko dla przeglądarek
Szczerze mówiąc to mam nadzieję, że koncepcja separacji przywilejów przeniesie się na Windows. Nie obraziłbym się, gdyby model ten stosowany był nie tylko przez przeglądarki internetowe, ale również przez programy pocztowe, odtwarzacze multimedialne, czy programy biurowe. W zasadzie to przez każdy program, który ma kontakt z niezaufanymi danymi.
A sam sandbox powinien być możliwie prosty, tak, by szansa, że sam w sobie wprowadzi nowe podatności, była niewielka.
Chrome to wzorowo zabezpieczona przeglądarka? Cóż, z tym wzorowym zabezpieczeniem to może pewna przesada, aczkolwiek zwrócenie uwagi na korzyści płynące z sandboxa jest słuszne. Pisałem zresztą o tym już jakiś czas temu: Chrome ma sandboxa (czyli nie t
Przesłany: Jan 09, 22:15