Disassembling the existing HTTP server scanner module
Let's work with a simple module for an HTTP version scanner, and see how it works. The path to this Metasploit module is: /modules/auxiliary/scanner/http/http_version.rb.
Let's examine this module systematically:
## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'rex/proto/http' class MetasploitModule < Msf::Auxiliary
Let's discuss how things are arranged here. The copyright lines, starting with the # symbol, are the comments and are included in all Metasploit modules. The require 'rex/proto/http' statement tasks the interpreter to include a path to all the HTTP protocol methods from the rex library. Therefore, the path to all the files from the /lib/rex/proto/http directory is now available to the module, as shown in the following screenshot:
All these files contain a variety of HTTP methods, which include functions to set up a connection, the GET and POST request, response handling, and so on.
In the next line, Msf::Auxiliary defines the code as an auxiliary type module. Let's continue with the code, as follows:
# Exploit mixins should be called first include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::WmapScanServer # Scanner mixin should be near last include Msf::Auxiliary::Scanner
The preceding section includes all the necessary library files that contain methods used in the modules. Let's list the path for these included libraries, as follows:
Let's look at the next piece of code:
def initialize super( 'Name' => 'HTTP Version Detection', 'Description' => 'Display version information about each system', 'Author' => 'hdm',
'License' => MSF_LICENSE ) register_wmap_options({ 'OrderID' => 0, 'Require' => {}, })
end
This part of the module defines the initialize method, which initializes the basic parameters such as Name, Author, Description, and License for this module and initializes the WMAP parameters as well. Now, let's have a look at the last section of the code:
# Fingerprint a single host def run_host(ip) begin connect res = send_request_raw({ 'uri' => '/', 'method' => 'GET' }) fp = http_fingerprint(:response => res) print_good("#{ip}:#{rport} #{fp}") if fp report_service(:host => rhost, :port => rport, :sname => (ssl ? 'https' : 'http'), :info => fp) rescue ::Timeout::Error, ::Errno::EPIPE ensure disconnect end end end
The function here is the meat of the scanner.