Proving Grounds: CVE-2025-27136 Writeup
Proving Grounds is Offensive Security’s practice lab platform. This is a writeup for CVE-2025-27136, rated Intermediate with no community rating. It involves exploiting an XML parsing vulnerability with an XXE payload on a LocalS3 instance to leak the root user’s SSH private key, then using that private key to SSH into the server as root to obtain the flag.
Recon
As always, I started this off with an nmap scan:
1
sudo nmap -Pn -n 192.168.110.161 -sC -sV -p- --open
This returned a lot of information, with not a ton of it being super useful. The key things to highlight here are: SSH is open, and there is a service running on port 8080 with the server header of LocalS3.
When trying to access the server on port 8080 through a web browser I saw this:
I tried a few directory enumeration tools to see if I could find any S3 buckets or files on the server, but got nothing.
At this point I looked up the CVE that the challenge was titled after, and found a PoC for it on GitHub.
That pretty much concludes the recon phase. This was a very quick lab compared to the previous two writeups.
Exploitation
The lab description mentioned using this exploit to obtain an SSH private key. The only problem with this is I didn’t know whose private key I was supposed to use.
However this wasn’t much of a problem knowing I could leak files stored on the server with the PoC exploit. I just pointed the payload at file:///etc/shadow.
After that, I used curl to send a pretty simple PUT request to a random bucket endpoint that didn’t exist.
1
curl -X PUT http://192.168.218.238:8080/bucket-name -H "Content-Type: application/xml" -d @xxe_payload.xml
Next I just sent a second curl request to that newly created endpoint to trigger the exploit.
1
curl http://192.168.218.238:8080/bucket-name/?location
This gave me a list of potential accounts I could steal the private key from. Only two of these are even an option, root and sync. Everything else is clearly marked with /usr/sbin/nologin.
As you can see in the screenshot, there was no real feedback that the bucket was successfully configured, so I tried creating it twice. This let me know that the bucket ‘bucket-name’ already exist. This isn’t necessary for the exploit to work.
Getting root user access
Choosing between stealing the private key of the root user or a user called sync, I think we can all agree root is the clear choice here. Getting this SSH key was basically the exact same process as before.
The single difference between the two is instead of file:///etc/passwd, I instead used file:///root/.ssh/id_rsa. This is the default name and location when generating a private key as the root user on a Linux machine.
After that, I used the exact same process to upload and trigger the payload.
And would you look at that, an OpenSSH private key.
All that was left to do now was copy the key into a file, change the permissions, SSH into the machine, and retrieve the flag.
A simple ls immediately revealed the flag located in proof.txt.
Reflection
This was by far the easiest lab I’ve done so far. The exploit worked exactly as the PoCs said it would, with very little I had to do differently.
I ended up completing the lab in a little over an hour, which I am definitely happy with.
Tools used: nmap, curl, GitHub








