2017-10-13 01:32:01 +00:00
|
|
|
##
|
|
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
|
|
##
|
|
|
|
|
|
|
|
class MetasploitModule < Msf::Auxiliary
|
|
|
|
include Msf::Exploit::Remote::Tcp
|
|
|
|
include Msf::Auxiliary::Report
|
|
|
|
include Msf::Auxiliary::Scanner
|
|
|
|
|
|
|
|
def initialize
|
|
|
|
super(
|
|
|
|
'Name' => 'Gopher gophermap Scanner',
|
2017-10-20 16:44:07 +00:00
|
|
|
'Description' => %q(
|
2017-10-13 01:32:01 +00:00
|
|
|
This module identifies Gopher servers, and processes the gophermap
|
|
|
|
file which lists all the files on the server.
|
2017-10-20 16:44:07 +00:00
|
|
|
),
|
2017-10-13 01:32:01 +00:00
|
|
|
'References' =>
|
|
|
|
[
|
2017-10-20 16:44:07 +00:00
|
|
|
['URL', 'https://sdfeu.org/w/tutorials:gopher']
|
2017-10-13 01:32:01 +00:00
|
|
|
],
|
|
|
|
'Author' => 'h00die',
|
|
|
|
'License' => MSF_LICENSE
|
|
|
|
)
|
|
|
|
|
2017-10-20 16:44:07 +00:00
|
|
|
register_options(
|
|
|
|
[
|
|
|
|
Opt::RPORT(70),
|
|
|
|
OptString.new('PATH', [false, 'Path to enumerate', ''])
|
|
|
|
]
|
|
|
|
)
|
2017-10-13 01:32:01 +00:00
|
|
|
end
|
|
|
|
|
2017-10-20 16:44:07 +00:00
|
|
|
TYPE_MAP = {
|
|
|
|
'0' => 'Text file',
|
|
|
|
'1' => 'Directory',
|
|
|
|
'2' => 'CSO name server',
|
|
|
|
'3' => 'Error',
|
|
|
|
'4' => 'Mac HQX filer',
|
|
|
|
'5' => 'PC binary',
|
|
|
|
'6' => 'UNIX uuencoded file',
|
|
|
|
'7' => 'Search server',
|
|
|
|
'8' => 'Telnet Session',
|
|
|
|
'9' => 'Binary File',
|
|
|
|
'c' => 'Calendar',
|
|
|
|
'e' => 'Event',
|
|
|
|
'g' => 'GIF image',
|
|
|
|
'h' => 'HTML',
|
|
|
|
'i' => 'inline text',
|
|
|
|
's' => 'Sound',
|
|
|
|
'I' => 'Image',
|
|
|
|
'M' => 'MIME multipart/mixed message',
|
|
|
|
'T' => 'TN3270 Session'
|
|
|
|
}.freeze
|
|
|
|
|
2017-10-13 01:32:01 +00:00
|
|
|
def get_type(char)
|
2017-10-20 16:44:07 +00:00
|
|
|
TYPE_MAP.fetch(char.chomp)
|
2017-10-13 01:32:01 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def run_host(ip)
|
|
|
|
begin
|
|
|
|
connect
|
|
|
|
sock.put("#{datastore['path']}\r\n")
|
|
|
|
gophermap = sock.get_once
|
|
|
|
if gophermap
|
|
|
|
gophermap.split("\r\n").each do |line|
|
2017-10-20 16:44:07 +00:00
|
|
|
line_parts = line.split("\t")
|
|
|
|
next unless line_parts.length >= 2
|
|
|
|
# syntax: [type_character]description[tab]path[tab, after this is optional]server[tab]port
|
|
|
|
line_parts = line.split("\t")
|
|
|
|
desc = line_parts[0]
|
|
|
|
type_char = desc.slice!(0) # remove first character which is the file type
|
|
|
|
file_type = get_type(type_char)
|
|
|
|
if file_type && file_type == 'inline text'
|
|
|
|
print_good(desc)
|
|
|
|
next
|
|
|
|
end
|
|
|
|
if file_type
|
|
|
|
print_good(" #{file_type}: #{desc}")
|
|
|
|
else
|
|
|
|
print_good(" Invalid File Type (#{type_char}): #{desc}")
|
|
|
|
end
|
|
|
|
if line_parts.length >= 3
|
|
|
|
print_good(" Path: #{line_parts[2]}:#{line_parts[3]}#{line_parts[1]}")
|
|
|
|
elsif line.length >= 2
|
|
|
|
print_good(" Path: #{line_parts[2]}#{line_parts[1]}")
|
|
|
|
else
|
|
|
|
print_good(" Path: #{line_parts[1]}")
|
2017-10-13 01:32:01 +00:00
|
|
|
|
|
|
|
end
|
|
|
|
end
|
2017-10-20 16:44:07 +00:00
|
|
|
report_service(host: ip, port: rport, service: 'gopher', info: gophermap)
|
2017-10-13 01:32:01 +00:00
|
|
|
else
|
|
|
|
print_error('No gophermap')
|
|
|
|
end
|
|
|
|
rescue ::Rex::ConnectionError, ::IOError, ::Errno::ECONNRESET
|
|
|
|
rescue ::Exception => e
|
|
|
|
print_error("#{ip}: #{e} #{e.backtrace}")
|
|
|
|
ensure
|
|
|
|
disconnect
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|