2015-05-11 16:29:22 +00:00
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf :: Auxiliary
# Exploit mixins should be called first
include Msf :: Exploit :: Remote :: HttpClient
# Scanner mixin should be near last
include Msf :: Auxiliary :: Scanner
def initialize
super (
2015-05-12 09:47:49 +00:00
'Name' = > 'HTTP HTML Title Tag Content Grabber' ,
2015-05-11 18:46:10 +00:00
'Description' = > %q{
2015-05-26 22:00:10 +00:00
Generates a GET request to the provided webservers and returns the server header ,
HTML title attribute and location header ( if set ) . This is useful for rapidly identifying
2015-05-11 18:46:10 +00:00
interesting web applications en mass .
} ,
'Author' = > 'Stuart Morgan <stuart.morgan[at]mwrinfosecurity.com>' ,
2015-05-11 16:29:22 +00:00
'License' = > MSF_LICENSE ,
)
register_options (
[
OptBool . new ( 'STORE_NOTES' , [ true , 'Store the captured information in notes. Use "notes -t http.title" to view' , true ] ) ,
OptBool . new ( 'SHOW_ERRORS' , [ true , 'Show error messages relating to grabbing titles on the console' , true ] ) ,
2015-05-12 16:18:21 +00:00
OptBool . new ( 'SHOW_TITLES' , [ true , 'Show the titles on the console as they are grabbed' , true ] ) ,
OptString . new ( 'TARGETURI' , [ true , 'The base path' , '/' ] )
2015-05-11 17:14:37 +00:00
] , self . class )
2015-05-11 16:29:22 +00:00
deregister_options ( 'VHOST' )
end
2015-05-11 17:48:55 +00:00
def run
2015-05-11 17:50:03 +00:00
if datastore [ 'STORE_NOTES' ] == false && datastore [ 'SHOW_ERRORS' ] == false && datastore [ 'SHOW_TITLES' ] == false
print_error ( " Notes storage is false, errors have been turned off and titles are not being shown on the console. There isn't much point in running this module. " )
2015-05-11 17:48:55 +00:00
else
2015-05-11 17:50:03 +00:00
super
2015-05-11 17:48:55 +00:00
end
end
2015-05-11 16:29:22 +00:00
def run_host ( target_host )
begin
2015-05-11 18:34:23 +00:00
# Send a normal GET request
2015-05-11 18:48:12 +00:00
res = send_request_cgi (
2015-05-12 16:18:21 +00:00
'uri' = > normalize_uri ( target_uri . path )
2015-05-11 18:48:12 +00:00
)
2015-05-11 16:29:22 +00:00
2015-05-11 18:34:23 +00:00
# If no response, quit now
if res . nil?
print_error ( " [ #{ target_host } : #{ rport } ] No response " ) if datastore [ 'SHOW_ERRORS' ] == true
return
end
# Retrieve the headers to capture the Location and Server header
# Note that they are case-insensitive but stored in a hash
2015-05-11 16:29:22 +00:00
server_header = nil
location_header = nil
2015-05-11 17:14:37 +00:00
if ! res . headers . nil?
res . headers . each do | key , val |
location_header = val if key . downcase == 'location'
server_header = val if key . downcase == 'server'
2015-05-11 16:29:22 +00:00
end
else
2015-05-11 18:34:23 +00:00
print_error ( " [ #{ target_host } : #{ rport } ] No HTTP headers " ) if datastore [ 'SHOW_ERRORS' ] == true
end
# If the body is blank, just stop now as there is no chance of a title
if res . body . nil?
print_error ( " [ #{ target_host } : #{ rport } ] No webpage body " ) if datastore [ 'SHOW_ERRORS' ] == true
return
2015-05-11 16:29:22 +00:00
end
2015-05-11 18:34:23 +00:00
# Very basic, just match the first title tag we come to. If the match fails,
# there is no chance that we will have a title
rx = %r{ <title>[ \ n \ t \ s]*(?<title>.+?)[ \ s \ n \ t]*</title> }im . match ( res . body . to_s )
unless rx
print_error ( " [ #{ target_host } : #{ rport } ] No webpage title " ) if datastore [ 'SHOW_ERRORS' ] == true
return
end
# Last bit of logic to capture the title
rx [ :title ] . strip!
if rx [ :title ] != ''
2015-05-11 20:10:18 +00:00
rx_title = Rex :: Text . html_decode ( rx [ :title ] )
2015-05-11 18:34:23 +00:00
print_status ( " [ #{ target_host } : #{ rport } ] [C: #{ res . code } ] [R: #{ location_header } ] [S: #{ server_header } ] #{ rx_title } " ) if datastore [ 'SHOW_TITLES' ] == true
if datastore [ 'STORE_NOTES' ] == true
2015-05-20 21:20:09 +00:00
notedata = { code : res . code , port : rport , server : server_header , title : rx_title , redirect : location_header , uri : datastore [ 'TARGETURI' ] }
report_note ( host : target_host , port : rport , type : " http.title " , data : notedata , update : :unique_data )
2015-05-11 17:14:37 +00:00
end
2015-05-11 16:29:22 +00:00
else
2015-05-11 18:34:23 +00:00
print_error ( " [ #{ target_host } : #{ rport } ] No webpage title " ) if datastore [ 'SHOW_ERRORS' ] == true
2015-05-11 16:29:22 +00:00
end
end
rescue :: Rex :: ConnectionRefused , :: Rex :: HostUnreachable , :: Rex :: ConnectionTimeout
rescue :: Timeout :: Error , :: Errno :: EPIPE
end
end