Lucene search
K

HTTP Error Based SQL Injection Scanner

🗓️ 01 Feb 2010 02:12:30Reported by et <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 23 Views

Identify HTTP Error Based SQL Injection issue

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::WmapScanUniqueQuery
  include Msf::Auxiliary::Scanner
  include Msf::Auxiliary::Report


  def initialize(info = {})
    super(update_info(info,
      'Name'   		=> 'HTTP Error Based SQL Injection Scanner',
      'Description'	=> %q{
        This module identifies the existence of Error Based SQL injection issues. Still requires a lot of work

      },
      'Author' 		=> [ 'et [at] cyberspace.org' ],
      'License'		=> BSD_LICENSE))

    register_options(
      [
        OptEnum.new('METHOD', [true, 'HTTP Request Method', 'GET', ['GET', 'POST']]),
        OptString.new('PATH', [ true,  "The path/file to test SQL injection", '/default.aspx']),
        OptString.new('QUERY',[ false,  "HTTP URI Query", '']),
        OptString.new('DATA', [ false,  "HTTP Body/Data Query", ''])
      ])

    register_advanced_options(
      [
        OptBool.new('NoDetailMessages', [ false, "Do not display detailed test messages", true ])
      ])

  end

  def run_host(ip)

    http_method = datastore['METHOD'].upcase

    qvars = nil

    sqlinj = [
      [ "'" ,'Single quote'],
      [ "')",'Single quote and parenthesis'],
      [ "\"",'Double quote'],
      [ "%u0027",'unicode single quote'],
      [ "%u02b9",'unicode single quote'],
      [ "%u02bc",'unicode single quote'],
      [ "%u02c8",'unicode single quote'],
      [ "%c0%27",'unicode single quote'],
      [ "%c0%a7",'unicode single quote'],
      [ "%e0%80%a7",'unicode single quote'],
      [ "#{rand(10)}'", 'Random value with single quote']
    ]

    errorstr = [
      ["Unclosed quotation mark after the character string",'MSSQL','string'],
      ["Syntax error in string in query expression",'MSSQL','string'],
      ["Microsoft OLE DB Provider",'MSSQL','unknown'],
      ["You have an error in your SQL syntax",'MySQL','unknown'],
      ["java.sql.SQLException",'unknown','unknown'],
      ["ORA-",'ORACLE','unknown'],
      ["PLS-",'ORACLE','unknown'],
      ["Syntax error",'unknown','unknown'],
    ]

    #
    # Dealing with empty query/data and making them hashes.
    #

    if  http_method =='GET'
      if not datastore['QUERY'].empty?
        qvars = queryparse(datastore['QUERY']) #Now its a Hash
      else
        print_error("You need to set QUERY param for GET")
        return
      end
    else
      if not datastore['DATA'].empty?
        qvars = queryparse(datastore['DATA']) #Now its a Hash
      else
        print_error("You need to set DATA parameter for POST")
        return
      end
    end

    #
    # Send normal request to check if error is generated
    # (means the error is caused by other means)
    #
    #

    if http_method == 'POST'
      reqinfo = {
        'uri'  		=> normalize_uri(datastore['PATH']),
        'query' 	=> datastore['QUERY'],
        'data' 		=> datastore['DATA'],
        'method'   	=> http_method,
        'ctype'		=> 'application/x-www-form-urlencoded',
        'encode'	=> false
      }
    else
      reqinfo = {
        'uri'  		=> normalize_uri(datastore['PATH']),
        'query' 	=> datastore['QUERY'],
        'method'   	=> http_method,
        'ctype'		=> 'application/x-www-form-urlencoded',
        'encode'	=> false
      }
    end

    begin
      normalres = send_request_raw(reqinfo, 20)

    rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
    rescue ::Timeout::Error, ::Errno::EPIPE
    end

    if !datastore['NoDetailMessages']
      print_status("Normal request sent.")
    end

    found = false
    inje = nil
    dbt = nil
    injt = nil

    if normalres
      errorstr.each do |estr,dbtype,injtype|
        if normalres.body.include? estr
          found = true
          inje = estr
          dbt = dbtype
          injt = injtype
        end
      end

      if found
        print_error("[#{wmap_target_host}] Error string appears in the normal response, unable to test")
        print_error("[#{wmap_target_host}] Error string: '#{inje}'")
        print_error("[#{wmap_target_host}] DB TYPE: #{dbt}, Error type '#{injt}'")

        report_web_vuln(
          :host	=> ip,
          :port	=> rport,
          :vhost  => vhost,
          :ssl    => ssl,
          :path	=> datastore['PATH'],
          :method => datastore['METHOD'],
          :pname  => "",
          :proof  => "Error: #{inje}",
          :risk   => 2,
          :confidence   => 50,
          :category     => 'Database error',
          :description  => "Error string appears in the normal response #{inje} #{dbt}",
          :name   => 'Database error'
        )

        return
      end
    else
      print_error("[#{wmap_target_host}] No response")
      return
    end

    #
    # Test URI Query parameters
    #

    found = false

    if qvars
      sqlinj.each do |istr,idesc|

        if found
          break
        end

        qvars.each do |key,value|
          if http_method == 'POST'
            qvars = queryparse(datastore['DATA']) #Now its a Hash
          else
            qvars = queryparse(datastore['QUERY']) #Now its a Hash
          end
          qvars[key] = qvars[key]+istr

          if !datastore['NoDetailMessages']
            print_status("- Testing query with #{idesc}. Parameter #{key}:")
          end

          fstr = ""
          qvars.each_pair do |var,val|
            fstr += var+"="+val+"&"
          end

          if http_method == 'POST'
            reqinfo = {
              'uri'  		=> normalize_uri(datastore['PATH']),
              'query'		=> datastore['QUERY'],
              'data' 		=> fstr,
              'method'   	=> http_method,
              'ctype'		=> 'application/x-www-form-urlencoded',
              'encode'	=> false
            }
          else
            reqinfo = {
              'uri'  		=> normalize_uri(datastore['PATH']),
              'query' 	=> fstr,
              'method'   	=> http_method,
              'ctype'		=> 'application/x-www-form-urlencoded',
              'encode'	=> false
            }
          end

          begin

            testres = send_request_raw(reqinfo, 20)

          rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
          rescue ::Timeout::Error, ::Errno::EPIPE
          end

          if testres
            errorstr.each do |estr,dbtype,injtype|
              if testres.body.include? estr
                found = true
                inje = estr
                dbt = dbtype
                injt = injtype
              end
            end

            if found
              print_good("[#{wmap_target_host}] SQL Injection found. (#{idesc}) (#{datastore['PATH']})")
              print_good("[#{wmap_target_host}] Error string: '#{inje}' Test Value: #{qvars[key]}")
              print_good("[#{wmap_target_host}] Vuln query parameter: #{key} DB TYPE: #{dbt}, Error type '#{injt}'")

              report_web_vuln(
                :host	=> ip,
                :port	=> rport,
                :vhost  => vhost,
                :ssl    => ssl,
                :path	=> datastore['PATH'],
                :method => datastore['METHOD'],
                :pname  => key,
                :proof  => istr,
                :risk   => 2,
                :confidence   => 50,
                :category     => 'SQL injection',
                :description  => "Error string appears in the normal response #{inje} #{dbt}",
                :name   => 'SQL injection'
              )

              return
            end
          else
            print_error("[#{wmap_target_host}] No response")
            return
          end
        end
      end

      if http_method == 'POST'
        qvars = queryparse(datastore['DATA']) #Now its a Hash
      else
        qvars = queryparse(datastore['QUERY']) #Now its a Hash
      end
    end
  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

08 Feb 2021 12:24Current
8.1High risk
Vulners AI Score8.1
23