Zastosuj SELinux

SELinux ma ustawione domyślne odmowa dostępu, co oznacza, że każdy dostęp który ma zaczep w jądrze, musi być wyraźnie dozwolony przez zasadę. Ten oznacza, że plik zasad zawiera dużą ilość informacji na temat reguły, typy, zajęcia, uprawnienia i nie tylko. Pełna analiza SELinux wykracza poza zakres tego dokumentu, ale zrozumienie sposobu pisania reguł zasad jest teraz niezbędne przy wprowadzaniu nowych urządzeń z Androidem. W internecie można znaleźć wiele informacji na temat SELinux. Patrz sekcja Pomoc techniczna dokumentacji z sugerowanymi materiałami.

Pliki kluczy

Aby włączyć SELinux, zintegruj najnowsze jądro Androida, a potem dodaj pliki znajdujące się w katalogu system/sepolicy. Po skompilowaniu te pliki stanowią zabezpieczenia jądra SELinux i obejmują starsze wersje systemu operacyjnego Android.

Ogólnie nie należy modyfikować plików system/sepolicy bezpośrednio. Zamiast tego dodaj lub zmodyfikuj własne pliki zasad dotyczących urządzeń w katalogu /device/manufacturer/device-name/sepolicy. W Androidzie 8.0 i nowszych zmiany wprowadzane w tych plikach powinny mają wpływ tylko na zasady w katalogu dostawcy. Więcej informacji o oddzielaniu publicznych zasad SEPolicy w Androidzie 8.0 i nowszych znajdziesz w artykule Dostosowywanie SEPolicy w Androidzie 8.0 i nowszych wersjach. Niezależnie od wersji Androida nadal modyfikujesz te pliki:

Pliki zasad

Pliki z końcówką *.te to pliki źródłowe zasad SELinux, definiowanie domen i ich etykiet. Może być konieczne utworzenie nowych plików zasad w /device/manufacturer/device-name/sepolicy, ale staraj się aktualizować istniejące pliki, gdy tylko jest to możliwe.

Pliki kontekstu

W plikach kontekstowych określasz etykiety swoich obiektów.

  • file_contexts przypisuje etykiety do plików i jest używany przez różne komponentów przestrzeni użytkownika. Podczas tworzenia nowych zasad utwórz lub zaktualizuj ten plik, aby przypisać do plików nowe etykiety. Aby zastosować nową file_contexts, ponownie utworzyć obraz systemu plików lub uruchomić restorecon dla pliku, zmienić etykiety. Podczas przekształcania zmiany w file_contexts są automatycznie stosowane do partycji systemowej i partycji danych użytkownika w ramach przekształcania. Zmiany można też automatycznie stosować podczas uaktualniania innych partycji, dodając do pliku init.board.rc wywołania restorecon_recursive po zamontowaniu partycji do odczytu i zapisu.
  • genfs_contexts przypisuje etykiety do systemów plików, takich jak proc lub vfat, które nie obsługują rozszerzonych połączeń . Ta konfiguracja jest wczytywana jako część zasady jądra, ale zmiany mogą nie zadziałać w przypadku izorów w rdzeniu, wymagając ponownego uruchomienia lub odłącz i ponownie podłącz system plików, aby w pełni zastosować zmianę. Określone etykiety mogą być też przypisane do konkretnych uchwytów, takich jak vfat, za pomocą opcji context=mount.
  • property_contexts przypisuje etykiety właściwościom systemu Android, aby kontrolować, które procesy mogą je ustawiać. Ta konfiguracja jest odczytywana przez Proces init podczas uruchamiania.
  • service_contexts przypisuje etykiety usługom bindera Androida, aby kontrolować, które procesy mogą dodawać (rejestrować) i znajdować (wyszukiwać) odwołanie bindera dla usługi. Ta konfiguracja jest odczytywana przez proces servicemanager podczas uruchamiania.
  • seapp_contexts przypisuje etykiety do procesów aplikacji i katalogów /data/data. Ta konfiguracja jest odczytywana przez proces zygote przy każdym uruchomieniu aplikacji oraz przez installd podczas uruchamiania.
  • mac_permissions.xml przypisuje tag seinfo do aplikacji na podstawie ich sygnatury i opcjonalnie nazwy pakietu. Tag seinfo może być następnie używany jako klucz w seapp_contexts, aby przypisać określoną etykietę do wszystkich aplikacji z ten tag seinfo. Ta konfiguracja jest odczytywana przez system_server podczas uruchamiania.
  • keystore2_key_contexts przypisuje etykiety do przestrzeni nazw Keystore 2.0. Te przestrzenie nazw są wymuszane przez demona keystore2. Keystore zawsze udostępniał przestrzenie nazw na podstawie identyfikatorów UID/AID. Keystore 2.0 dodatkowo wymusza przestrzenie nazw zdefiniowane w pliku sepolicy. Szczegółowy opis formatu i konwencji znajdziesz tutaj.

Plik Makefile BoardConfig.mk

Po zmodyfikowaniu lub dodaniu plików zasad i kontekstu zaktualizuj plik /device/manufacturer/device-name/BoardConfig.mkmakefile, aby odwoływał się do podkatalogu sepolicy i każdego nowego pliku zasad. Więcej informacji na temat zmiennych BOARD_SEPOLICY znajdziesz tutaj: system/sepolicy/README.

BOARD_SEPOLICY_DIRS += \
        <root>/device/manufacturer/device-name/sepolicy

BOARD_SEPOLICY_UNION += \
        genfs_contexts \
        file_contexts \
        sepolicy.te

Po przebudowaniu SELinux jest włączony na urządzeniu. Możesz teraz dostosować zasady SELinux, aby uwzględnić własne dodatki do systemu operacyjnego Android zgodnie z opisem w sekcji Personalizacja, lub zweryfikować istniejące ustawienia zgodnie z opisem w sekcji Weryfikacja.

Gdy nowe pliki zasad i aktualizacje pliku BoardConfig.mk zostaną zainstalowane, nowe ustawienia zasad zostaną automatycznie wbudowane w końcowy plik zasad jądra. Więcej informacji na temat tworzenia zasad Sepolicy na urządzeniu znajdziesz w sekcji Sepolicy tworzenia zasad.

Implementacja

Aby rozpocząć korzystanie z SELinux:

  1. Włącz SELinux w jądrze: CONFIG_SECURITY_SELINUX=y
  2. Zmień parametr kernel_cmdline lub polecenie startconfig tak, aby:
    BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
    lub
    BOARD_BOOTCONFIG := androidboot.selinux=permissive
    Służy tylko do wstępnego opracowywania zasad na urządzeniu. Po masz początkową zasadę wczytywania, usuń ten parametr, jest egzekwowane lub przestaje działać CTS.
  3. Uruchom system w trybie mniej rygorystycznym i sprawdź, jakie odmowy pojawiają się podczas uruchamiania:
    W systemie Ubuntu 14.04 lub nowszym:
    adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
    
    W systemie Ubuntu 12.04:
    adb pull /sys/fs/selinux/policy
    adb logcat -b all | audit2allow -p policy
    
  4. Oceń wyniki pod kątem ostrzeżeń podobnych do init: Warning! Service name needs a SELinux domain defined; please fix! Zobacz Weryfikacja instrukcji i narzędziami.
  5. Zidentyfikuj urządzenia i inne nowe pliki, które wymagają etykiet.
  6. Użyj istniejących lub nowych etykiet dla obiektów. Przejrzyj pliki *_contexts, aby sprawdzić, jak były wcześniej etykietowane, i przypisz nową etykietę, znając znaczenie poprzedniej. Najlepiej, istniejąca etykieta, która jest zgodna z naszymi zasadami, ale czasami potrzebujesz nowej etykiety, a reguły dostępu do niej są niezbędną. Dodaj etykiety do odpowiednich plików kontekstowych.
  7. Określ domeny/procesy, które powinny mieć własne domeny zabezpieczeń. Prawdopodobnie musisz napisać dla każdej z nich zupełnie nowe zasady. Wszystkie usługi utworzone na podstawie usługi init powinny mieć własne. Te polecenia pomogą Ci znaleźć usługi, które nadal działają (ale WSZYSTKIE usługi wymagają takiej obsługi):
    adb shell su -c ps -Z | grep init
    
    adb shell su -c dmesg | grep 'avc: '
    
  8. Sprawdź init.device.rc, aby zidentyfikować domeny, które nie mają typu domeny. Udostępnij im domenę wcześniej w programowania, aby uniknąć dodawania reguł do init lub myląc dostęp init z tymi, które są w ich do własnych zasad.
  9. Aby używać zmiennych BOARD_SEPOLICY_*, skonfiguruj BOARD_CONFIG.mk. Zobacz README (w języku angielskim) w system/sepolicy, aby dowiedzieć się, jak to skonfigurować.
  10. Sprawdź pliki init.device.rc i fstab.device i upewnij się, że każde użycie opcji mount odpowiada poprawnie oznaczonemu systemowi plików lub że określono opcję context= mount.
  11. Przejrzyj każdą odmowę i utwórz zasadę SELinux, która będzie obsługiwać każdą z nich. Zobacz przykłady w sekcji Dostosowywanie.

Zacznij od zasad podanych w AOSP, a następnie na ich podstawie na własne potrzeby. Więcej informacji o strategii dotyczącej zasad dokładniej przyjrzeć się niektórym z tych kroków, zobacz Zapisywanie zasad SELinux.

Przykłady zastosowań

Oto kilka przykładów luk w zabezpieczeniach, które warto wziąć pod uwagę podczas tworzenia własnych treści i powiązane zasady SELinux:

Dowiązania symboliczne: dowiązania symboliczne są wyświetlane jako pliki, dlatego często są i odczytać je jako pliki, co może prowadzić do ataku. Na przykład niektóre komponenty uprzywilejowane, takie jak init, zmieniają uprawnienia niektórych plików, czasami w nadmierny sposób.

Osoby przeprowadzające atak mogą zastąpić te pliki dowiązaniami symbolicznymi do kontrolowanego przez nich kodu. co pozwoli atakującym zastąpić dowolne pliki. Jeśli jednak wiesz, aplikacja nigdy nie przechodzi dowiązania symbolicznego, możesz tego zabronić z SELinux.

Pliki systemowe: weź pod uwagę klasę plików systemowych, które powinna być modyfikowana tylko przez serwer systemu. Mimo to, ponieważ netd, init i vold działają jako root, mają dostęp do tych plików systemowych. Jeśli netd zostanie naruszony, może to spowodować utratę tych plików i potencjalnie samego serwera systemu.

Dzięki SELinux możesz zidentyfikować te pliki jako pliki danych serwera systemowego. Dlatego jedyną domeną, która ma do nich dostęp tylko do odczytu i zapisu, jest serwer systemowy. Nawet jeśli netd zostanie naruszony, nie będzie można przełączyć domen na domenę serwera systemowego i uzyskać dostępu do tych plików systemowych, mimo że działa on jako root.

Dane aplikacji: kolejnym przykładem jest klasa funkcji, które muszą działać jako root, ale nie powinny mieć dostępu do danych aplikacji. To niesamowite, przydatne, ponieważ mogą być zgłaszane asercje o szerokim zakresie, na przykład określone domeny niepowiązane do danych aplikacji, które nie mają dostępu do internetu.

setattr: w przypadku poleceń takich jak chmod czy chown, możesz zidentyfikować zbiór plików, w których powiązane domena może przeprowadzić setattr. Wszystko inne może być zabronione, nawet przez użytkownika root. Aplikacja może więc działać na podstawie reguł chmodchown, ale nie shell_data_files ani system_data_files.