Morfitronik Security & Privacy

Jak załadować profile AppArmor w fazie initrd/initramfs na Debian Linux

2019-09-23 19:05:21
Morfik

Zapewne wielu użytkowników Debiana zdążyło już zauważyć, że od wydania 10 (Buster) AppArmor jest włączony domyślnie. Nie powinien on raczej sprawiać żadnych problemów po doinstalowaniu pakietów apparmor-profiles oraz apparmor-profiles-extra , które zawierają szereg profili pod różne aplikacje użytkowe. Niemniej jednak, pewnych procesów nie da się ograniczyć przez AppArmor, przynajmniej nie w standardowy sposób. Chodzi o to, że jeśli mamy już odpalony jakiś proces, to nie ma możliwości zamknąć go w profilu AA do momentu aż zakończy on swoje działanie i zostanie uruchomiony ponownie. Profile AppArmor’a są ładowane podczas startu systemu w pewnym określonym momencie ale szereg procesów systemowych startuje sporo wcześniej w stosunku do usługi AppArmor’a. W taki sposób nawet jeśli w późniejszym czasie profile zostaną załadowane, to i tak część procesów nie będzie ograniczona bez względu na to czy zdefiniowaliśmy im zestaw reguł. Oczywiście można próbować restartować usługi lub szeregować je po apparmor.service ale nie zawsze tak się da zrobić. Alternatywnym rozwiązaniem tego problemu jest ładowanie polityki AppArmor’a w fazie initrd/initramfs, czyli w momencie, w którym nasz system nie ma jeszcze nawet uruchomionego procesu z PID z numerkiem 1 .

Przeniesienie procesu ładowania profili do initrd/initramfs

Wiemy już, że nie możemy polegać na usługach systemowych mających za zadanie aplikować reguły podczas startu systemu. Musimy zatem się zatroszczyć o ręczne ich ładowanie w fazie initrd/initramfs. W tym celu potrzebne będą nam dwa skrypty.

Poniżej znajduje się zawartość pliku /etc/initramfs-tools/hooks/apparmor :

#!/bin/sh

set -e

PREREQ=""
prereqs()
{
   echo "$PREREQ"
}

case $1 in
prereqs)
   prereqs
   exit 0
   ;;
esac

[ -r /usr/share/initramfs-tools/hook-functions ] || exit 0
. /usr/share/initramfs-tools/hook-functions

copy_exec /sbin/apparmor_parser /sbin

mkdir -p $DESTDIR/etc/apparmor/
cp -a /etc/apparmor/ $DESTDIR/etc/
mkdir -p $DESTDIR/usr/share/apparmor-features/
cp -a /usr/share/apparmor-features/features $DESTDIR/usr/share/apparmor-features/
mkdir -p $DESTDIR/etc/apparmor.d/
cp -a /etc/apparmor.d/ $DESTDIR/etc/

for i in $(ls /etc/apparmor.d/disable/); do rm $DESTDIR/etc/apparmor.d/$i ;done
rm -R $DESTDIR/etc/apparmor.d/disable/

Ten powyższy skrypt ma za zadanie skopiować binarkę apparmor_parser oraz wszystkie niezbędne jej pliki do obrazu initrd/initramfs. W tym obrazie mają znaleźć się także wszystkie profile AppArmor’a, które mamy zdefiniowane w katalogu /etc/apparmor.d/ . Jako, że cześć profili AA może być przez nas wyłączona (linki do katalogu /etc/apparmor.d/disable/ ), to musimy się ich pozbyć z obrazu, tak by nie zostały one przez przypadek załadowane.

Niżej zaś znajduje się zawartość pliku /etc/initramfs-tools/scripts/init-bottom/apparmor :

#!/bin/sh

PREREQ=""
prereqs()
{
   echo "$PREREQ"
}

case $1 in
prereqs)
   prereqs
   exit 0
   ;;
esac

export PATH=/sbin:/usr/sbin:/bin:/usr/bin

mount -t securityfs none /sys/kernel/security

echo -en "\n *** \033[5mApplying AppArmor profile list\033[0m ..."

profile_list=$(find /etc/apparmor.d/ -maxdepth 1 -type f)
apparmor_parser -a $profile_list
if [ $? -eq 0 ]; then
    echo -e " \033[32mOK\033[0m"
else
    echo -e " \033[31mFAIL\033[0m"
fi

Ten skrypt z kolei ma za zadanie zamontować /sys/kernel/security w fazie initrd/initramfs oraz zaaplikować reguły obecne w plikach profili. Warto tutaj zaznaczyć, by nie wywoływać apparmor_parser dla każdego profilu z osobna, bo załadowanie ich w taki sposób może zająć nawet kilka minut. Lepszym rozwiązaniem jest po prostu podanie wszystkich profili w argumencie dla apparmor_parser , co zaoszczędzi nam sporo czasu podczas startu systemu.

Pamiętajmy by obu skryptom nadać prawa wykonywania:

# chmod +x /etc/initramfs-tools/hooks/apparmor
# chmod +x /etc/initramfs-tools/scripts/init-bottom/apparmor

Generowanie obrazu initrd/initramfs

Generujemy teraz obraz initrd/initramfs przy pomocy update-initramfs :

# update-initramfs -u -k all

Tak utworzony obraz powinien zawierać już wszystkie niezbędne pliki do zastosowania polityki AppArmor’a w fazie initrd/initramfs. Możemy na wszelki wypadek podejrzeć jeszcze sam obraz:

# lsinitramfs /boot/initrd.img-5.3.0-amd64| grep apparmor
etc/apparmor
etc/apparmor.d
...
usr/sbin/apparmor_parser
...

Usługa systemd apparmor.service

AppArmor dostarcza usługę dla systemd – apparmor.service i to ona standardowo ładuje profile AA podczas startu systemu. My ten krok ładowania profili mamy zrobiony już w fazie initrd/initramfs i ponowne ładowanie profili podczas startu systemu jest już pozbawione sensu. Ta usługa jest dla nas praktycznie bezużyteczna i możemy ją sobie spokojnie wyłączyć:

# systemctl disable apparmor.service

Test ładowania polityki AppArmor’a

Teraz wystarczy już jedynie restartować komputer. Zaraz na samym początku powinniśmy zauważyć informację o ładowaniu profili AA:

Po tym jak system się uruchomi, wpisujemy w terminal aa-status by sprawdzić czy profile zostały załadowane oraz czy interesujące nas usługi systemowe są chronione:

Jak widać, zostało załadowanych nieco ponad 550 profili. Spośród wszystkich procesów aktualnie działających w systemie, 51 jest ograniczonych przez politykę AA (49 enforce i 2 complain). Warto zwrócić uwagę, że nie ma żadnego procesu który by miał zdefiniowany profil ale działał bez ograniczeń ze strony AppArmor’a. W taki oto sposób można ograniczyć praktycznie dowolny proces działający w systemie, nawet ten mający PID z numerem 1.


Komentarze

Zawartość wpisu