NFsec Logo

AppArmor – Zbroja dla (web)aplikacji

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 ControlMAC), który jest rozszerzeniem jądra (ang. Linux Security ModulesLSM) 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

Kategorie K a t e g o r i e : Bezpieczeństwo

Tagi T a g i : , , , , , , , , , , ,

Komentowanie tego wpisu jest zablokowane.