AppArmor – Zbroja dla (web)aplikacji
Napisał: Patryk Krawaczyński
10/04/2020 w Bezpieczeństwo Brak komentarzy. (artykuł nr 730, ilość słów: 2831)
A
ppArmor to system obowiązkowej kontroli dostępu (ang. Mandatory Access Control – MAC), który jest rozszerzeniem jądra (ang. Linux Security Modules – LSM) w celu ograniczenia programów do określonego zestawu zasobów. Model bezpieczeństwa AppArmor polega na przywiązywaniu atrybutów kontroli dostępów z programami, a nie z użytkownikami. Ograniczenia są obsługiwane za pomocą profili ładowanych do jądra – najczęściej podczas rozruchu systemu. Profile posiadają zazwyczaj dwa tryby pracy: egzekwowania (ang. enforcement) oraz uskarżania (ang. complain). Profile załadowane w trybie egzekwowania zasad spowodują wymuszanie ograniczeń zdefiniowanych w profilu, a także zgłaszanie prób ich naruszenia za pomocą daemona syslog lub auditd. Profile w trybie składania skarg nie będą egzekwować zasad tylko raportować próby ich naruszenia. Istnieje jeszcze trzeci tryb – audytu (ang. audit), w którym logowane są wszystkie sukcesy i niepowodzenia stosowania zasad z profilu.
DAC:
Podobnie jak większość innych LSM, AppArmor uzupełnia domyślną politykę DAC (ang. Discretionary Access Control), a nie ją zastępuje. DAC dla przypomnienia definiuje podstawowe kontrole dostępu do obiektów w systemie plików. Jest to typowa kontrola dostępu zapewniana przez uprawnienia do plików, a uprawnienia dostępu są zazwyczaj w gestii właściciela obiektu (pliku, katalogu, urządzenia). DAC umożliwia ograniczenie dostępu do obiektów na podstawie tożsamości użytkowników lub grup (podmiotów), które próbują uzyskać do nich dostęp. W zależności od uprawnień dostępu podmiotu – może on także być w stanie przekazać uprawnienia innym podmiotom:
# ls -la /etc/hosts -rw-r--r--. 1 root root 120 Jun 17 14:40 /etc/hosts
W powyższym przykładzie root jest właścicielem obiektu (pliku) o nazwie hosts
i ma uprawnienia odczytu i zapisu dla tego obiektu. Polecenia chmod
, chown
, chusr
oraz chgrp
pomagają nam zmienić uprawnienia DAC do obiektu w systemie plików Linux / Unix.
MAC:
Obowiązkowa kontrola dostępu to mechanizm bezpieczeństwa, który ogranicza poziom kontroli, jaką użytkownicy (podmioty) mają nad tworzonymi przez siebie obiektami. W przeciwieństwie do implementacji DAC, w której użytkownicy mają pełną kontrolę nad własnymi plikami, katalogami itp., MAC dodaje dodatkowe etykiety lub kategorie do wszystkich obiektów systemu plików (SELinux) lub opiera je na ścieżkach dostępu (AppArmor). Użytkownicy i procesy muszą mieć odpowiedni dostęp do tych kategorii lub ścieżek, zanim będą mogli wchodzić w interakcję (lub uzyskiwać dostęp) z tymi obiektami.
AppArmor:
Ubuntu, SUSE i wiele innych dystrybucji używa go jako domyślny system MAC. RedHat (i jego warianty) używają SELinux, który wymaga dobrej integracji w przestrzeni użytkownika, aby działał poprawnie. SELinux dołącza wcześniej wspomniane etykiety do wszystkich plików, procesów i obiektów, dlatego jest bardzo elastyczny. Jednak skonfigurowanie SELinux również nie należy do najprostszych i wymaga obsługiwanego systemu plików. AppArmor różni się od niektórych innych systemów MAC w Linuksie: jest oparty o ścieżki, umożliwia trzy tryby pracy zdefiniowanych profili i umożliwia dołączenie mniejszych plików z gotowymi przepisami (ang. include files) w celu ułatwienia programowania zasad dostępu. Daje to mu znacznie niższą barierę wejścia dla użytkownika niż inne popularne systemy MAC.
Dobrze zdefiniowany profil zasad dostępu może proaktywnie chronić nasz system operacyjny i (web)aplikacje przez zagrożeniami zewnętrznymi lub wewnętrznymi, a nawet atakami typu 0-day, egzekwując określony zestaw reguł dla poszczególnych aplikacji. Zasady bezpieczeństwa całkowicie określają, do jakich zasobów systemowych mają dostęp poszczególne aplikacje i jakie posiadają do nich uprawnienia. Dostęp jest domyślnie zabroniony, jeśli żaden profil nie mówi inaczej. AppArmor zawiera kilka domyślnych zasad, a dzięki połączeniu zaawansowanych narzędzi do analizy statycznej i narzędzi opartych na uczeniu się, profile AppArmor nawet dla bardzo złożonych aplikacji można wdrożyć w ciagu kilku godzin. Architektura AppArmor:
------------------ [ AppArmor ] ------------------ [ Profile ] - [ Daemon ] - [ Serwer ] - [ Skrypt ] - [ Program ] ------------------ [ Moduł AppArmor ] ------------------ [ Interfejs LSM ] ------------------ [ Jądro Linux ] ------------------
Instalacja oprogramowania:
Wsparcie dla AppArmor zostało przedstawione w systemie Ubuntu od wersji 7.04 i jest standardowo włączone od wersji 7.10 (początkowo w 1998 roku program ten był rozwijany przez firmę Immunix pod nazwą SubDomain, po przejęciu przez firmę Novell w 2005 jego rozwój nabrał rozpędu zostając przemianowanym na AppArmor ostatecznie trafiając do firmy Canonical). Jak zostało wspomniane wcześniej ograniczenia ukierunkowane na daną aplikację są dostępne za pomocą profili dla określonych plików binarnych. Z każdą wersją dystrybucji tworzonych jest coraz więcej profili, a kolejne są planowane. Podstawowe oprogramowanie możemy zainstalować poleceniem:
apt install -y apparmor apparmor-utils apparmor-easyprof
Po zakończeniu instalacji weryfikację działania modułu możemy wykonać poleceniem: aa-enabled
:
root@darkstar:~# aa-enabled Yes
W celu wyświetlenia informacji o bieżących zasadach Apparmor możemy użyć komendy: apparmor_status
lub aa-status
:
root@darkstar:~# aa-status apparmor module is loaded. 3 profiles are loaded. 3 profiles are in enforce mode. /sbin/dhclient /usr/bin/lxc-start /usr/bin/man 0 profiles are in complain mode. 0 processes have profiles defined. 0 processes are in enforce mode. 0 processes are in complain mode. 0 processes are unconfined but have a profile defined.
Możemy także zobaczyć listę aktualnie załadowanych profili poprzez odpytanie procfs:
root@darkstar:~# cat /sys/kernel/security/apparmor/profiles /usr/bin/man (enforce) /usr/bin/lxc-start (enforce) /sbin/dhclient (enforce)
Tworzenie profili:
AppArmor posiada zestaw kilku programów, które mogą nam pomóc w tworzeniu profilu dla wybranej aplikacji. Należy pamiętać, że profile dotyczą procesów, a nie systemu. Stworzenie profilu i nadanie w nim odpowiednich uprawnień to krytyczne zadanie z punktu widzenia bezpieczeństwa, jakie AppArmor ma nam zapewnić.
Analiza programów – za pomocą narzędzia aa-unconfined
możemy przeprowadzić automatyczne skanowanie portów i wykrywanie programów prowadzących nasłuch na portach. Umożliwia nam identyfikacje aplikacji bez proflili, które mogą być ograniczone przez AppArmor:
root@darkstar:~# aa-unconfined 949 /usr/bin/memcached not confined 1041 /usr/sbin/sshd not confined 1151 /usr/sbin/mysqld not confined 1279 /usr/bin/noderig not confined 1393 /usr/sbin/postfix not confined
Generator profili – pozwala na statyczną analizę programów lub skryptów dostarczając przy tym podstawowe szablony. Na początek użyjemy narzędzia aa-easyprof
w celu wygenerowania szkieletu polityki dla skryptu profileme.sh; pamiętajmy, aby zawsze określić bezwzględną ścieżkę do programu:
# aa-easyprof /home/agresor/profileme.sh > /etc/apparmor.d/home.agresor.profileme.sh # cat /etc/apparmor.d/home.agresor.profileme.sh # vim:syntax=apparmor # AppArmor policy for profileme.sh # ###AUTHOR### # ###COPYRIGHT### # ###COMMENT### #include <tunables/global> # No template variables specified "/home/agresor/profileme.sh" { #include <abstractions/base> # No abstractions specified # No policy groups specified # No read paths specified # No write paths specified }
Utworzone profile znajdują się w katalogu /etc/apparmor.d. Ich nazwa tworzona jest na podstawie ścieżki do pliku, gdzie znak "/"
zamieniony jest na kropkę "."
, co możemy zaobserwować w przykładzie powyżej. Istnieje wiele dróg na stworzenie profilu. Każda z nich oferuje różną dokładność, z jaką chcemy monitorować daną aplikację. Na przykład aa-easyprof
doskonale nadaje się do stworzenia szablonu, który można później uzupełniać ręczne o kolejne reguły lub też stworzyć profil półautomatycznie za pomocą innych narzędzi. Proces ten zastosujemy na prostym skrypcie:
#!/bin/bash touch /tmp/test.txt echo "Write test." > /tmp/test.txt cp /tmp/test.txt /home/agresor/hello.txt rm /tmp/test.txt rm /home/agresor/hello.txt echo "DONE."
Posiadając już wstępny szkielet możemy załadować profil do jądra oraz ustawić go w tryb nauki, w którym nasza polityka będzie jedynie monitorowana, a wszystkie akcje zapisywane w dzienniku systemowym:
apparmor_parser -r /etc/apparmor.d/home.agresor.profileme.sh
Setting /etc/apparmor.d/home.agresor.profileme.sh to complain mode.
AppArmor wszystkie zabronione akcje loguje do pliku /var/log/syslog
(lub /var/log/audit/autid.log
, jeśli w systemie jest zainstalowany auditd). Jądro może ograniczać szybkość i ilość komunikatów AppArmor, co może powodować problemy podczas procesu profilowania. Na szczęście możemy tego uniknąć poprzez instalację auditd lub tymczasowym wyłączeniu mechanizmu dławienia ilości wiadomości:
sysctl -w kernel.printk_ratelimit=0
Dobrym sposobem wyświetlania odfiltrowanych informacji od AppArmor jest wykorzystanie narzędzia aa-notify
– na przykład:
apt install -y apparmor-notify aa-notify -s 1 -v
Profile: /home/agresor/profileme.sh Operation: open Name: /dev/tty Denied: wr Logfile: /var/log/syslog
Pokaże wszystkie komunikaty odmowy z AppArmor w ciągu ostatniego dnia. Podążymy teraz łatwą drogą do opracowania profilu dla skryptu profileme.sh i skorzystajmy z narzędzia aa-logprof
(innym często stosowanym jest również aa-genprof
), który za pomocą wpisów Apparmor w logach pomoże nam stworzyć profil. Na początek przestawmy jeszcze raz (dla pewności) tryb wcześniej zdefiniowanego szablonu tylko na monitorowanie zachowań:
aa-complain /etc/apparmor.d/home.agresor.profileme.sh
Po tej czynności powinniśmy zauważyć zmianę w linii 11, która dodaje informację o zmianie trybu:
/home/agresor/profileme.sh flags=(complain) {
Spróbujmy teraz uruchomić skrypt:
/home/agresor/profileme.sh
Natychmiast po tym fakcie powinny wygenerować się wpisy AppArmor:
Apr 6 20:20:04 darkstar kernel: [ 2142.320017] audit: type=1400 audit(156204404.630:11): apparmor="ALLOWED" operation="open" profile="/home/agresor/profileme.sh" name="/dev/tty" pid=1683 comm="profileme.sh" requested_mask="wr" denied_mask="wr" fsuid=0 ouid=0 Apr 6 20:20:04 darkstar kernel: [ 2142.320998] audit: type=1400 audit(156204404.630:12): apparmor="ALLOWED" operation="open" profile="/home/agresor/profileme.sh" name="/home/agresor/profileme.sh" pid=1683 comm="profileme.sh" requested_mask="r" denied_mask="r" fsuid=0 ouid=0 Apr 6 20:20:04 darkstar kernel: [ 2142.321705] audit: type=1400 audit(156204404.630:13): apparmor="ALLOWED" operation="exec" profile="/home/agresor/profileme.sh" name="/bin/touch" pid=1684 comm="profileme.sh" requested_mask="x" denied_mask="x" fsuid=0 ouid=0 target="/home/agresor/profileme.sh//null-/bin/touch"
ponieważ nie stworzyliśmy jeszcze żadnych reguł pozwalających na poruszanie się skryptu po systemie. Uruchamiając teraz narzędzie aa-logprof
spowodujemy, że przeanalizuje ono komunikaty AppArmor i zasugeruje nam reguły dla profilu, które pozwolą na uruchomienie sktyptu “w zamknięciu”:
root@darkstar:~# aa-logprof Reading log entries from /var/log/syslog. Updating AppArmor profiles in /etc/apparmor.d. Profile: /home/agresor/profileme.sh Execute: /bin/touch Severity: unknown (I)nherit / (C)hild / (N)amed / (X) ix On / (D)eny / Abo(r)t / (F)inish Profile: /home/agresor/profileme.sh Execute: /bin/cp Severity: unknown (I)nherit / (C)hild / (N)amed / (X) ix On / (D)eny / Abo(r)t / (F)inish Profile: /home/agresor/profileme.sh Execute: /bin/rm Severity: unknown (I)nherit / (C)hild / (N)amed / (X) ix On / (D)eny / Abo(r)t / (F)inish Complain-mode changes: Profile: /home/agresor/profileme.sh Capability: dac_override Severity: 9 [1 - capability dac_override,] (A)llow / [(D)eny] / (I)gnore / Audi(t) / Abo(r)t / (F)inish Adding capability dac_override, to profile. Profile: /home/agresor/profileme.sh Path: /dev/tty New Mode: owner rw Severity: 9 [1 - #include <abstractions/consoles>] 2 - owner /dev/tty rw, (A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / (O)wner permissions off / Abo(r)t / (F)inish Profile: /home/agresor/profileme.sh Path: /dev/tty New Mode: owner rw Severity: 9 1 - #include <abstractions/consoles> [2 - owner /dev/tty rw,] (A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / (O)wner permissions off / Abo(r)t / (F)inish Adding owner /dev/tty rw, to profile. Profile: /home/agresor/profileme.sh Path: /home/agresor/profileme.sh New Mode: owner r Severity: 4 [1 - owner /home/*/profileme.sh r,] 2 - owner /home/agresor/profileme.sh r, (A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / (O)wner permissions off / Abo(r)t / (F)inish Profile: /home/agresor/profileme.sh Path: /home/agresor/profileme.sh New Mode: owner r Severity: 4 1 - owner /home/*/profileme.sh r, [2 - owner /home/agresor/profileme.sh r,] (A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / (O)wner permissions off / Abo(r)t / (F)inish Adding owner /home/agresor/profileme.sh r, to profile. Profile: /home/agresor/profileme.sh Path: /tmp/test.txt New Mode: owner rw Severity: unknown [1 - #include <abstractions/user-tmp>] 2 - owner /tmp/test.txt rw, (A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / (O)wner permissions off / Abo(r)t / (F)inish Profile: /home/agresor/profileme.sh Path: /tmp/test.txt New Mode: owner rw Severity: unknown 1 - #include <abstractions/user-tmp> [2 - owner /tmp/test.txt rw,] (A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / (O)wner permissions off / Abo(r)t / (F)inish Adding owner /tmp/test.txt rw, to profile. Profile: /home/agresor/profileme.sh Path: /lib/x86_64-linux-gnu/ld-2.27.so Old Mode: r New Mode: owner mr Severity: unknown [1 - owner /lib/x86_64-linux-gnu/ld-*.so mr,] 2 - owner /{usr/,}lib{,32,64}/** mr, 3 - owner /lib/x86_64-linux-gnu/ld-2.27.so mr, (A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / (O)wner permissions off / Abo(r)t / (F)inish Profile: /home/agresor/profileme.sh Path: /lib/x86_64-linux-gnu/ld-2.27.so Old Mode: r New Mode: owner mr Severity: unknown 1 - owner /lib/x86_64-linux-gnu/ld-*.so mr, 2 - owner /{usr/,}lib{,32,64}/** mr, [3 - owner /lib/x86_64-linux-gnu/ld-2.27.so mr,] (A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / (O)wner permissions off / Abo(r)t / (F)inish Adding owner /lib/x86_64-linux-gnu/ld-2.27.so mr, to profile. Profile: /home/agresor/profileme.sh Path: /proc/filesystems New Mode: owner r Severity: 6 [1 - owner /proc/filesystems r,] (A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / (O)wner permissions off / Abo(r)t / (F)inish Adding owner /proc/filesystems r, to profile. Profile: /home/agresor/profileme.sh Path: /home/agresor/hello.txt New Mode: owner w Severity: 6 [1 - owner /home/*/hello.txt w,] 2 - owner /home/agresor/hello.txt w, (A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / (O)wner permissions off / Abo(r)t / (F)inish Profile: /home/agresor/profileme.sh Path: /home/agresor/hello.txt New Mode: owner w Severity: 6 1 - owner /home/*/hello.txt w, [2 - owner /home/agresor/hello.txt w,] (A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / (O)wner permissions off / Abo(r)t / (F)inish Adding owner /home/agresor/hello.txt w, to profile. = Changed Local Profiles = The following local profiles were changed. Would you like to save them? [1 - /home/agresor/profileme.sh] (S)ave Changes / Save Selec(t)ed Profile / [(V)iew Changes] / View Changes b/w (C)lean profiles / Abo(r)t Writing updated profile for /home/agresor/profileme.sh.
Po zapisaniu profilu możemy go przeładować, aby dodać nowe reguły:
apparmor_parser -r /etc/apparmor.d/home.agresor.profileme.sh cat /etc/apparmor.d/home.agresor.profileme.sh
# Last Modified: Mon Apr 6 21:44:15 2020 #include <tunables/global> # vim:syntax=apparmor # AppArmor policy for profileme.sh # AUTHOR # COPYRIGHT # COMMENT # No template variables specified /home/agresor/profileme.sh flags=(complain) { #include <abstractions/base> capability dac_override, /bin/cp mrix, /bin/rm mrix, /bin/touch mrix, owner /dev/tty rw, owner /home/agresor/hello.txt w, owner /home/agresor/profileme.sh r, owner /lib/x86_64-linux-gnu/ld-2.27.so mr, owner /proc/filesystems r, owner /tmp/test.txt rw, }
Następnie powinniśmy uruchomić ponownie skrypt i upewnić się, że żadne, nowe wpisy nie pojawiają się w logach. Posiadając czysty dziennik – możemy przełączyć skrypt w tryb egzektowania reguł z profilu:
aa-enforce /etc/apparmor.d/home.agresor.profileme.sh
Jeśli teraz zmienimy nazwę pliku gdzie zapisywane są dane lub dokonamy innej modyfikacji dopuszczonych ścieżek – akcje z nimi związane zostaną zablokowane:
root@darkstar:~# aa-enforce /etc/apparmor.d/home.agresor.profileme.sh Setting /etc/apparmor.d/home.agresor.profileme.sh to enforce mode. root@darkstar:~# cat /var/log/syslog Apr 6 22:03:36 darkstar kernel: [ 8353.780377] audit: type=1400 audit(156210616.144:392): apparmor="DENIED" operation="mknod" profile="/home/agresor/profileme.sh" name="/tmp/hacked.txt" pid=2337 comm="profileme.sh" requested_mask="c" denied_mask="c" fsuid=0 ouid=0
Jeśli chcemy być paranoicznie pewni możemy dodać kilka reguł blokujących, aby upewnić się, że nie da się odczytać niektórych danych. Chociaż profile AppArmor mają domyślną politykę blokady w standardzie to dodanie jawnych reguł odmowy może zabezpieczyć nas przed błędami w profilu:
deny /tmp/secured/ rw, deny /tmp/secred_key rw,
Nawet jeśli docelowy katalog jeszcze nie istnieje w systemie to reguła nadal będzie aktualna, gdyby któregoś dnia został utworzony. Pamiętajmy, gdy chcemy określić katalog na końcu dodajemy znak “/
” – w ten sposób AppArmor jest w stanie odróżnić katalog od pliku. Jeśli chcemy tymczasowo wyłączyć profil danego programu lub aplikacji wystarczy wydać polecenie:
aa-disable /home/agresor/profileme.sh
Inne wskazówki, które mogą nam pomóc w budowaniu profili to:
- AppArmor zapewnia dodatkowe kontrole dla tradycyjnych uprawnień typu DAC. Normalne uprawnienia są zawsze sprawdzane oprócz kontroli uprawnien z poziomu AppArmor. W związku z tym AppArmor nie może zapewnić użytkownikowi większych uprawnień niż te, które są w DAC.
- AppArmor normalizuje nazwy ścieżek dostępu. Rozwiązuje on symboliczne dowiązanie (ang. symbolic link) i traktuje każde dowiązanie twarde (ang. hard link) jako inną ścieżkę dostępu.
- Reguły zabraniające nie mogą być nadpisane przez reguły dopuszczające.
- Tworzenie plików wymaga odpowiednich uprawnień (
w
) w ścieżce dostępu. Oddzielne reguły zapisu do katalogu, w którym znajduje się dany plik nie są wymagane. Usuwanie działa podobnie jak tworzenie i wymaga tych samych uprawnień (w
). Kopiowanie wymaga uprawnień odczytu ze źródła (r
) i zapisu w miejscu docelowym (w
). Przesunięcie działa podobnie jak kopiowanie, ale wymaga dodatkowo praw usunięcia ze źródła (w
) - Profil musi być załadowany przed uruchomieniem aplikacji, aby ograniczenia mogły obowiązywać. Jeżeli aplikacja będzie działać, a dodamy nowe reguły i przeładujemy profil – zaczną one obowiązywać natychmiast.
Wykorzystanie profili:
Profile AppArmor możemy wykorzystać w wielu przypadkach, ale najczęściej będą to punkty umożliwiające wejście do systemu. Dla komputera domowego będzie do przeglądarka, a dla serwera webaplikacja. Spójrzmy na przykład zabezpieczenia PHP przez atakiem RCE (ang. Remote Command Execution) oraz LFI (ang. Local File Inclusion). Na początek tworzymy profil dla php-fpm, który komunikuje się z serwerem HTTP po lokalnym gnieździe:
# Last Modified: Thu Feb 21 04:28:56 2019 #include <tunables/global> /usr/sbin/php-fpm7.2 flags=(attach_disconnected) { #include <abstractions/base> #include <abstractions/nameservice> #include <abstractions/openssl> #include <abstractions/php> capability chown, capability dac_override, capability kill, capability net_admin, capability setgid, capability setuid, deny owner / rw, /etc/php/7.2/fpm/php-fpm.conf r, /etc/php/7.2/fpm/pool.d/www.conf r, /var/www/** r, /lib/x86_64-linux-gnu/ld-*.so mr, /run/php/php-fpm.pid w, /run/php/php-fpm.sock rwlk, /run/mysqld/mysqld.sock rwlk, /run/systemd/notify w, /usr/sbin/php-fpm7.2 mr, /var/log/php-fpm.log w, }
Następnie umieszczamy w ścieżce /var/www “specjalny” skrypt test.php:
<?php if(isset($_GET['cmd'])) { system($_GET['cmd']); } if(isset($_GET['inc'])) { include($_GET['inc']); } ?>
Aby jego działanie nie było przerwane przez inne mechanizmy w konfiguracji PHP (php.ini
) wyłączamy:
; open_basedir = /var/www ; disable_functions = pcntl_alarm, pcntl_fork, pcntl_waitpid, pcntl_wait, pcntl_wifexited, pcntl_wifstopped, pcntl_wifsignaled, pcntl_wifcontinued, pcntl_wexitstatus ,pcntl_wtermsig, pcntl_wstopsig,pcntl_signal, pcntl_signal_get_handler, pcntl_signal_dispatch, pcntl_get_last_error, pcntl_strerror, pcntl_sigprocmask, pcntl_sigwaitinfo, pcntl_sigtimedwait, pcntl_exec, pcntl_getpriority, pcntl_setpriority, pcntl_async_signals, exec, passthru, shell_exec, system, proc_open, popen, curl_exec, curl_multi_exec,phpinfo
Następnie wywołujemy skrypt w celu wykonania RCE:
curl -s 'http://darkstar.localhost/test.php?cmd=id'
Skrypt nie powinien zwrócić żadnej treści w odpowiedzi, my za to w logach powinniśmy zobaczyć:
Apr 9 23:21:36 darkstar kernel: [462546.621023] audit: type=1400 audit(156467296.529:333): apparmor="DENIED" operation="exec" profile="/usr/sbin/php-fpm7.2" name="/bin/bash" pid=29270 comm="php-fpm7.2" requested_mask="x" denied_mask="x" fsuid=33 ouid=0 target="/usr/sbin/php-fpm7.2//null-/bin/bash"
Stwórzmy teraz w katalogu tymczasowym (bardzo często wykorzystywanym przez szkodliwe oprogramowanie) plik i spróbumy odczytać jego zawartość poprzez żądanie HTTP:
touch /tmp/payload.log echo "Hello Moto" > /tmp/payload.log chmod 644 /tmp/payload.log curl -s 'http://darkstar.localhost/test.php?inc=/tmp/payload.log'
Skrypt nie powinien zwrócić żadnej treści w odpowiedzi, my za to w logach powinniśmy zobaczyć:
Apr 9 23:29:32 darkstar kernel: [463022.967836] audit: type=1400 audit(156467772.859:389): apparmor="DENIED" operation="open" profile="/usr/sbin/php-fpm7.2" name="/tmp/payload.log" pid=29346 comm="php-fpm7.2" requested_mask="r" denied_mask="r" fsuid=33 ouid=0
Zresztą samo umieszczenie skryptu typu webshell by było bardzo utrudnione ze względu na prawo tylko do odczytu w całej ścieżce /var/www (/var/www/** r
).
Więcej informacji: AppArmor Core Policy Reference, How to create an AppArmor Profile, AppArmor How To Use, AppArmor: Say Goodbye to Remote Command Execution, Confining Privileges with AppArmor