Capability dac_read_search i dac_override w profilu AppArmor'a

Spis treści

Od jakiegoś czasu tworzę dla aplikacji w moim Debianie profile pod AppArmor, tak by ograniczyć programom swobodny dostęp do plików czy urządzeń. Tych profili zebrało się już trochę i podczas pisania jednego z nich, zacząłem się zastanawiać czy wszystkie CAP'y (linux capabilities), których żądają procesy, są im faktycznie niezbędne do prawidłowego funkcjonowania. Chodzi póki co o dac_read_search i dac_override . Co ciekawe, odmowa dac_override w części aplikacji nie powodowała żadnych negatywnych konsekwencji. Idąc dalej tym tropem, postanowiłem z paru profili AA usunąć linijkę zawierającą capability dac_override, zostawiając tym samym jedynie capability dac_read_search, i zobaczyć co się stanie. Okazało się, że sporo programów już o dac_override nie prosi. Zatem co się zmieniło przez tych parę lat i czy ta zmiana dotyczy samych aplikacji, a może kernela linux'a?

DAC i CAP

Każdy z nas wie raczej czym są uprawnienia do plików w linux, oraz zdaje sobie sprawę, że użytkownicy w systemie niekoniecznie mają wgląd w każdą jego część. To, czy konkretny użytkownik będzie mógł odczytać, zapisać lub też wykonać dany plik zależy od uprawnień jakie zostały nadane na ten plik dla użytkownika, grupy i innych user'ów w systemie. Wyjątkiem jest użytkownik root . On teoretycznie ma wgląd w każde miejsce w systemie i może podglądać pliki innych użytkowników, nawet jeśli te mają wyraźnie ustawione uprawnienia typu 0400 .

By procesy działające z uprawnieniami administratora systemu root nieco powściągnąć od zaglądania w dowolne miejsce, stworzono dodatkowe uprawnienia, czyli capabilities. Przeciętny użytkownik linux'a nie dostrzeże tej zmiany, bo po zalogowaniu się na root'a będzie miał on i tak dostęp do każdego pliku w systemie, podobnie zresztą jak i same aplikacje. Wyjątkiem jest sytuacja, gdy wykorzystywany jest jakiś dodatkowy moduł bezpieczeństwa w stosunku do tradycyjnego Unix'owego DAC (Discretionary Access Control), a takim jest np. AppArmor czy SELinux.

Różnica w CAP dac_read_search i dac_override

Gdy w grę wchodzi AppArmor lub SELinux, to trzeba liczyć się z tymi dodatkowymi uprawnieniami/możliwościami, jakie oferuje już od dłuższego czasu linux'owy kernel. W skrócie, uprawnienia root zostały rozbite na 64 części, z których póki co około 40 jest w użytku. Dwa z nich to dac_read_search i dac_override .

Celem dac_read_search jest umożliwienie procesowi root obejście uprawnień odczytu (read) do pliku/katalogu oraz wykonania (execute) ale tylko w stosunku do katalogu. Po nadaniu tego CAP'a, proces root będzie w stanie odczytać plik oraz otworzyć folder, do którego nie ma uprawnień. Z kolei (jak się można już łatwo domyśleć) dac_override ma za zadanie umożliwić obejście wszystkich uprawnień do pliku/katalogu, czyli umożliwi procesowi root odczyt, zapis i wykonanie w stosunku do nieswoich plików i katalogów. Jak widać ten drugi CAP jest o wiele potężniejszy.

Problem w kernelu linux'a dotyczący dac_override

We wstępie wspomniałem, że szereg aplikacji w moim Debianie może działać bez dac_override , gdy nada mu się jedynie dac_read_search . To powinno być raczej oczywiste, bo gdy proces z uprawnieniami root chce jedynie odczytać plik lub katalog, do którego nie ma uprawnień, to powinien skorzystać z dac_read_search , a nie z dac_override .

Problemem z żądaniem dac_override do samego odczytu plików tkwił w kernelu linux'a. Szukając informacji na ten temat, natrafiłem na ten oto artykuł. Z niego z kolei dowiedziałem się , że miała miejsce jakaś bliżej nieokreślona zmiana w kernelu, która się dokonała też nie wiadomo kiedy dokładnie. Postanowiłem zatem poszukać co, kiedy i gdzie zmieniono. Przy pomocy serwisu elixir.bootlin.com udało mi się odszukać odwołanie do dac_override i natrafiłem tam na plik fs/namei.c . Szukając jeszcze trochę, trafiłem w końcu na tego patch'a.

Zgodnie z tym co zostało napisane na podlinkowanym wyżej ML, sprawdzenie dac_read_search i dac_override w nowszych kernelach (v4.12+) odbywa się w innej kolejności niż to miało miejsce w starszych wydaniach. W starszych kernelach, najpierw był sprawdzany dac_override , a potem dac_read_search , a obecnie jest odwrotnie. W ten sposób proces root dostaje nieco mniej uprawnień w przypadku, gdy żąda jedynie odczytu nieswoich plików. Ta zmiana weszła w życie około 2017-07-12. Jest zatem niemal pewne, że profile AppArmor'a, które były pisane wcześniej i chciały dac_override , obecnie powinny bez problemu działać z dac_read_search . Oczywiście w dalszym ciągu znajdą się procesy, które będą chcieć dac_override i trzeba będzie je ręcznie zweryfikować.

W taki oto sposób z 54 profili AppArmor'a, w których był obecny dac_override , byłem w stanie się go pozbyć w przypadku 25. Czyli prawie połowa aplikacji miała ten CAP nadany niepotrzebnie.

Warto też zaznaczyć, że AppArmor czy SELinux nie będzie prosił o dac_read_search czy też dac_override w sytuacji, gdy uprawnienia do plików będą odpowiednie. Lepiej jest zadbać o to, by plik/katalog, do którego proces z uprawnieniami root chce uzyskać dostęp, miał grupę root i w niej stosowne uprawnienia, niż nadawać któryś z tych dwóch CAP'ów. Oczywiście nie zawsze będzie można to uczynić i w pewnych sytuacjach AppArmor/SELinux będzie nas prosił o dac_read_search lub/i dac_override i jeśli ich nie przyznamy, to nasza aplikacja będzie mieć defekty w działaniu.

Mikhail Morfikov avatar
Mikhail Morfikov
Po ponad 10 latach spędzonych z różnej maści linux'ami (Debian/Ubuntu, OpenWRT, Android) mogę śmiało powiedzieć, że nie ma rzeczy niemożliwych i problemów, których nie da się rozwiązać. Jedną umiejętność, którą ludzki umysł musi posiąść, by wybrnąć nawet z tej najbardziej nieprzyjemniej sytuacji, to zdolność logicznego rozumowania.