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.