Skip to content

Commit c001f01

Browse files
committed
HTML Title Grabber
1 parent cc87df9 commit c001f01

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
##
2+
# This module requires Metasploit: http://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
require 'cgi'
8+
9+
class Metasploit3 < Msf::Auxiliary
10+
11+
# Exploit mixins should be called first
12+
include Msf::Exploit::Remote::HttpClient
13+
include Msf::Auxiliary::WmapScanServer
14+
# Scanner mixin should be near last
15+
include Msf::Auxiliary::Scanner
16+
17+
def initialize
18+
super(
19+
'Name' => 'HTTP HTML <title> tag content grabber',
20+
'Description' => 'Generates a GET request to the webservers provided and returns the server header, HTML title attribute and location header (if set). Useful for rapidly identifying all webservers on a network and identifying interesting hosts en mass.',
21+
'Author' => ['Stuart Morgan <stuart.morgan[at]mwrinfosecurity.com>'],
22+
'License' => MSF_LICENSE,
23+
)
24+
25+
register_options(
26+
[
27+
OptBool.new('STORE_NOTES', [ true, 'Store the captured information in notes. Use "notes -t http.title" to view', true ]),
28+
OptBool.new('SHOW_ERRORS', [ true, 'Show error messages relating to grabbing titles on the console', true ]),
29+
OptBool.new('SHOW_TITLES', [ true, 'Show the titles on the console as they are grabbed', true ]),
30+
], self.class)
31+
32+
deregister_options('VHOST')
33+
end
34+
35+
def run_host(target_host)
36+
begin
37+
res = send_request_cgi({
38+
'uri' => '/',
39+
'method' => 'GET',
40+
})
41+
42+
if res.nil?
43+
print_error("No response from #{target_host}:#{rport}") if datastore['SHOW_ERRORS'] == true
44+
else
45+
server_header = nil
46+
location_header = nil
47+
if not res.headers.nil?
48+
res.headers.each do |key,val|
49+
location_header = val if key.downcase == 'location'
50+
server_header = val if key.downcase == 'server'
51+
end
52+
else
53+
print_error("No headers from #{target_host}:#{rport}") if datastore['SHOW_ERRORS'] == true
54+
end
55+
56+
if not res.body.nil?
57+
# Very basic, just match the first title tag we come to.
58+
rx = /<title>[\n\t\s]*(?<title>.+?)[\s\n\t]*<\/title>/im.match(res.body.to_s)
59+
if rx
60+
rx[:title].strip!
61+
if not rx[:title] == ''
62+
rx_title = CGI.unescapeHTML(rx[:title])
63+
print_status("[#{target_host}:#{rport}] [C:#{res.code}] [R:#{location_header}] [S:#{server_header}] #{rx_title}") if datastore['SHOW_TITLES'] == true
64+
if datastore['STORE_NOTES'] == true then
65+
notedata = { code: res.code, port: rport, server: server_header, title: rx_title, redirect: location_header}
66+
report_note(:host => target_host, :type => "http.title", :data => notedata)
67+
end
68+
else
69+
print_error("No webpage title from #{target_host}:#{rport}") if datastore['SHOW_ERRORS'] == true
70+
end
71+
else
72+
print_error("No webpage title from #{target_host}:#{rport}") if datastore['SHOW_ERRORS'] == true
73+
end
74+
else
75+
print_error("No webpage body from #{target_host}:#{rport}") if datastore['SHOW_ERRORS'] == true
76+
end
77+
end
78+
79+
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
80+
rescue ::Timeout::Error, ::Errno::EPIPE
81+
end
82+
end
83+
end

0 commit comments

Comments
 (0)