metasploit-framework/modules/auxiliary/scanner/oracle/sid_brute.rb

129 lines
3.9 KiB
Ruby
Raw Normal View History

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
2016-03-08 13:02:44 +00:00
class MetasploitModule < Msf::Auxiliary
2013-08-30 21:28:54 +00:00
include Msf::Exploit::Remote::TNS
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::AuthBrute # Actually, doesn't use much here, but there's a couple handy functions.
2013-08-30 21:28:54 +00:00
def initialize(info = {})
super(update_info(info,
'Name' => 'Oracle TNS Listener SID Bruteforce',
'Description' => %q{
This module queries the TNS listner for a valid Oracle database
instance name (also known as a SID).
Any response other than a "reject" will be considered a success.
If a specific SID is provided, that SID will be attempted. Otherwise,
SIDs read from the named file will be attempted in sequence instead.
},
'Author' => [ 'todb' ],
'License' => MSF_LICENSE
))
2013-08-30 21:28:54 +00:00
register_options(
[
2013-09-26 19:34:48 +00:00
OptPath.new('SID_FILE', [ false, "File containing instance names, one per line", File.join(Msf::Config.data_directory, "wordlists", "sid.txt") ]),
2013-08-30 21:28:54 +00:00
OptString.new('SID', [ false, 'A specific SID to attempt.' ]),
Opt::RPORT(1521)
], self.class)
2013-08-30 21:28:54 +00:00
deregister_options(
"RHOST", "USERNAME", "PASSWORD", "USER_FILE", "PASS_FILE", "USERPASS_FILE",
"BLANK_PASSWORDS", "USER_AS_PASS", "REMOVE_USER_FILE", "REMOVE_PASS_FILE",
"REMOVE_USERPASS_FILE"
)
end
2013-08-30 21:28:54 +00:00
def build_sid_request(sid,ip)
connect_data = "(DESCRIPTION=(CONNECT_DATA=(SID=#{sid})(CID=(PROGRAM=)(HOST=__jdbc__)(USER=)))(ADDRESS=(PROTOCOL=tcp)(HOST=#{ip})(PORT=#{rport})))"
pkt = tns_packet(connect_data)
end
2013-08-30 21:28:54 +00:00
def hostport
[target_host,rport].join(":")
end
2013-08-30 21:28:54 +00:00
def check_sid(sid,ip)
pkt = build_sid_request(sid,ip)
sock.put(pkt)
data = sock.get_once || ''
parse_response(data)
end
2013-08-30 21:28:54 +00:00
def parse_response(data)
return unless data
len,sum,type,r,hsum,rest = data.unpack("nnCCnA*")
type # 2 is "accept", 11 is resend. Usually you get 11, then 2. 4 is refuse.
end
2013-08-30 21:28:54 +00:00
def do_sid_check(sid,ip)
begin
connect
response_code = check_sid(sid,ip)
if response_code.nil?
print_status "#{hostport} Oracle - No response given, something is wrong."
return :abort
elsif response_code != 4
print_good "#{hostport} Oracle - '#{sid}' is valid"
report_note(
:host => ip,
:proto => 'tcp',
:port => rport,
:sname => 'oracle',
:type => "oracle.sid",
:data => sid,
:update => :unique_data
)
return :success
else
vprint_status "#{hostport} Oracle - Refused '#{sid}'"
return :fail
end
rescue ::Rex::ConnectionError, ::Errno::EPIPE
print_error("#{hostport} Oracle - unable to connect to a TNS listener")
return :abort
2015-08-24 17:36:15 +00:00
ensure
disconnect
2013-08-30 21:28:54 +00:00
end
end
# Based vaguely on each_user_pass in AuthBrute
2013-08-30 21:28:54 +00:00
def each_sid(&block)
@@oracle_sid_fail = []
@@oracle_sid_success = []
if datastore['SID'].nil? || datastore['SID'].empty?
sids = extract_words(datastore['SID_FILE']).map {|s| s.to_s.strip.upcase}.uniq
else
sids = [datastore['SID'].to_s.strip.upcase]
end
print_status "Checking #{sids.size} SID#{sids.size != 1 && "s"} against #{hostport}"
sids.each do |s|
userpass_sleep_interval unless (@@oracle_sid_fail | @@oracle_sid_success).empty?
next if @@oracle_sid_fail.include?(s) || @@oracle_sid_success.include?(s)
ret = block.call(s)
case ret
when :abort
break
when :success
@@oracle_sid_success << s
break if datastore["STOP_ON_SUCCESS"]
when :fail
@@oracle_sid_fail << s
end
end
end
2013-08-30 21:28:54 +00:00
def run_host(ip)
each_sid do |sid|
vprint_status "#{hostport} Oracle - Checking '#{sid}'..."
do_sid_check(sid,ip)
end
end
end