Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/fuzzers/tds/tds_login_username.rb
19535 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
require 'English'
7
class MetasploitModule < Msf::Auxiliary
8
include Msf::Exploit::Remote::MSSQL
9
include Msf::Auxiliary::Fuzzer
10
11
def initialize(info = {})
12
super(
13
update_info(
14
info,
15
'Name' => 'TDS Protocol Login Request Username Fuzzer',
16
'Description' => %q{
17
This module sends a series of malformed TDS login requests.
18
},
19
'Author' => [ 'hdm' ],
20
'License' => MSF_LICENSE,
21
'Notes' => {
22
'Stability' => [CRASH_SERVICE_DOWN],
23
'SideEffects' => [],
24
'Reliability' => []
25
}
26
)
27
)
28
end
29
30
# A copy of the mssql_login method with the ability to overload each option
31
def do_login(opts = {})
32
@connected = false
33
disconnect if sock
34
connect
35
@connected = true
36
37
pkt = ''
38
db = ''
39
40
pkt << [
41
0x00000000, # Dummy size
42
opts[:tds_version] || 0x71000001, # TDS Version
43
opts[:size] || 0x00000000, # Size
44
opts[:version] || 0x00000007, # Version
45
opts[:pid] || rand(1024 + 1), # PID
46
opts[:connection_id] || 0x00000000, # ConnectionID
47
opts[:flags_opt1] || 0xe0, # Option Flags 1
48
opts[:flags_opt2] || 0x03, # Option Flags 2
49
opts[:flags_sql_type] || 0x00, # SQL Type Flags
50
opts[:flags_reserved] || 0x00, # Reserved Flags
51
opts[:timezone] || 0x00000000, # Time Zone
52
opts[:collation] || 0x00000000 # Collation
53
].pack('VVVVVVCCCCVV')
54
55
cname = Rex::Text.to_unicode(opts[:cname] || Rex::Text.rand_text_alpha(1..8))
56
uname = Rex::Text.to_unicode(opts[:uname] || 'sa')
57
pname = opts[:pname_raw] || mssql_tds_encrypt(opts[:pname] || '')
58
aname = Rex::Text.to_unicode(opts[:aname] || Rex::Text.rand_text_alpha(1..8))
59
sname = Rex::Text.to_unicode(opts[:sname] || rhost)
60
dname = Rex::Text.to_unicode(opts[:dname] || db)
61
62
idx = pkt.size + 50 # lengths below
63
64
pkt << [idx, cname.length / 2].pack('vv')
65
idx += cname.length
66
67
pkt << [idx, uname.length / 2].pack('vv')
68
idx += uname.length
69
70
pkt << [idx, pname.length / 2].pack('vv')
71
idx += pname.length
72
73
pkt << [idx, aname.length / 2].pack('vv')
74
idx += aname.length
75
76
pkt << [idx, sname.length / 2].pack('vv')
77
idx += sname.length
78
79
pkt << [0, 0].pack('vv')
80
81
pkt << [idx, aname.length / 2].pack('vv')
82
idx += aname.length
83
84
pkt << [idx, 0].pack('vv')
85
86
pkt << [idx, dname.length / 2].pack('vv')
87
88
# The total length has to be embedded twice more here
89
pkt << [
90
0,
91
0,
92
0x12345678,
93
0x12345678
94
].pack('vVVV')
95
96
pkt << cname
97
pkt << uname
98
pkt << pname
99
pkt << aname
100
pkt << sname
101
pkt << aname
102
pkt << dname
103
104
# Total packet length
105
pkt[0, 4] = [pkt.length].pack('V')
106
107
# Embedded packet lengths
108
pkt[pkt.index([0x12345678].pack('V')), 8] = [pkt.length].pack('V') * 2
109
110
# Packet header and total length including header
111
pkt = "\x10\x01" + [pkt.length + 8].pack('n') + [0].pack('n') + [1].pack('C') + "\x00" + pkt
112
113
resp = mssql_send_recv(pkt, opts[:timeout])
114
115
info = { errors: [] }
116
info = mssql_parse_reply(resp, info)
117
info
118
end
119
120
def run
121
last_str = nil
122
last_inp = nil
123
last_err = nil
124
125
cnt = 0
126
fuzz_strings do |str|
127
# capped at 16-bit lengths
128
next if str.length > 65535
129
130
cnt += 1
131
132
if (cnt % 100 == 0)
133
print_status("Fuzzing with iteration #{cnt} using #{@last_fuzzer_input}")
134
end
135
136
begin
137
do_login(uname: str, timeout: 0.50)
138
rescue ::Interrupt
139
print_status("Exiting on interrupt: iteration #{cnt} using #{@last_fuzzer_input}")
140
raise $ERROR_INFO
141
rescue StandardError => e
142
last_err = e
143
ensure
144
disconnect
145
end
146
147
if !@connected
148
if last_str
149
print_status("The service may have crashed: method=#{last_inp} string=#{last_str.unpack('H*')[0]} error=#{last_err}")
150
else
151
print_status("Could not connect to the service: #{last_err}")
152
end
153
return
154
end
155
156
last_str = str
157
last_inp = @last_fuzzer_input
158
end
159
end
160
end
161
162