[Vulnhub] Ew_Skuzzy

Oh boy Skuzzy.  Eww indeed.  This one took me far longer than I’d care to admit.  However, after much trials and tribulations I finally got root.  Big thanks to g0tm1lk for the initial hint and drxpsec for getting me on track on the final flag.  Let’s begin.

As always, let’s start off with the nmap scan.

Ok.  We got a web server, port 514, and port 3260.  Let’s start off with the web server.

That’s a nice welcome.  We even got a place to look for hints.  Time to dirb it up.

root@kali:~/ew_skuzzy# cat dirb_output | grep 200
+ http://172.16.2.41/index.html (CODE:200|SIZE:1297)
==> DIRECTORY: http://172.16.2.41/smblogin/custom-log/
==> DIRECTORY: http://172.16.2.41/smblogin/custom-log/refer/
==> DIRECTORY: http://172.16.2.41/smblogin/custom-log/refer/del/
==&gt; DIRECTORY: http://172.16.2.41/smblogin/custom-log/refer/del/arquivos/ </code>

==&gt; DIRECTORY: http://172.16.2.41/smblogin/custom-log/refer/del/arquivos/_archive/autodeploy/
==&gt; DIRECTORY: http://172.16.2.41/smblogin/custom-log/refer/del/arquivos/_archive/autodeploy/Links/
==&gt; DIRECTORY: http://172.16.2.41/smblogin/custom-log/refer/del/arquivos/_archive/autodeploy/Links/pdf/
==&gt; DIRECTORY: http://172.16.2.41/smblogin/custom-log/refer/del/arquivos/_archive/autodeploy/Links/pdf/portals/
==&gt; DIRECTORY: http://172.16.2.41/smblogin/custom-log/refer/del/arquivos/_archive/autodeploy/Links/pdf/portals/images3/
==&gt; DIRECTORY: http://172.16.2.41/smblogin/custom-log/refer/del/arquivos/_archive/autodeploy/Links/pdf/portals/images3/forgotpassword/
==&gt; DIRECTORY: http://172.16.2.41/smblogin/custom-log/refer/del/arquivos/_archive/autodeploy/Links/pdf/portals/images3/forgotpassword/tuscany/
==&gt; DIRECTORY: http://172.16.2.41/smblogin/custom-log/refer/del/arquivos/_archive/autodeploy/Links/pdf/portals/images3/forgotpassword/tuscany/send-password/
==&gt; DIRECTORY: http://172.16.2.41/smblogin/custom-log/refer/del/arquivos/_archive/autodeploy/Links/pdf/portals/images3/forgotpassword/tuscany/send-password/catalog/
+ http://172.16.2.41/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 (CODE:200|SIZE:450)
+ http://172.16.2.41/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 (CODE:200|SIZE:527)

A couple of things that returned 200 codes.  Let’s check them out.

That’s some quality trolling.  It appears that the web site is a dead end.  Let’s investigate port 3260 some more.  What is ISCSI anyways?

http://searchstorage.techtarget.com/definition/iSCSI

Ah.  So it’s a network storage medium.  I bet there’s some juicy info on it.  But how do we connect to it?

https://help.ubuntu.com/lts/serverguide/iscsi-initiator.html

https://www.cyberciti.biz/faq/howto-setup-debian-ubuntu-linux-iscsi-initiator/

Those two sites got me started (especially the second one).  Eventually, I got the drive mounted and was able to take a look at the files.

And we’re rewarded with our first flag!  Also a very large .dsk file.  Let’s run strings against that and see what we get.

Oh.  Well there’s our second flag (and our 3rd flag).  I think we’re supposed to get this another way though.  After much research, I found that one can use PowerISO to mount the .dsk file.  Let’s take a look at what’s inside.

So we have an email, our second flag, and an encrypted file.  The email gives us a lot of hings about how to get into that file.

  • ROCKYOU is clearly a reference to the famous rockyou.txt password list
  • bleeding-edge is likely a reference to openssl (because heartbleed)
  • October 2000 competition?  2000.10.02: NIST announces its selection of AES.
  • -md SHA256 is the hashing algorithm used to encrypt it

So someone used openssl to encrypt this file and the passphrase is one from rockyou.txt.  Now, I could write a script to brute force it, or I could borrow someone else’s hard work.

https://github.com/glv2/bruteforce-salted-openssl.  It looks like someone did the heavy lifting for us.  Let’s get that passphrase.

So now we have the passphrase.  Let’s put together all the information we have to decrypt the file.

There’s our CSV.  And a 3rd flag!  Now, I spent a long long time figuring out what to do next.  I knew that the MD5 hashes probably had to do with the web, but googling them yielded nothing.  Finally, I decided to see if those were directories on the website.

This was one of those “so obvious I missed it” times.  Checking out the “obvious hacker” website didn’t turn up much.  What about the other one?

Ok this one appears a bit more dynamic.  Oh hey!  A link for the flag.

🙁

😀

Let’s check out what this feed reader is.

Hmm.  So it looks like a dynamic page that pulls content from places.  Woah.  Check out that URL.

That’s got to be exploitable.  I messed around with this a lot.  It was definitely an LFI.  However, every time I tried a different IP besides 127.0.0.1 it complained about a secret key missing.  My first guess was to corrupt the web server logs and then use the LFI to get PHP to execute, but that didn’t end up working.  I then thought of using the LFI to view the PHP files.  Unfortunately, they kept executing.  I then came across https://www.idontplaydarts.com/2011/02/using-php-filter-for-local-file-inclusion/ which would base64 encode the pages and I could then decode them offline.  First, I took a look at reader.php

<?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.
    }
}

Let’s go through this.  It uses a regex to get the IP in the URL parameter.  If it’s 127.0.0.1, no key is required.  If it is something else, it requires a key.  The SHA256 hash of the key needs to match the hash that is hardcoded in.  If the hash matches, it will include the content.  Oh, and the coder even let us know that they know it’s insecure.  That’s good.

So we have 3 options

  • Bruteforce the key
  • Hack the regex
  • Find the key

I tried #1 before realizing I was an idiot.  The code says the key is 47 characters.  That would take forever.  And then it hit me.

Length of MD5 hash = 40

Length of “flag#{}” = 7

40 + 7 = 47

The key was one of the previous flags!

However, the hashes for flags 1-3 didn’t match.  There must be a 4th one.  I kept looking through the php files until…

<?php defined ('VIAINDEX') or die('Ooooh! So close..'); ?>

<h1>Flag</h1>



Hmm. Looking for a flag? Come on... I haven't made it easy yet, did you think I was going to this time?

<img src="trollface.png" />
<?php // Ok, ok. Here's your flag! // // flag4{4e44db0f1edc3c361dbf54eaf4df40352db91f8b} // // Well done, you're doing great so far! // Next step. SHELL! // // // Oh. That flag above? You're gonna need it... ?>

And there it is, the 4th flag.  There’s even a helpful hint to let us know it’s the key.

Let’s prepare to get a shell.  We need the following items

We get that all set up

and get our reverse shell

And now we begin again with enumeration.  This time, I used the linuxprivchecker.py script which can be found here.  There’s a lot to go through.

 

=================================================================================================
LINUX PRIVILEGE ESCALATION CHECKER
=================================================================================================</code>

[*] GETTING BASIC SYSTEM INFO...

[+] Kernel
Linux version 4.4.0-64-generic (buildd@lgw01-56)
(gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4) )
#85-Ubuntu SMP Mon Feb 20 11:50:30 UTC 2017

[+] Hostname
skuzzy

[+] Operating System
__
_____ _____ | |
| __|_ _ _ | __|___ _ _ ___ ___ _ _| |
| __| | | | |__ | _| | |- _|- _| | |__|
|_____|_____| |_____|___|___|___|___|_ |__|
|___|
Intentionally Vulnerable VM! Do not expose to the Internet!
Developed By - vortex
twitter: @vortexau
email: vortex@juicedigital.net
Hints available at /dev/null (or ping me on Twitter)
Assigned IP: 172.16.2.41/22



[+] SUID/SGID Files and Directories

drwxrwsr-x 2 root staff 4096 Apr 13 2016 /var/local
-rwsr-xr-x 1 root root 8736 Mar 2 22:56 /opt/alicebackup
-rwxr-sr-x 1 root shadow 35600 Mar 17 2016 /sbin/unix_chkpwd
-rwxr-sr-x 1 root shadow 35632 Mar 17 2016 /sbin/pam_extrausers_chkpwd

I truncated a fair bit of that output for brevity

What should stand out to us is the file /opt/alicebackup which is owned by root and has the SUID bit set.  After some analysis with strings and IDA

the code appears to be

setuid(0);
setgid(0);
id;
scp /tmp/special bob@alice.home:~;

This is the part where I got stuck for a weekend.  I focused too much on alice.home.  I set up a DNS spoofer on my attack box and set up a symlink between /tmp/special and /etc/shadow.  Needless to say, that did not end up working out (because of some DNS issues between vbox and vmware.  I think it may have worked but I couldn’t solve the VLAN issue between the two).  After talking with some other folks, I re-focused on the first command.  And then it hit me.  scp did not have the full path set.  That meant I could modify the environment variables (specifically the path) to run my own version of scp.  Let’s get that set up.

My rogue scp script was simple:

And then all I had to do was:

And there it is!  Oh man.  Try harder is a good motto.  K.I.S.S. is a better one.

Keep hacking it!

EDITS:

21 Mar 2017 – fixed hash type

Leave a Reply

Your email address will not be published. Required fields are marked *