modules/auxiliary/fuzzers: Resolve RuboCop violations

This commit is contained in:
bcoles
2025-05-10 14:09:40 +10:00
parent b5129fe198
commit 75c2104625
21 changed files with 1569 additions and 1410 deletions
+183 -180
View File
@@ -20,28 +20,33 @@ class MetasploitModule < Msf::Auxiliary
crash the target server.
},
'Author' => [ 'pello <fropert[at]packetfault.org>' ],
'License' => MSF_LICENSE
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SERVICE_DOWN],
'SideEffects' => [],
'Reliability' => []
}
)
register_options([
Opt::RPORT(53),
OptInt.new('STARTSIZE', [ false, "Fuzzing string startsize.",0]),
OptInt.new('ENDSIZE', [ false, "Max Fuzzing string size. (L2 Frame size)",500]),
OptInt.new('STEPSIZE', [ false, "Increment fuzzing string each attempt.",100]),
OptInt.new('ERRORHDR', [ false, "Introduces byte error in the DNS header.", 0]),
OptInt.new('STARTSIZE', [ false, 'Fuzzing string startsize.', 0]),
OptInt.new('ENDSIZE', [ false, 'Max Fuzzing string size. (L2 Frame size)', 500]),
OptInt.new('STEPSIZE', [ false, 'Increment fuzzing string each attempt.', 100]),
OptInt.new('ERRORHDR', [ false, 'Introduces byte error in the DNS header.', 0]),
OptBool.new('CYCLIC', [ false, "Use Cyclic pattern instead of A's (fuzzing payload).", true]),
OptInt.new("ITERATIONS", [true, "Number of iterations to run by test case", 5]),
OptString.new('DOMAIN', [ false, "Force DNS zone domain name."]),
OptString.new('IMPORTENUM', [ false, "Import dns_enum database output and automatically use existing RR."]),
OptInt.new('ITERATIONS', [true, 'Number of iterations to run by test case', 5]),
OptString.new('DOMAIN', [ false, 'Force DNS zone domain name.']),
OptString.new('IMPORTENUM', [ false, 'Import dns_enum database output and automatically use existing RR.']),
OptEnum.new('METHOD', [false, 'Underlayer protocol to use', 'UDP', ['UDP', 'TCP', 'AUTO']]),
OptBool.new('DNSSEC', [ false, "Add DNSsec to each question (UDP payload size, EDNS0, ...)",false]),
OptBool.new('TRAILINGNUL', [ false, "NUL byte terminate DNS names",true]),
OptBool.new('RAWPADDING', [ false, "Generate totally random data from STARTSIZE to ENDSIZE",false]),
OptString.new('OPCODE', [ false, "Comma separated list of opcodes to fuzz. Leave empty to fuzz all fields.",'' ]),
OptBool.new('DNSSEC', [ false, 'Add DNSsec to each question (UDP payload size, EDNS0, ...)', false]),
OptBool.new('TRAILINGNUL', [ false, 'NUL byte terminate DNS names', true]),
OptBool.new('RAWPADDING', [ false, 'Generate totally random data from STARTSIZE to ENDSIZE', false]),
OptString.new('OPCODE', [ false, 'Comma separated list of opcodes to fuzz. Leave empty to fuzz all fields.', '' ]),
# OPCODE accepted values: QUERY,IQUERY,STATUS,UNASSIGNED,NOTIFY,UPDATE
OptString.new('CLASS', [ false, "Comma separated list of classes to fuzz. Leave empty to fuzz all fields.",'' ]),
OptString.new('CLASS', [ false, 'Comma separated list of classes to fuzz. Leave empty to fuzz all fields.', '' ]),
# CLASS accepted values: IN,CH,HS,NONE,ANY
OptString.new('RR', [ false, "Comma separated list of requests to fuzz. Leave empty to fuzz all fields.",'' ])
OptString.new('RR', [ false, 'Comma separated list of requests to fuzz. Leave empty to fuzz all fields.', '' ])
# RR accepted values: A,CNAME,MX,PTR,TXT,AAAA,HINFO,SOA,NS,WKS,RRSIG,DNSKEY,DS,NSEC,NSEC3,NSEC3PARAM
# RR accepted values: AFSDB,ISDN,RP,RT,X25,PX,SRV,NAPTR,MD,MF,MB,MG,MR,NULL,MINFO,NSAP,NSAP-PTR,SIG
# RR accepted values: KEY,GPOS,LOC,NXT,EID,NIMLOC,ATMA,KX,CERT,A6,DNAME,SINK,OPT,APL,SSHFP,IPSECKEY
@@ -50,7 +55,7 @@ class MetasploitModule < Msf::Auxiliary
])
end
class Dns_header < BinData::Record
class DnsHeader < BinData::Record
endian :big
uint16 :txid, initial_value: rand(0xffff)
bit1 :qr
@@ -68,7 +73,7 @@ class MetasploitModule < Msf::Auxiliary
rest :payload
end
class Dns_add_rr < BinData::Record
class DnsAddRr < BinData::Record
endian :big
uint8 :name
uint16 :rr_type, initial_value: 0x0029
@@ -89,72 +94,70 @@ class MetasploitModule < Msf::Auxiliary
if pkt[4].to_i >= 0x17 || (pkt[4].to_i >= 0x0b && pkt[4].to_i <= 0x0f)
print_error("#{msg} Server replied incorrectly to the following request:\n#{@lastdata.unpack('H*')}")
return false
else
return true
end
return true
end
def dns_alive(method)
connect_udp if method == "UDP" || method == "AUTO"
connect if method == "TCP"
payload = ""
domain = ""
if @domain == nil
domain << Rex::Text.rand_text_alphanumeric(rand(2)+2)
domain << "."
domain << Rex::Text.rand_text_alphanumeric(rand(6)+3)
domain << "."
connect_udp if method == 'UDP' || method == 'AUTO'
connect if method == 'TCP'
domain = ''
domain << Rex::Text.rand_text_alphanumeric(2..3)
domain << '.'
if @domain.nil?
domain << Rex::Text.rand_text_alphanumeric(3..8)
domain << '.'
domain << Rex::Text.rand_text_alphanumeric(2)
else
domain << Rex::Text.rand_text_alphanumeric(rand(2)+2)
domain << "."
domain << @domain
end
splitFQDN = domain.split('.')
payload = splitFQDN.inject("") { |a,x| a + [x.length,x].pack("CA*") }
pkt = Dns_header.new
split_fqdn = domain.split('.')
payload = split_fqdn.inject('') { |a, x| a + [x.length, x].pack('CA*') }
pkt = DnsHeader.new
pkt.txid = rand(0xffff)
pkt.opcode = 0x0000
pkt.payload = payload + "\x00" + "\x00\x01" + "\x00\x01"
testingPkt = pkt.to_binary_s
testing_pkt = pkt.to_binary_s
if method == "UDP"
udp_sock.put(testingPkt)
res, addr = udp_sock.recvfrom(65535)
if method == 'UDP'
udp_sock.put(testing_pkt)
res, = udp_sock.recvfrom(65535)
disconnect_udp
elsif method == "TCP"
sock.put(testingPkt)
res, addr = sock.get_once(-1, 20)
elsif method == 'TCP'
sock.put(testing_pkt)
res, = sock.get_once(-1, 20)
disconnect
end
if res && res.empty?
print_error("#{msg} The remote server is not responding to DNS requests.")
return false
else
return true
end
return true
end
def fuzz_padding(payload, size)
padding = size - payload.length
if padding <= 0 then return payload end
return payload if padding <= 0
if datastore['CYCLIC']
@fuzzdata = Rex::Text.rand_text_alphanumeric(padding)
else
@fuzzdata = 'A' * padding
end
payload = payload.ljust(padding, @fuzzdata)
return payload
return payload.ljust(padding, @fuzzdata)
end
def corrupt_header(pkt, nb)
len = pkt.length - 1
for i in 0..nb - 1
selectByte = rand(len)
pkt[selectByte] = [rand(255).to_s].pack('H')
for _ in 0..nb - 1
select_byte = rand(len)
pkt[select_byte] = [rand(255).to_s].pack('H')
end
return pkt
end
@@ -168,129 +171,129 @@ class MetasploitModule < Msf::Auxiliary
end
def setup_fqdn(domain, entry)
if domain == nil
domain = ""
domain << Rex::Text.rand_text_alphanumeric(rand(62)+2)
domain << "."
domain << Rex::Text.rand_text_alphanumeric(rand(61)+3)
domain << "."
domain << Rex::Text.rand_text_alphanumeric(rand(62)+2)
if domain.nil?
domain = ''
domain << Rex::Text.rand_text_alphanumeric(2..63)
domain << '.'
domain << Rex::Text.rand_text_alphanumeric(3..63)
domain << '.'
domain << Rex::Text.rand_text_alphanumeric(2..63)
elsif @dnsfile
domain = entry + "." + domain
domain = entry + '.' + domain
else
domain = Rex::Text.rand_text_alphanumeric(rand(62)+2) + "." + domain
domain = Rex::Text.rand_text_alphanumeric(2..63) + '.' + domain
end
return domain
end
def import_enum_data(dnsfile)
enumdata = Array.new(count = File.foreach(dnsfile).inject(0) {|c, line| c+1}, 0)
enumdata = Array.new(File.foreach(dnsfile).inject(0) { |c, _line| c + 1 }, 0)
idx = 0
File.open(dnsfile,"rb").each_line do |line|
line = line.split(",")
File.open(dnsfile, 'rb').each_line do |line|
line = line.split(',')
enumdata[idx] = Hash.new
enumdata[idx][:name] = line[0].strip
enumdata[idx][:rr] = line[1].strip
enumdata[idx][:class] = line[2].strip
idx = idx + 1
idx += 1
end
return enumdata
end
def setup_nsclass(nsclass)
classns = ""
classns = ''
for idx in nsclass
classns << {
"IN" => 0x0001, "CH" => 0x0003, "HS" => 0x0004,
"NONE" => 0x00fd, "ANY" => 0x00ff
}.values_at(idx).pack("n")
'IN' => 0x0001, 'CH' => 0x0003, 'HS' => 0x0004,
'NONE' => 0x00fd, 'ANY' => 0x00ff
}.values_at(idx).pack('n')
end
return classns
end
def setup_opcode(nsopcode)
opcode = ""
opcode = ''
for idx in nsopcode
opcode << {
"QUERY" => 0x0000, "IQUERY" => 0x0001, "STATUS" => 0x0002,
"UNASSIGNED" => 0x0003, "NOTIFY" => 0x0004, "UPDATE" => 0x0005
}.values_at(idx).pack("n")
'QUERY' => 0x0000, 'IQUERY' => 0x0001, 'STATUS' => 0x0002,
'UNASSIGNED' => 0x0003, 'NOTIFY' => 0x0004, 'UPDATE' => 0x0005
}.values_at(idx).pack('n')
end
return opcode
end
def setup_reqns(nsreq)
reqns= ""
reqns = ''
for idx in nsreq
reqns << {
"A" => 0x0001, "NS" => 0x0002, "MD" => 0x0003, "MF" => 0x0004,
"CNAME" => 0x0005, "SOA" => 0x0006, "MB" => 0x0007, "MG" => 0x0008,
"MR" => 0x0009, "NULL" => 0x000a, "WKS" => 0x000b, "PTR" => 0x000c,
"HINFO" => 0x000d, "MINFO" => 0x000e, "MX" => 0x000f, "TXT" => 0x0010,
"RP" => 0x0011, "AFSDB" => 0x0012, "X25" => 0x0013, "ISDN" => 0x0014,
"RT" => 0x0015, "NSAP" => 0x0016, "NSAP-PTR" => 0x0017, "SIG" => 0x0018,
"KEY" => 0x0019, "PX" => 0x001a, "GPOS" => 0x001b, "AAAA" => 0x001c,
"LOC" => 0x001d, "NXT" => 0x001e, "EID" => 0x001f, "NIMLOC" => 0x0020,
"SRV" => 0x0021, "ATMA" => 0x0022, "NAPTR" => 0x0023, "KX" => 0x0024,
"CERT" => 0x0025, "A6" => 0x0026, "DNAME" => 0x0027, "SINK" => 0x0028,
"OPT" => 0x0029, "APL" => 0x002a, "DS" => 0x002b, "SSHFP" => 0x002c,
"IPSECKEY" => 0x002d, "RRSIG" => 0x002e, "NSEC" => 0x002f, "DNSKEY" => 0x0030,
"DHCID" => 0x0031, "NSEC3" => 0x0032, "NSEC3PARAM" => 0x0033, "HIP" => 0x0037,
"NINFO" => 0x0038, "RKEY" => 0x0039, "TALINK" => 0x003a, "SPF" => 0x0063,
"UINFO" => 0x0064, "UID" => 0x0065, "GID" => 0x0066, "UNSPEC" => 0x0067,
"TKEY" => 0x00f9, "TSIG" => 0x00fa, "IXFR" => 0x00fb, "AXFR" => 0x00fc,
"MAILA" => 0x00fd, "MAILB" => 0x00fe, "*" => 0x00ff, "TA" => 0x8000,
"DLV" => 0x8001, "RESERVED" => 0xffff
}.values_at(idx).pack("n")
'A' => 0x0001, 'NS' => 0x0002, 'MD' => 0x0003, 'MF' => 0x0004,
'CNAME' => 0x0005, 'SOA' => 0x0006, 'MB' => 0x0007, 'MG' => 0x0008,
'MR' => 0x0009, 'NULL' => 0x000a, 'WKS' => 0x000b, 'PTR' => 0x000c,
'HINFO' => 0x000d, 'MINFO' => 0x000e, 'MX' => 0x000f, 'TXT' => 0x0010,
'RP' => 0x0011, 'AFSDB' => 0x0012, 'X25' => 0x0013, 'ISDN' => 0x0014,
'RT' => 0x0015, 'NSAP' => 0x0016, 'NSAP-PTR' => 0x0017, 'SIG' => 0x0018,
'KEY' => 0x0019, 'PX' => 0x001a, 'GPOS' => 0x001b, 'AAAA' => 0x001c,
'LOC' => 0x001d, 'NXT' => 0x001e, 'EID' => 0x001f, 'NIMLOC' => 0x0020,
'SRV' => 0x0021, 'ATMA' => 0x0022, 'NAPTR' => 0x0023, 'KX' => 0x0024,
'CERT' => 0x0025, 'A6' => 0x0026, 'DNAME' => 0x0027, 'SINK' => 0x0028,
'OPT' => 0x0029, 'APL' => 0x002a, 'DS' => 0x002b, 'SSHFP' => 0x002c,
'IPSECKEY' => 0x002d, 'RRSIG' => 0x002e, 'NSEC' => 0x002f, 'DNSKEY' => 0x0030,
'DHCID' => 0x0031, 'NSEC3' => 0x0032, 'NSEC3PARAM' => 0x0033, 'HIP' => 0x0037,
'NINFO' => 0x0038, 'RKEY' => 0x0039, 'TALINK' => 0x003a, 'SPF' => 0x0063,
'UINFO' => 0x0064, 'UID' => 0x0065, 'GID' => 0x0066, 'UNSPEC' => 0x0067,
'TKEY' => 0x00f9, 'TSIG' => 0x00fa, 'IXFR' => 0x00fb, 'AXFR' => 0x00fc,
'MAILA' => 0x00fd, 'MAILB' => 0x00fe, '*' => 0x00ff, 'TA' => 0x8000,
'DLV' => 0x8001, 'RESERVED' => 0xffff
}.values_at(idx).pack('n')
end
return reqns
end
def build_packet(dnsOpcode,dnssec,trailingnul,reqns,classns,payload)
pkt = Dns_header.new
pkt.opcode = dnsOpcode
def build_packet(dns_opcode, dnssec, trailingnul, reqns, classns, payload)
pkt = DnsHeader.new
pkt.opcode = dns_opcode
if trailingnul
if @dnsfile
pkt.payload = payload + "\x00" + reqns + classns
else
pkt.payload = payload + "\x00" + [reqns].pack("n") + [classns].pack("n")
pkt.payload = payload + "\x00" + [reqns].pack('n') + [classns].pack('n')
end
elsif @dnsfile
pkt.payload = payload + [rand(1..255).to_s].pack('H') + reqns + classns
else
if @dnsfile
pkt.payload = payload + [(rand(255) + 1).to_s].pack('H') + reqns + classns
else
pkt.payload = payload + [(rand(255) + 1).to_s].pack('H') + [dnsReq].pack("n") + [dnsClass].pack("n")
end
pkt.payload = payload + [rand(1..255).to_s].pack('H') + [dns_req].pack('n') + [dns_class].pack('n')
end
if dnssec
dnssecpkt = Dns_add_rr.new
dnssecpkt = DnsAddRr.new
pkt.additionalRR = 1
pkt.payload = dnssecpkt.to_binary_s
end
return pkt.to_binary_s
pkt.to_binary_s
end
def dns_send(data, method)
method = "UDP" if (method == "AUTO" && data.length < 512)
method = "TCP" if (method == "AUTO" && data.length >= 512)
method = 'UDP' if method == 'AUTO' && data.length < 512
method = 'TCP' if method == 'AUTO' && data.length >= 512
connect_udp if method == "UDP"
connect if method == "TCP"
udp_sock.put(data) if method == "UDP"
sock.put(data) if method == "TCP"
connect_udp if method == 'UDP'
connect if method == 'TCP'
udp_sock.put(data) if method == 'UDP'
sock.put(data) if method == 'TCP'
res, addr = udp_sock.recvfrom(65535,1) if method == "UDP"
res, addr = sock.get_once(-1,1) if method == "TCP"
res, = udp_sock.recvfrom(65535, 1) if method == 'UDP'
res, = sock.get_once(-1, 1) if method == 'TCP'
disconnect_udp if method == "UDP"
disconnect if method == "TCP"
disconnect_udp if method == 'UDP'
disconnect if method == 'TCP'
if res && res.length == 0
@failCount += 1
if @failCount == 1
@probablyVuln = @lastdata if @lastdata != nil
return true
elsif @failCount >= 3
if res && res.empty?
@fail_count += 1
if @fail_count == 1
@probably_vuln = @lastdata if !@lastdata.nil?
elsif @fail_count >= 3
if dns_alive(method) == false
if @lastdata
print_error("#{msg} DNS is DOWN since the request:")
@@ -299,55 +302,53 @@ class MetasploitModule < Msf::Auxiliary
print_error("#{msg} DNS is DOWN")
end
return false
else
return true
end
else
return true
end
elsif res && res.length > 0
return true
elsif res && !res.empty?
@lastdata = data
if res[3].to_i >= 0x8000 # ignore server response as a query
@failCount = 0
@fail_count = 0
return true
end
if @rawpadding
@failCount = 0
@fail_count = 0
return true
end
if check_response_construction(res)
@failCount = 0
@fail_count = 0
return true
else
return false
end
return false
end
end
def fix_variables
@fuzz_opcode = datastore['OPCODE'].blank? ? "QUERY,IQUERY,STATUS,UNASSIGNED,NOTIFY,UPDATE" : datastore['OPCODE']
@fuzz_class = datastore['CLASS'].blank? ? "IN,CH,HS,NONE,ANY" : datastore['CLASS']
fuzz_rr_queries = "A,NS,MD,MF,CNAME,SOA,MB,MG,MR,NULL,WKS,PTR," <<
"HINFO,MINFO,MX,TXT,RP,AFSDB,X25,ISDN,RT," <<
"NSAP,NSAP-PTR,SIG,KEY,PX,GPOS,AAAA,LOC,NXT," <<
"EID,NIMLOC,SRV,ATMA,NAPTR,KX,CERT,A6,DNAME," <<
"SINK,OPT,APL,DS,SSHFP,IPSECKEY,RRSIG,NSEC," <<
"DNSKEY,DHCID,NSEC3,NSEC3PARAM,HIP,NINFO,RKEY," <<
"TALINK,SPF,UINFO,UID,GID,UNSPEC,TKEY,TSIG," <<
"IXFR,AXFR,MAILA,MAILB,*,TA,DLV,RESERVED"
@fuzz_opcode = datastore['OPCODE'].blank? ? 'QUERY,IQUERY,STATUS,UNASSIGNED,NOTIFY,UPDATE' : datastore['OPCODE']
@fuzz_class = datastore['CLASS'].blank? ? 'IN,CH,HS,NONE,ANY' : datastore['CLASS']
fuzz_rr_queries = 'A,NS,MD,MF,CNAME,SOA,MB,MG,MR,NULL,WKS,PTR,' \
'HINFO,MINFO,MX,TXT,RP,AFSDB,X25,ISDN,RT,' \
'NSAP,NSAP-PTR,SIG,KEY,PX,GPOS,AAAA,LOC,NXT,' \
'EID,NIMLOC,SRV,ATMA,NAPTR,KX,CERT,A6,DNAME,' \
'SINK,OPT,APL,DS,SSHFP,IPSECKEY,RRSIG,NSEC,' \
'DNSKEY,DHCID,NSEC3,NSEC3PARAM,HIP,NINFO,RKEY,' \
'TALINK,SPF,UINFO,UID,GID,UNSPEC,TKEY,TSIG,' \
'IXFR,AXFR,MAILA,MAILB,*,TA,DLV,RESERVED'
@fuzz_rr = datastore['RR'].blank? ? fuzz_rr_queries : datastore['RR']
end
def run_host(ip)
msg = "#{ip}:#{rhost} - DNS -"
begin
@lastdata = nil
@probablyVuln = nil
@probably_vuln = nil
@startsize = datastore['STARTSIZE']
@stepsize = datastore['STEPSIZE']
@endsize = datastore['ENDSIZE']
@underlayerProtocol = datastore['METHOD']
@failCount = 0
@underlayer_protocol = datastore['METHOD']
@fail_count = 0
@domain = datastore['DOMAIN']
@dnsfile = datastore['IMPORTENUM']
@rawpadding = datastore['RAWPADDING']
@@ -358,7 +359,7 @@ class MetasploitModule < Msf::Auxiliary
fix_variables
if !dns_alive(@underlayerProtocol) then return false end
return false if !dns_alive(@underlayer_protocol)
print_status("#{msg} Fuzzing DNS server, this may take a while.")
@@ -368,18 +369,19 @@ class MetasploitModule < Msf::Auxiliary
end
if @rawpadding
if @domain == nil
print_status("DNS Fuzzer: DOMAIN could be set for health check but not mandatory.")
if @domain.nil?
print_status('DNS Fuzzer: DOMAIN could be set for health check but not mandatory.')
end
nsopcode=@fuzz_opcode.split(",")
nsopcode = @fuzz_opcode.split(',')
opcode = setup_opcode(nsopcode)
opcode.unpack("n*").each do |dnsOpcode|
opcode.unpack('n*').each do |dns_opcode|
1.upto(iter) do
while @startsize <= @endsize
data = random_payload(@startsize).to_s
data[2] = 0x0
data[3] = dnsOpcode
if !dns_send(data,@underlayerProtocol) then return false end
data[3] = dns_opcode
return false if !dns_send(data, @underlayer_protocol)
@lastdata = data
@startsize += @stepsize
end
@@ -390,8 +392,8 @@ class MetasploitModule < Msf::Auxiliary
end
if @dnsfile
if @domain == nil
print_error("DNS Fuzzer: Domain variable must be set.")
if @domain.nil?
print_error('DNS Fuzzer: Domain variable must be set.')
return
end
@@ -399,24 +401,26 @@ class MetasploitModule < Msf::Auxiliary
nsreq = []
nsclass = []
nsentry = []
for req, value in dnsenumdata
for req, _ in dnsenumdata
nsreq << req[:rr]
nsclass << req[:class]
nsentry << req[:name]
end
nsopcode=@fuzz_opcode.split(",")
nsopcode = @fuzz_opcode.split(',')
else
nsreq=@fuzz_rr.split(",")
nsopcode=@fuzz_opcode.split(",")
nsclass=@fuzz_class.split(",")
nsreq = @fuzz_rr.split(',')
nsopcode = @fuzz_opcode.split(',')
nsclass = @fuzz_class.split(',')
begin
classns = setup_nsclass(nsclass)
raise ArgumentError, "Invalid CLASS: #{nsclass.inspect}" unless classns
opcode = setup_opcode(nsopcode)
raise ArgumentError, "Invalid OPCODE: #{opcode.inspect}" unless nsopcode
reqns = setup_reqns(nsreq)
raise ArgumentError, "Invalid RR: #{nsreq.inspect}" unless nsreq
rescue ::Exception => e
rescue StandardError => e
print_error("DNS Fuzzer error, aborting: #{e}")
return
end
@@ -424,7 +428,7 @@ class MetasploitModule < Msf::Auxiliary
for question in nsreq
case question
when "RRSIG", "DNSKEY", "DS", "NSEC", "NSEC3", "NSEC3PARAM"
when 'RRSIG', 'DNSKEY', 'DS', 'NSEC', 'NSEC3', 'NSEC3PARAM'
dnssec = true
end
end
@@ -433,47 +437,48 @@ class MetasploitModule < Msf::Auxiliary
classns = setup_nsclass(nsclass)
reqns = setup_reqns(nsreq)
opcode = setup_opcode(nsopcode)
opcode.unpack("n*").each do |dnsOpcode|
opcode.unpack('n*').each do |dns_opcode|
for i in 0..nsentry.length - 1
reqns = setup_reqns(nsreq[i])
classns = setup_nsclass(nsclass[i])
1.upto(iter) do
payload = ""
nsdomain = setup_fqdn(@domain, nsentry[i])
splitFQDN = nsdomain.split('.')
payload = splitFQDN.inject("") { |a,x| a + [x.length,x].pack("CA*") }
pkt = build_packet(dnsOpcode,dnssec,trailingnul,reqns,classns,payload)
split_fqdn = nsdomain.split('.')
payload = split_fqdn.inject('') { |a, x| a + [x.length, x].pack('CA*') }
pkt = build_packet(dns_opcode, dnssec, trailingnul, reqns, classns, payload)
pkt = corrupt_header(pkt, errorhdr) if errorhdr > 0
if @startsize == 0
if !dns_send(pkt,@underlayerProtocol) then return end
else
if @startsize == 0 && !dns_send(pkt, @underlayer_protocol)
break
end
while @startsize <= @endsize
pkt = fuzz_padding(pkt, @startsize)
if !dns_send(pkt,@underlayerProtocol) then return end
break if !dns_send(pkt, @underlayer_protocol)
@startsize += @stepsize
end
@startsize = datastore['STARTSIZE']
end
end
end
end
else
classns.unpack("n*").each do |dnsClass|
opcode.unpack("n*").each do |dnsOpcode|
reqns.unpack("n*").each do |dnsReq|
classns.unpack('n*').each do |dns_class|
opcode.unpack('n*').each do |dns_opcode|
reqns.unpack('n*').each do |dns_req|
1.upto(iter) do
payload = ""
nsdomain = setup_fqdn(@domain,"")
splitFQDN = nsdomain.split('.')
payload = splitFQDN.inject("") { |a,x| a + [x.length,x].pack("CA*") }
pkt = build_packet(dnsOpcode,dnssec,trailingnul,dnsReq,dnsClass,payload)
nsdomain = setup_fqdn(@domain, '')
split_fqdn = nsdomain.split('.')
payload = split_fqdn.inject('') { |a, x| a + [x.length, x].pack('CA*') }
pkt = build_packet(dns_opcode, dnssec, trailingnul, dns_req, dns_class, payload)
pkt = corrupt_header(pkt, errorhdr) if errorhdr > 0
if @startsize == 0
if !dns_send(pkt,@underlayerProtocol) then return end # If then return end?
else
if @startsize == 0 && !dns_send(pkt, @underlayer_protocol)
break
end
while @startsize <= @endsize
pkt = fuzz_padding(pkt, @startsize)
if !dns_send(pkt,@underlayerProtocol) then return end
break if !dns_send(pkt, @underlayer_protocol)
@startsize += @stepsize
end
@startsize = datastore['STARTSIZE']
@@ -484,5 +489,3 @@ class MetasploitModule < Msf::Auxiliary
end
end
end
end
end
+150 -141
View File
@@ -9,11 +9,10 @@
#
##
class MetasploitModule < Msf::Auxiliary
include Exploit::Remote::TcpServer
def initialize()
def initialize
super(
'Name' => 'Simple FTP Client Fuzzer',
'Description' => %q{
@@ -21,27 +20,31 @@ class MetasploitModule < Msf::Auxiliary
},
'Author' => [ 'corelanc0d3r <peter.ve[at]corelan.be>' ],
'License' => MSF_LICENSE,
'References' =>
[
'References' => [
[ 'URL', 'http://www.corelan.be:8800/index.php/2010/10/12/death-of-an-ftp-client/' ],
]
],
'Notes' => {
'Stability' => [CRASH_SERVICE_DOWN],
'SideEffects' => [],
'Reliability' => []
}
)
register_options(
[
OptPort.new('SRVPORT', [ true, "The local port to listen on.", 21 ]),
OptString.new('FUZZCMDS', [ true, "Comma separated list of commands to fuzz (Uppercase).", "LIST,NLST,LS,RETR", nil, /(?:[A-Z]+,?)+/ ]),
OptInt.new('STARTSIZE', [ true, "Fuzzing string startsize.",1000]),
OptInt.new('ENDSIZE', [ true, "Max Fuzzing string size.",200000]),
OptInt.new('STEPSIZE', [ true, "Increment fuzzing string each attempt.",1000]),
OptBool.new('RESET', [ true, "Reset fuzzing values after client disconnects with QUIT cmd.",true]),
OptString.new('WELCOME', [ true, "FTP Server welcome message.","Evil FTP Server Ready"]),
OptPort.new('SRVPORT', [ true, 'The local port to listen on.', 21 ]),
OptString.new('FUZZCMDS', [ true, 'Comma separated list of commands to fuzz (Uppercase).', 'LIST,NLST,LS,RETR', nil, /(?:[A-Z]+,?)+/ ]),
OptInt.new('STARTSIZE', [ true, 'Fuzzing string startsize.', 1000]),
OptInt.new('ENDSIZE', [ true, 'Max Fuzzing string size.', 200000]),
OptInt.new('STEPSIZE', [ true, 'Increment fuzzing string each attempt.', 1000]),
OptBool.new('RESET', [ true, 'Reset fuzzing values after client disconnects with QUIT cmd.', true]),
OptString.new('WELCOME', [ true, 'FTP Server welcome message.', 'Evil FTP Server Ready']),
OptBool.new('CYCLIC', [ true, "Use Cyclic pattern instead of A's (fuzzing payload).", true]),
OptBool.new('ERROR', [ true, "Reply with error codes only",false]),
OptBool.new('ERROR', [ true, 'Reply with error codes only', false]),
OptBool.new('EXTRALINE', [ true, "Add extra CRLF's in response to LIST", true])
])
]
)
end
# Not compatible today
def support_ipv6?
false
@@ -54,217 +57,216 @@ class MetasploitModule < Msf::Auxiliary
def run
@fuzzsize = datastore['STARTSIZE'].to_i
exploit()
exploit
end
# Handler for new FTP client connections
def on_client_connect(c)
@state[c] = {
:name => "#{c.peerhost}:#{c.peerport}",
:ip => c.peerhost,
:port => c.peerport,
:user => nil,
:pass => nil
def on_client_connect(client)
@state[client] = {
name: "#{client.peerhost}:#{client.peerport}",
ip: client.peerhost,
port: client.peerport,
user: nil,
pass: nil
}
# set up an active data port on port 20
print_status("Client connected : " + c.peerhost)
active_data_port_for_client(c, 20)
send_response(c,"","WELCOME",220," "+datastore['WELCOME'])
print_status("Client connected : #{client.peerhost}")
active_data_port_for_client(client, 20)
send_response(client, '', 'WELCOME', 220, ' ' + datastore['WELCOME'])
# from this point forward, on_client_data() will take over
end
def on_client_close(c)
@state.delete(c)
def on_client_close(client)
@state.delete(client)
end
# Active and Passive data connections
def passive_data_port_for_client(c)
@state[c][:mode] = :passive
if(not @state[c][:passive_sock])
def passive_data_port_for_client(client)
@state[client][:mode] = :passive
if !(@state[client][:passive_sock])
s = Rex::Socket::TcpServer.create(
'LocalHost' => '0.0.0.0',
'LocalPort' => 0,
'Context' => { 'Msf' => framework, 'MsfExploit' => self }
)
dport = s.getsockname[2]
@state[c][:passive_sock] = s
@state[c][:passive_port] = dport
@state[client][:passive_sock] = s
@state[client][:passive_port] = dport
print_status(" - Set up passive data port #{dport}")
end
@state[c][:passive_port]
@state[client][:passive_port]
end
def active_data_port_for_client(c,port)
@state[c][:mode] = :active
connector = Proc.new {
host = c.peerhost.dup
sock = Rex::Socket::Tcp.create(
def active_data_port_for_client(client, port)
@state[client][:mode] = :active
connector = proc do
host = client.peerhost.dup
Rex::Socket::Tcp.create(
'PeerHost' => host,
'PeerPort' => port,
'Context' => { 'Msf' => framework, 'MsfExploit' => self }
)
}
@state[c][:active_connector] = connector
@state[c][:active_port] = port
end
@state[client][:active_connector] = connector
@state[client][:active_port] = port
print_status(" - Set up active data port #{port}")
end
def establish_data_connection(c)
print_status(" - Establishing #{@state[c][:mode]} data connection")
def establish_data_connection(client)
print_status(" - Establishing #{@state[client][:mode]} data connection")
begin
Timeout.timeout(20) do
if(@state[c][:mode] == :active)
return @state[c][:active_connector].call()
if (@state[client][:mode] == :active)
return @state[client][:active_connector].call
end
if(@state[c][:mode] == :passive)
return @state[c][:passive_sock].accept
if (@state[client][:mode] == :passive)
return @state[client][:passive_sock].accept
end
end
print_status(" - Data connection active")
rescue ::Exception => e
print_status(' - Data connection active')
rescue StandardError => e
print_error("Failed to establish data connection: #{e.class} #{e}")
end
nil
end
# FTP Client-to-Server Command handlers
def on_client_data(c)
def on_client_data(client)
# get the client data
data = c.get_once
return if not data
data = client.get_once
return if !data
# split data into command and arguments
cmd, arg = data.strip.split(/\s+/, 2)
arg ||= ""
arg ||= ''
return if !cmd
return if not cmd
# convert commands to uppercase and strip spaces
case cmd.upcase.strip
when 'USER'
@state[c][:user] = arg
send_response(c,arg,"USER",331," User name okay, need password")
@state[client][:user] = arg
send_response(client, arg, 'USER', 331, ' User name okay, need password')
return
when 'PASS'
@state[c][:pass] = arg
send_response(c,arg,"PASS",230,"-Password accepted.\r\n230 User logged in.")
@state[client][:pass] = arg
send_response(client, arg, 'PASS', 230, "-Password accepted.\r\n230 User logged in.")
return
when 'QUIT'
if (datastore['RESET'])
print_status("Resetting fuzz settings")
if datastore['RESET']
print_status('Resetting fuzz settings')
@fuzzsize = datastore['STARTSIZE']
@stepsize = datastore['STEPSIZE']
end
print_status("** Client disconnected **")
send_response(c,arg,"QUIT",221," User logged out")
print_status('** Client disconnected **')
send_response(client, arg, 'QUIT', 221, ' User logged out')
return
when 'SYST'
send_response(c,arg,"SYST",215," UNIX Type: L8")
send_response(client, arg, 'SYST', 215, ' UNIX Type: L8')
return
when 'TYPE'
send_response(c,arg,"TYPE",200," Type set to #{arg}")
send_response(client, arg, 'TYPE', 200, " Type set to #{arg}")
return
when 'CWD'
send_response(c,arg,"CWD",250," CWD Command successful")
send_response(client, arg, 'CWD', 250, ' CWD Command successful')
return
when 'PWD'
send_response(c,arg,"PWD",257," \"/\" is current directory.")
send_response(client, arg, 'PWD', 257, ' "/" is current directory.')
return
when 'REST'
send_response(c,arg,"REST",200," OK")
send_response(client, arg, 'REST', 200, ' OK')
return
when 'XPWD'
send_response(c,arg,"PWD",257," \"/\" is current directory")
send_response(client, arg, 'PWD', 257, ' "/" is current directory')
return
when 'SIZE'
send_response(c,arg,"SIZE",213," 1")
send_response(client, arg, 'SIZE', 213, ' 1')
return
when 'MDTM'
send_response(c,arg,"MDTM",213," #{Time.now.strftime("%Y%m%d%H%M%S")}")
send_response(client, arg, 'MDTM', 213, " #{Time.now.strftime('%Y%m%d%H%M%S')}")
return
when 'CDUP'
send_response(c,arg,"CDUP",257," \"/\" is current directory")
send_response(client, arg, 'CDUP', 257, ' "/" is current directory')
return
when 'PORT'
port = arg.split(',')[4, 2]
if(not port and port.length == 2)
c.put("500 Illegal PORT command.\r\n")
if !port && (port.length == 2)
client.put("500 Illegal PORT command.\r\n")
return
end
port = port.map{|x| x.to_i}.pack('C*').unpack('n')[0]
active_data_port_for_client(c, port)
send_response(c,arg,"PORT",200," PORT command successful")
port = port.map(&:to_i).pack('C*').unpack('n')[0]
active_data_port_for_client(client, port)
send_response(client, arg, 'PORT', 200, ' PORT command successful')
return
when 'PASV'
print_status("Handling #{cmd.upcase} command")
daddr = Rex::Socket.source_address(c.peerhost)
dport = passive_data_port_for_client(c)
@state[c][:daddr] = daddr
@state[c][:dport] = dport
daddr = Rex::Socket.source_address(client.peerhost)
dport = passive_data_port_for_client(client)
@state[client][:daddr] = daddr
@state[client][:dport] = dport
pasv = (daddr.split('.') + [dport].pack('n').unpack('CC')).join(',')
dofuzz = fuzz_this_cmd("PASV")
dofuzz = fuzz_this_cmd('PASV')
code = 227
if datastore['ERROR']
code = 557
end
if (dofuzz == 1)
print_status(" * Fuzzing response for PASV, payload length #{@fuzzdata.length}")
send_response(c,arg,"PASV",code," Entering Passive Mode (#{@fuzzdata},1,1,1,1,1)\r\n")
incr_fuzzsize()
send_response(client, arg, 'PASV', code, " Entering Passive Mode (#{@fuzzdata},1,1,1,1,1)\r\n")
incr_fuzzsize
else
send_response(c,arg,"PASV",code," Entering Passive Mode (#{pasv})")
send_response(client, arg, 'PASV', code, " Entering Passive Mode (#{pasv})")
end
return
when /^(LIST|NLST|LS)$/
# special case - requires active/passive connection
print_status("Handling #{cmd.upcase} command")
conn = establish_data_connection(c)
if(not conn)
c.put("425 Can't build data connection\r\n")
conn = establish_data_connection(client)
if !conn
client.put("425 Can't build data connection\r\n")
return
end
print_status(" - Data connection set up")
print_status(' - Data connection set up')
code = 150
if datastore['ERROR']
code = 550
end
c.put("#{code} Here comes the directory listing.\r\n")
client.put("#{code} Here comes the directory listing.\r\n")
code = 226
if datastore['ERROR']
code = 550
end
c.put("#{code} Directory send ok.\r\n")
strfile = "passwords.txt"
strfolder = "Secret files"
dofuzz = fuzz_this_cmd("LIST")
client.put("#{code} Directory send ok.\r\n")
strfile = 'passwords.txt'
strfolder = 'Secret files'
dofuzz = fuzz_this_cmd('LIST')
if (dofuzz == 1)
strfile = @fuzzdata + ".txt"
strfile = @fuzzdata + '.txt'
strfolder = @fuzzdata
paylen = @fuzzdata.length
print_status("* Fuzzing response for LIST, payload length #{paylen}")
incr_fuzzsize()
incr_fuzzsize
end
print_status(" - Sending directory list via data connection")
dirlist = ""
print_status(' - Sending directory list via data connection')
if datastore['EXTRALINE']
extra = "\r\n"
else
extra = ""
extra = ''
end
dirlist = "drwxrwxrwx 1 100 0 11111 Jun 11 21:10 #{strfolder}\r\n" + extra
dirlist << "-rw-rw-r-- 1 1176 1176 1060 Aug 16 22:22 #{strfile}\r\n" + extra
@@ -275,65 +277,67 @@ class MetasploitModule < Msf::Auxiliary
when 'RETR'
# special case - requires active/passive connection
print_status("Handling #{cmd.upcase} command")
conn = establish_data_connection(c)
if(not conn)
c.put("425 Can't build data connection\r\n")
conn = establish_data_connection(client)
if !conn
client.put("425 Can't build data connection\r\n")
return
end
print_status(" - Data connection set up")
strcontent = "blahblahblah"
dofuzz = fuzz_this_cmd("LIST")
print_status(' - Data connection set up')
strcontent = 'blahblahblah'
dofuzz = fuzz_this_cmd('LIST')
if (dofuzz == 1)
strcontent = @fuzzdata
paylen = @fuzzdata.length
print_status("* Fuzzing response for RETR, payload length #{paylen}")
incr_fuzzsize()
incr_fuzzsize
end
c.put("150 Opening BINARY mode data connection #{strcontent}\r\n")
print_status(" - Sending data via data connection")
client.put("150 Opening BINARY mode data connection #{strcontent}\r\n")
print_status(' - Sending data via data connection')
conn.put(strcontent)
c.put("226 Transfer complete\r\n")
client.put("226 Transfer complete\r\n")
conn.close
return
when /^(STOR|MKD|REM|DEL|RMD)$/
send_response(c,arg,cmd.upcase,500," Access denied")
send_response(client, arg, cmd.upcase, 500, ' Access denied')
return
when 'FEAT'
send_response(c,arg,"FEAT","","211-Features:\r\n211 End")
send_response(client, arg, 'FEAT', '', "211-Features:\r\n211 End")
return
when 'HELP'
send_response(c,arg,"HELP",214," Syntax: #{arg} - (#{arg}-specific commands)")
send_response(client, arg, 'HELP', 214, " Syntax: #{arg} - (#{arg}-specific commands)")
when 'SITE'
send_response(c,arg,"SITE",200," OK")
send_response(client, arg, 'SITE', 200, ' OK')
return
when 'NOOP'
send_response(c,arg,"NOOP",200," OK")
send_response(client, arg, 'NOOP', 200, ' OK')
return
when 'ABOR'
send_response(c,arg,"ABOR",225," Abor command successful")
send_response(client, arg, 'ABOR', 225, ' Abor command successful')
return
when 'ACCT'
send_response(c,arg,"ACCT",200," OK")
send_response(client, arg, 'ACCT', 200, ' OK')
return
when 'RNFR'
send_response(c,arg,"RNRF",350," File.exist")
send_response(client, arg, 'RNRF', 350, ' File.exist')
return
when 'RNTO'
send_response(c,arg,"RNTO",350," File.exist")
send_response(client, arg, 'RNTO', 350, ' File.exist')
return
else
send_response(c,arg,cmd.upcase,200," Command not understood")
send_response(client, arg, cmd.upcase, 200, ' Command not understood')
return
end
return
end
@@ -341,71 +345,76 @@ class MetasploitModule < Msf::Auxiliary
# Do we need to fuzz this command ?
def fuzz_this_cmd(cmd)
@fuzzcommands = datastore['FUZZCMDS'].split(",")
@fuzzcommands = datastore['FUZZCMDS'].split(',')
fuzzme = 0
@fuzzcommands.each do |thiscmd|
if ((cmd.upcase == thiscmd.upcase) || (thiscmd=="*")) && (fuzzme==0)
if ((cmd.upcase == thiscmd.upcase) || (thiscmd == '*')) && (fuzzme == 0)
fuzzme = 1
break
end
end
if fuzzme == 1
# should we use a cyclic pattern, or just A's ?
if datastore['CYCLIC']
@fuzzdata = Rex::Text.pattern_create(@fuzzsize)
else
@fuzzdata = "A" * @fuzzsize
@fuzzdata = 'A' * @fuzzsize
end
end
return fuzzme
end
def incr_fuzzsize
@stepsize = datastore['STEPSIZE'].to_i
@fuzzsize = @fuzzsize + @stepsize
@fuzzsize += @stepsize
print_status("(i) Setting next payload size to #{@fuzzsize}")
if (@fuzzsize > datastore['ENDSIZE'].to_i)
@fuzzsize = datastore['ENDSIZE'].to_i
end
end
# Send data back to the server
def send_response(c,arg,cmd,code,msg)
def send_response(client, arg, cmd, code, msg)
if arg.length > 40
showarg = arg[0,40] + "..."
showarg = arg[0, 40] + '...'
else
showarg = arg
end
if cmd.length > 40
showcmd = cmd[0,40] + "..."
showcmd = cmd[0, 40] + '...'
else
showcmd = cmd
end
print_status("Sending response for '#{showcmd}' command, arg #{showarg}")
dofuzz = fuzz_this_cmd(cmd)
## Fuzz this command ? (excluding PASV, which is handled in the command handler)
if (dofuzz==1) && (cmd.upcase != "PASV")
if (dofuzz == 1) && (cmd.upcase != 'PASV')
paylen = @fuzzdata.length
print_status("* Fuzzing response for #{cmd.upcase}, payload length #{paylen}")
if datastore['ERROR']
code = "550 "
code = '550 '
end
if cmd=="FEAT"
if cmd == 'FEAT'
@fuzzdata = "211-Features:\r\n " + @fuzzdata + "\r\n211 End"
end
if cmd=="PWD"
@fuzzdata = " \"/"+@fuzzdata+"\" is current directory"
if cmd == 'PWD'
@fuzzdata = ' "/' + @fuzzdata + '" is current directory'
end
cmsg = code.to_s + " " + @fuzzdata
c.put("#{cmsg}\r\n")
print_status("* Fuzz data sent")
incr_fuzzsize()
cmsg = code.to_s + ' ' + @fuzzdata
client.put("#{cmsg}\r\n")
print_status('* Fuzz data sent')
incr_fuzzsize
else
# Do not fuzz
cmsg = code.to_s + msg
cmsg = cmsg.strip
c.put("#{cmsg}\r\n")
end
return
client.put("#{cmsg}\r\n")
end
end
end
+66 -61
View File
@@ -14,23 +14,29 @@ class MetasploitModule < Msf::Auxiliary
This module will connect to a FTP server and perform pre- and post-authentication fuzzing
},
'Author' => [ 'corelanc0d3r <peter.ve[at]corelan.be>', 'jduck' ],
'License' => MSF_LICENSE
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SERVICE_DOWN],
'SideEffects' => [],
'Reliability' => []
}
)
register_options(
[
Opt::RPORT(21),
OptInt.new('STARTATSTAGE', [ false, "Start at this test stage",1]),
OptInt.new('STEPSIZE', [ false, "Increase string size each iteration with this number of chars",10]),
OptInt.new('DELAY', [ false, "Delay between connections in seconds",1]),
OptInt.new('STARTSIZE', [ false, "Fuzzing string startsize",10]),
OptInt.new('ENDSIZE', [ false, "Fuzzing string endsize",20000]),
OptInt.new('STOPAFTER', [ false, "Stop after x number of consecutive errors",2]),
OptString.new('USER', [ false, "Username",'anonymous']),
OptString.new('PASS', [ false, "Password",'mozilla@example.com']),
OptBool.new('FASTFUZZ', [ false, "Only fuzz with cyclic pattern",true]),
OptBool.new('CONNRESET', [ false, "Break on CONNRESET error",true]),
])
OptInt.new('STARTATSTAGE', [ false, 'Start at this test stage', 1]),
OptInt.new('STEPSIZE', [ false, 'Increase string size each iteration with this number of chars', 10]),
OptInt.new('DELAY', [ false, 'Delay between connections in seconds', 1]),
OptInt.new('STARTSIZE', [ false, 'Fuzzing string startsize', 10]),
OptInt.new('ENDSIZE', [ false, 'Fuzzing string endsize', 20000]),
OptInt.new('STOPAFTER', [ false, 'Stop after x number of consecutive errors', 2]),
OptString.new('USER', [ false, 'Username', 'anonymous']),
OptString.new('PASS', [ false, 'Password', 'mozilla@example.com']),
OptBool.new('FASTFUZZ', [ false, 'Only fuzz with cyclic pattern', true]),
OptBool.new('CONNRESET', [ false, 'Break on CONNRESET error', true]),
]
)
@evilchars = [
'A', 'a', '%s', '%d', '%n', '%x', '%p', '-1', '0', '0xfffffffe', '0xffffffff', 'A/', '//', '/..', '//..',
@@ -53,36 +59,35 @@ class MetasploitModule < Msf::Auxiliary
register_advanced_options(
[
OptString.new('FtpCommands', [ false, "Commands to fuzz at stages 4 and 5",@commands.join(" ")]),
OptBool.new('ExpandCrash', [ false, "Expand any crash strings",false]),
])
OptString.new('FtpCommands', [ false, 'Commands to fuzz at stages 4 and 5', @commands.join(' ')]),
OptBool.new('ExpandCrash', [ false, 'Expand any crash strings', false]),
]
)
end
def get_pkt
buf = sock.get_once(-1, 10)
vprint_status("[in ] #{buf.inspect}")
buf
end
def send_pkt(pkt, get_resp = false)
def send_pkt(pkt, get_resp: true)
vprint_status("[out] #{pkt.inspect}")
sock.put(pkt)
get_pkt if get_resp
end
def process_phase(phase_num, phase_name, prepend = '', initial_cmds = [])
print_status("[Phase #{phase_num}] #{phase_name} - #{Time.now.localtime}")
ecount = 1
@evilchars.each do |evilstr|
if datastore['FASTFUZZ']
evilstr = "Cyclic"
evilstr = 'Cyclic'
@emax = 1
end
if (@stopprocess == false)
next unless (@stopprocess == false)
count = datastore['STARTSIZE']
print_status(" Character : #{evilstr} (#{ecount}/#{@emax})")
ecount += 1
@@ -96,20 +101,19 @@ class MetasploitModule < Msf::Auxiliary
end
print_status(" -> Fuzzing size set to #{count} (#{prepend}#{evilstr})")
initial_cmds.each do |cmd|
send_pkt(cmd, true)
send_pkt(cmd)
end
pkt = prepend + evil + "\r\n"
send_pkt(pkt, true)
send_pkt(pkt)
sock.put("QUIT\r\n")
select(nil, nil, nil, datastore['DELAY'])
disconnect
count += datastore['STEPSIZE']
rescue ::Exception => e
rescue StandardError => e
@error_cnt += 1
print_status("Exception #{@error_cnt} of #{@nr_errors}")
if (e.class.name == 'Rex::ConnectionRefused') or (e.class.name == 'EOFError') or (e.class.name == 'Errno::ECONNRESET' and datastore['CONNRESET']) or (e.class.name == 'Errno::EPIPE')
if e.instance_of?(::Rex::ConnectionRefused) || e.instance_of?(::EOFError) || (e.instance_of?(::Errno::ECONNRESET) && datastore['CONNRESET']) || e.instance_of?(::Errno::EPIPE)
if datastore['ExpandCrash']
print_status("Crash string : #{prepend}#{evil}")
else
@@ -119,7 +123,7 @@ class MetasploitModule < Msf::Auxiliary
print_status("System does not respond - exiting now\n")
@stopprocess = true
print_error("Error: #{e.class} #{e} #{e.backtrace}\n")
return
break
else
print_status("Exception triggered, need #{@nr_errors - @error_cnt} more exception(s) before interrupting process")
select(nil, nil, nil, 3) # wait 3 seconds
@@ -133,10 +137,9 @@ class MetasploitModule < Msf::Auxiliary
end
end
end
end
def ftp_commands
if datastore['FtpCommands'].to_s.upcase == "DEFAULT"
if datastore['FtpCommands'].to_s.upcase == 'DEFAULT'
@commands
else
datastore['FtpCommands'].split(/[\s,]+/)
@@ -144,7 +147,6 @@ class MetasploitModule < Msf::Auxiliary
end
def run_host(ip)
startstage = datastore['STARTATSTAGE']
@nr_errors = datastore['STOPAFTER']
@@ -155,34 +157,37 @@ class MetasploitModule < Msf::Auxiliary
@evilchars = ['']
end
print_status("Connecting to host " + ip + " on port " + datastore['RPORT'].to_s)
print_status('Connecting to host ' + ip + ' on port ' + datastore['RPORT'].to_s)
if (startstage == 1)
process_phase(1, "Fuzzing without command")
process_phase(1, 'Fuzzing without command')
startstage += 1
end
if (startstage == 2) and (@stopprocess == false)
process_phase(2, "Fuzzing USER", 'USER ')
if (startstage == 2) && (@stopprocess == false)
process_phase(2, 'Fuzzing USER', 'USER ')
startstage += 1
end
if (startstage == 3) and (@stopprocess == false)
process_phase(3, "Fuzzing PASS", 'PASS ',
[ "USER " + datastore['USER'] + "\r\n" ])
if (startstage == 3) && (@stopprocess == false)
process_phase(3, 'Fuzzing PASS', 'PASS ',
[ 'USER ' + datastore['USER'] + "\r\n" ])
startstage += 1
end
if (startstage == 4)
print_status "[Phase 4] Fuzzing commands: #{ftp_commands.join(", ")}"
ftp_commands().each do |cmd|
if (@stopprocess == false)
process_phase(4, "Fuzzing command: #{cmd}", "#{cmd} ",
print_status "[Phase 4] Fuzzing commands: #{ftp_commands.join(', ')}"
ftp_commands.each do |cmd|
next unless (@stopprocess == false)
process_phase(
4,
"Fuzzing command: #{cmd}", "#{cmd} ",
[
"USER " + datastore['USER'] + "\r\n",
"PASS " + datastore['PASS'] + "\r\n"
])
end
'USER ' + datastore['USER'] + "\r\n",
'PASS ' + datastore['PASS'] + "\r\n"
]
)
end
# Don't progress into stage 5, it must be selected manually.
# startstage += 1
@@ -190,25 +195,26 @@ class MetasploitModule < Msf::Auxiliary
# Fuzz other commands, all command combinations in one session
if (startstage == 5)
print_status("[Phase 5] Fuzzing other commands (Part 2, #{Time.now.localtime}): #{ftp_commands.join(", ")}")
ftp_commands().each do |cmd|
if (@stopprocess == false)
print_status("[Phase 5] Fuzzing other commands (Part 2, #{Time.now.localtime}): #{ftp_commands.join(', ')}")
ftp_commands.each do |cmd|
next unless (@stopprocess == false)
ecount = 1
count = datastore['STARTSIZE']
print_status("Fuzzing command #{cmd} - #{Time.now.localtime}")
connect
pkt = "USER " + datastore['USER'] + "\r\n"
send_pkt(pkt, true)
pkt = "PASS " + datastore['PASS'] + "\r\n"
send_pkt(pkt, true)
pkt = 'USER ' + datastore['USER'] + "\r\n"
send_pkt(pkt)
pkt = 'PASS ' + datastore['PASS'] + "\r\n"
send_pkt(pkt)
while count <= datastore['ENDSIZE']
print_status(" -> Fuzzing size set to #{count}")
begin
@evilchars.each do |evilstr|
if datastore['FASTFUZZ']
evilstr = "Cyclic"
evilstr = 'Cyclic'
evil = Rex::Text.pattern_create(count)
@emax = 1
ecount = 1
@@ -217,25 +223,25 @@ class MetasploitModule < Msf::Auxiliary
end
print_status(" Command : #{cmd}, Character : #{evilstr} (#{ecount}/#{@emax})")
ecount += 1
pkt = cmd + " " + evil + "\r\n"
send_pkt(pkt, true)
pkt = cmd + ' ' + evil + "\r\n"
send_pkt(pkt)
select(nil, nil, nil, datastore['DELAY'])
@error_cnt = 0
end
rescue ::Exception => e
rescue StandardError => e
@error_cnt += 1
print_status("Exception #{@error_cnt} of #{@nr_errors}")
if (e.class.name == 'Rex::ConnectionRefused') or (e.class.name == 'EOFError') or (e.class.name == 'Errno::ECONNRESET' and datastore['CONNRESET']) or (e.class.name == 'Errno::EPIPE')
if e.instance_of?(::Rex::ConnectionRefused) || e.instance_of?(::EOFError) || (e.instance_of?(::Errno::ECONNRESET) && datastore['CONNRESET']) || e.instance_of?(::Errno::EPIPE)
if @error_cnt >= @nr_errors
print_status("System does not respond - exiting now\n")
@stopprocess = true
print_error("Error: #{e.class} #{e} #{e.backtrace}\n")
return
else
break
end
print_status("Exception triggered, need #{@nr_errors - @error_cnt} more exception(s) before interrupting process")
select(nil, nil, nil, 3) # wait 3 seconds
end
end
if @error_cnt >= @nr_errors
@error_cnt = 0
end
@@ -249,4 +255,3 @@ class MetasploitModule < Msf::Auxiliary
end
end
end
end
+158 -151
View File
@@ -7,7 +7,9 @@ class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
super(
update_info(
info,
'Name' => 'HTTP Form Field Fuzzer',
'Description' => %q{
This module will grab all fields from a form,
@@ -20,44 +22,50 @@ class MetasploitModule < Msf::Auxiliary
'Paulino Calderon <calderon[at]websec.mx>' # Added cookie handling
],
'License' => MSF_LICENSE,
'References' =>
[
'References' => [
['URL', 'http://www.corelan.be:8800/index.php/2010/11/12/metasploit-module-http-form-field-fuzzer'],
]
))
],
'Notes' => {
'Stability' => [CRASH_SERVICE_DOWN],
'SideEffects' => [],
'Reliability' => []
}
)
)
register_options(
[
OptString.new('URL', [ false, "The URL that contains the form", "/"]),
OptString.new('FORM', [ false, "The name of the form to use. Leave empty to fuzz all forms","" ] ),
OptString.new('FIELDS', [ false, "Name of the fields to fuzz. Leave empty to fuzz all fields","" ] ),
OptString.new('ACTION', [ false, "Form action full URI. Leave empty to autodetect","" ] ),
OptInt.new('STARTSIZE', [ true, "Fuzzing string startsize.",1000]),
OptInt.new('ENDSIZE', [ true, "Max Fuzzing string size.",40000]),
OptInt.new('STEPSIZE', [ true, "Increment fuzzing string each attempt.",1000]),
OptInt.new('TIMEOUT', [ true, "Number of seconds to wait for response on GET or POST",15]),
OptInt.new('DELAY', [ true, "Number of seconds to wait between 2 actions",0]),
OptInt.new('STOPAFTER', [ false, "Stop after x number of consecutive errors",2]),
OptString.new('URL', [ false, 'The URL that contains the form', '/']),
OptString.new('FORM', [ false, 'The name of the form to use. Leave empty to fuzz all forms', '' ]),
OptString.new('FIELDS', [ false, 'Name of the fields to fuzz. Leave empty to fuzz all fields', '' ]),
OptString.new('ACTION', [ false, 'Form action full URI. Leave empty to autodetect', '' ]),
OptInt.new('STARTSIZE', [ true, 'Fuzzing string startsize.', 1000]),
OptInt.new('ENDSIZE', [ true, 'Max Fuzzing string size.', 40000]),
OptInt.new('STEPSIZE', [ true, 'Increment fuzzing string each attempt.', 1000]),
OptInt.new('TIMEOUT', [ true, 'Number of seconds to wait for response on GET or POST', 15]),
OptInt.new('DELAY', [ true, 'Number of seconds to wait between 2 actions', 0]),
OptInt.new('STOPAFTER', [ false, 'Stop after x number of consecutive errors', 2]),
OptBool.new('CYCLIC', [ true, "Use Cyclic pattern instead of A's (fuzzing payload).", true]),
OptBool.new('FUZZHEADERS', [ true, "Fuzz headers",true]),
OptString.new('HEADERFIELDS', [ false, "Name of the headerfields to fuzz. Leave empty to fuzz all fields","" ] ),
OptString.new('TYPES', [ true, "Field types to fuzz","text,password,inputtextbox"]),
OptString.new('CODE', [ true, "Response code(s) indicating OK", "200,301,302,303" ] ),
OptBool.new('HANDLECOOKIES', [ true, "Appends cookies with every request.",false])
])
OptBool.new('FUZZHEADERS', [ true, 'Fuzz headers', true]),
OptString.new('HEADERFIELDS', [ false, 'Name of the headerfields to fuzz. Leave empty to fuzz all fields', '' ]),
OptString.new('TYPES', [ true, 'Field types to fuzz', 'text,password,inputtextbox']),
OptString.new('CODE', [ true, 'Response code(s) indicating OK', '200,301,302,303' ]),
OptBool.new('HANDLECOOKIES', [ true, 'Appends cookies with every request.', false])
]
)
end
def init_vars
proto = "http://"
proto = 'http://'
if datastore['SSL']
proto = "https://"
proto = 'https://'
end
@send_data = {
:uri => '',
:version => '1.1',
:method => 'POST',
:headers => {
uri: '',
version: '1.1',
method: 'POST',
headers: {
'Content-Length' => 100,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-us,en;q=0.5',
@@ -65,41 +73,41 @@ class MetasploitModule < Msf::Auxiliary
'Accept-Charset' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
'Keep-Alive' => '300',
'Connection' => 'keep-alive',
'Referer' => proto + datastore['RHOST'] + ":" + datastore['RPORT'].to_s,
'Referer' => proto + datastore['RHOST'] + ':' + datastore['RPORT'].to_s,
'Content-Type' => 'application/x-www-form-urlencoded'
}
}
@get_data_headers = {
'Referer' => proto + datastore['RHOST'] + ":" + datastore['RPORT'].to_s,
'Referer' => proto + datastore['RHOST'] + ':' + datastore['RPORT'].to_s
}
end
def init_fuzzdata
@fuzzsize = datastore['STARTSIZE']
@endsize = datastore['ENDSIZE']
set_fuzz_payload()
set_fuzz_payload
@nrerrors = 0
end
def incr_fuzzsize
@stepsize = datastore['STEPSIZE'].to_i
@fuzzsize = @fuzzsize + @stepsize
@fuzzsize += @stepsize
end
def set_fuzz_payload
if datastore['CYCLIC']
@fuzzdata = Rex::Text.pattern_create(@fuzzsize)
else
@fuzzdata = "A" * @fuzzsize
@fuzzdata = 'A' * @fuzzsize
end
end
def is_error_code(code)
okcode = false
checkcodes = datastore['CODE'].split(",")
checkcodes = datastore['CODE'].split(',')
checkcodes.each do |testcode|
testcode = testcode.upcase.gsub(" ","")
if testcode == code.to_s().upcase.gsub(" ","")
testcode = testcode.upcase.gsub(' ', '')
if testcode == code.to_s.upcase.gsub(' ', '')
okcode = true
end
end
@@ -107,17 +115,17 @@ class MetasploitModule < Msf::Auxiliary
end
def fuzz_this_field(fieldname, fieldtype)
fuzzcommands = datastore['FIELDS'].split(",")
fuzzcommands = datastore['FIELDS'].split(',')
fuzzme = 0
if fuzzcommands.size > 0
if !fuzzcommands.empty?
fuzzcommands.each do |thiscmd|
thiscmd = thiscmd.strip
if ((fieldname.upcase == thiscmd.upcase) || (thiscmd == "")) && (fuzzme == 0)
if ((fieldname.upcase == thiscmd.upcase) || (thiscmd == '')) && (fuzzme == 0)
fuzzme = 1
end
end
else
fuzztypes = datastore['TYPES'].split(",")
fuzztypes = datastore['TYPES'].split(',')
fuzztypes.each do |thistype|
if (fieldtype.upcase.strip == thistype.upcase.strip)
fuzzme = 1
@@ -125,18 +133,18 @@ class MetasploitModule < Msf::Auxiliary
end
end
if fuzzme == 1
set_fuzz_payload()
set_fuzz_payload
end
return fuzzme
end
def fuzz_this_headerfield(fieldname)
fuzzheaderfields = datastore['HEADERFIELDS'].split(",")
fuzzheaderfields = datastore['HEADERFIELDS'].split(',')
fuzzme = 0
if fuzzheaderfields.size > 0
if !fuzzheaderfields.empty?
fuzzheaderfields.each do |thisfield|
thisfield = thisfield.strip
if ((fieldname.upcase == thisfield.upcase) || (thisfield == "")) && (fuzzme == 0)
if ((fieldname.upcase == thisfield.upcase) || (thisfield == '')) && (fuzzme == 0)
fuzzme = 1
end
end
@@ -144,24 +152,22 @@ class MetasploitModule < Msf::Auxiliary
fuzzme = 1
end
if fuzzme == 1
set_fuzz_payload()
set_fuzz_payload
end
return fuzzme
end
def do_fuzz_headers(form, headers)
headercnt = 0
datastr = ""
datastr = ''
form[:fields].each do |thisfield|
normaldata = "blah&"
if thisfield[:value]
if thisfield[:value] != ""
normaldata = thisfield[:value].strip + "&"
normaldata = 'blah&'
if thisfield[:value] && thisfield[:value] != ('')
normaldata = thisfield[:value].strip + '&'
end
datastr << thisfield[:name].downcase.strip + '=' + normaldata
end
datastr << thisfield[:name].downcase.strip + "=" + normaldata
end
if datastr.length > 0
if !datastr.empty?
datastr = datastr[0, datastr.length - 1] + "\r\n"
else
datastr = "\r\n"
@@ -172,7 +178,7 @@ class MetasploitModule < Msf::Auxiliary
# get or post ?
mysendheaders[:method] = form[:method].upcase
myheaders.each do |thisheader|
if not headers[thisheader[0]]
if !(headers[thisheader[0]])
# add header if needed
mysendheaders[thisheader[0]] = thisheader[1]
end
@@ -184,21 +190,21 @@ class MetasploitModule < Msf::Auxiliary
fuzzpacket = @send_data.dup
fuzzpacket[:method] = mysendheaders[:method]
headername = thisheader[0]
if fuzz_this_headerfield(headername.to_s().upcase) == 1
if fuzz_this_headerfield(headername.to_s.upcase) == 1
print_status(" - Fuzzing header '#{headername}' (#{headercnt + 1}/#{nrheaderstofuzz})")
init_fuzzdata()
init_fuzzdata
while @fuzzsize <= @endsize + 1
@fuzzheader[headername] = @fuzzdata
fuzzpacket[:headers] = @fuzzheader
response = send_fuzz(fuzzpacket, datastr)
if not process_response(response,headername,"header")
if !process_response(response, headername, 'header')
@fuzzsize = @endsize + 2
end
if datastore['DELAY'] > 0
print_status(" (Sleeping for #{datastore['DELAY']} seconds...)")
select(nil, nil, nil, datastore['DELAY'])
end
incr_fuzzsize()
incr_fuzzsize
end
else
print_status(" - Skipping header '#{headername}' (#{headercnt + 1}/#{nrheaderstofuzz})")
@@ -208,32 +214,32 @@ class MetasploitModule < Msf::Auxiliary
end
def do_fuzz_field(form, field)
fieldstofuzz = field.downcase.strip.split(",")
fieldstofuzz = field.downcase.strip.split(',')
@nrerrors = 0
while @fuzzsize <= @endsize + 1
allfields = form[:fields]
datastr = ""
normaldata = ""
datastr = ''
normaldata = ''
allfields.each do |thisfield|
dofuzzthis = false
if thisfield[:name]
next unless thisfield[:name]
fieldstofuzz.each do |fuzzthis|
if fuzzthis
next unless fuzzthis
if (thisfield[:name].downcase.strip == fuzzthis.downcase.strip)
dofuzzthis = true
end
end
end
if thisfield[:value]
normaldata = thisfield[:value].strip
else
normaldata = ""
normaldata = ''
end
if (dofuzzthis)
datastr << thisfield[:name].downcase.strip + "=" + @fuzzdata + "&"
if dofuzzthis
datastr << thisfield[:name].downcase.strip + '=' + @fuzzdata + '&'
else
datastr << thisfield[:name].downcase.strip + "=" + normaldata + "&"
end
datastr << thisfield[:name].downcase.strip + '=' + normaldata + '&'
end
end
datastr = datastr[0, datastr.length - 1]
@@ -242,9 +248,10 @@ class MetasploitModule < Msf::Auxiliary
@send_data[:method] = form[:method].upcase
response = send_fuzz(@send_data, datastr)
if not process_response(response,field,"field")
if !process_response(response, field, 'field')
return
end
if datastore['DELAY'] > 0
print_status(" (Sleeping for #{datastore['DELAY']} seconds...)")
select(nil, nil, nil, datastore['DELAY'])
@@ -253,25 +260,25 @@ class MetasploitModule < Msf::Auxiliary
end
def process_response(response, field, type)
if response == nil
if response.nil?
print_error(" No response - #{@nrerrors + 1} / #{datastore['STOPAFTER']} - fuzzdata length : #{@fuzzsize}")
if @nrerrors + 1 >= datastore['STOPAFTER']
print_status(" *!* No response : #{type} #{field} | fuzzdata length : #{@fuzzsize}")
return false
else
@nrerrors = @nrerrors + 1
@nrerrors += 1
end
else
okcode = is_error_code(response.code)
if okcode
@nrerrors = 0
incr_fuzzsize()
incr_fuzzsize
end
if not okcode and @nrerrors+1 >= datastore['STOPAFTER']
if !okcode && (@nrerrors + 1 >= datastore['STOPAFTER'])
print_status(" *!* Error response code #{response.code} | #{type} #{field} | fuzzdata length #{@fuzzsize}")
return false
else
@nrerrors = @nrerrors + 1
@nrerrors += 1
end
end
return true
@@ -290,22 +297,22 @@ class MetasploitModule < Msf::Auxiliary
end
def get_field_val(input)
tmp = input.split(/\=/)
tmp = input.split(/=/)
# get delimiter
tmp2 = tmp[1].strip
delim = tmp2[0, 1]
if delim != "'" && delim != '"'
delim = ""
delim = ''
end
tmp3 = tmp[1].split(/>/)
tmp4 = tmp3[0].gsub(delim,"")
tmp4 = tmp3[0].gsub(delim, '')
return tmp4
end
def get_form_data(body)
print_status("Enumerating form data")
body = body.gsub("\r","")
body = body.gsub("\n","")
print_status('Enumerating form data')
body = body.gsub("\r", '')
body = body.gsub("\n", '')
bodydata = body.downcase.split(/<form/)
# we need part after <form
totalforms = bodydata.size - 1
@@ -316,50 +323,50 @@ class MetasploitModule < Msf::Auxiliary
while formcnt < totalforms
fdata = bodydata[formidx]
print_status(" - Enumerating form ##{formcnt + 1}")
data = fdata.downcase.split(/<\/form>/)
data = fdata.downcase.split(%r{</form>})
# first, get action and name
formdata = data[0].downcase.split(/>/)
subdata = formdata[0].downcase.split(/ /)
namefound = false
actionfound = false
idfound = false
actionname = ""
formname = ""
formid = ""
formmethod = "post"
actionname = ''
formname = ''
formid = ''
formmethod = 'post'
subdata.each do |thisfield|
if thisfield.match(/^name=/) and not namefound
if thisfield.match(/^name=/) && !namefound
formname = get_field_val(thisfield)
namefound = true
end
if thisfield.match(/^id=/) and not idfound
if thisfield.match(/^id=/) && !idfound
formid = get_field_val(thisfield)
idfound = true
end
if thisfield.match(/^method=/)
formmethod = get_field_val(thisfield)
end
if thisfield.match(/^action=/) and not actionfound
next unless thisfield.match(/^action=/) && !actionfound
actionname = get_field_val(thisfield)
if (actionname.length < datastore['URL'].length) and (datastore['URL'].downcase.index(actionname.downcase).to_i() > -1)
if (actionname.length < datastore['URL'].length) && (datastore['URL'].downcase.index(actionname.downcase).to_i > -1)
actionname = datastore['URL']
end
actionfound = true
end
end
if datastore['ACTION'].length > 0
if !datastore['ACTION'].empty?
actionname = datastore['ACTION']
actionfound = true
end
if formname == "" and formid != ""
if (formname == '') && (formid != '')
formname = formid
end
if formid == "" and formname != ""
if (formid == '') && (formname != '')
formid = formname
end
if formid == "" and formname == ""
formid = "noname_" + (formcnt+1).to_s()
if (formid == '') && (formname == '')
formid = 'noname_' + (formcnt + 1).to_s
formname = formid
end
idfound = true
@@ -370,26 +377,27 @@ class MetasploitModule < Msf::Auxiliary
fieldtypemarks = [ '<input', '<select' ]
fieldtypemarks.each do |currfieldmark|
formfieldcnt = 0
if (namefound or idfound) and actionfound
next unless (namefound || idfound) && actionfound
# get fields in current form - data[0]
subdata = data[0].downcase.split(currfieldmark)
skipflag = 0
if subdata.size > 1
next unless subdata.size > 1
subdata.each do |thisinput|
if skipflag == 1
# first, find the delimiter
fielddata = thisinput.downcase.split(/>/)
fields = fielddata[0].split(/ /)
fieldname = ""
fieldtype = ""
fieldvalue = ""
fieldmethod = "post"
fieldid = ""
fieldname = ''
fieldtype = ''
fieldvalue = ''
fieldid = ''
fields.each do |thisfield|
if thisfield.match(/^type=/)
fieldtype = get_field_val(thisfield)
end
if currfieldmark == "<select" and thisfield.match(/^class=/)
if (currfieldmark == '<select') && thisfield.match(/^class=/)
fieldtype = get_field_val(thisfield)
end
if thisfield.match(/^name=/)
@@ -398,32 +406,32 @@ class MetasploitModule < Msf::Auxiliary
if thisfield.match(/^id=/)
fieldid = get_field_val(thisfield)
end
if thisfield.match(/^value=/)
next unless thisfield.match(/^value=/)
# special case
location = fielddata[0].index(thisfield)
delta = fielddata[0].size - location
remaining = fielddata[0][location, delta]
tmp = remaining.strip.split(/\=/)
if tmp.size > 1
tmp = remaining.strip.split(/=/)
next unless tmp.size > 1
delim = tmp[1][0, 1]
tmp2 = tmp[1].split(delim)
fieldvalue = tmp2[1]
end
end
end
if fieldname == "" and fieldid != ""
if (fieldname == '') && (fieldid != '')
fieldname = fieldid
end
if fieldid == "" and fieldname != ""
if (fieldid == '') && (fieldname != '')
fieldid = fieldname
end
print_status(" Field : #{fieldname}, type #{fieldtype}")
if fieldid != ""
if fieldid != ''
formfields << {
:id => fieldid,
:name => fieldname,
:type => fieldtype,
:value => fieldvalue
id: fieldid,
name: fieldname,
type: fieldtype,
value: fieldvalue
}
formfieldcnt += 1
end
@@ -432,23 +440,21 @@ class MetasploitModule < Msf::Auxiliary
end
end
end
end
end
print_status(" Nr of fields in form '#{formname}' : #{formfields.size}")
# store in multidimensional array
forms << {
:name => formname,
:id => formid,
:action => actionname,
:method => formmethod,
:fields => formfields
name: formname,
id: formid,
action: actionname,
method: formmethod,
fields: formfields
}
formidx = formidx + 1
formidx += 1
formcnt += 1
end
if forms.size > 0
print_status(" Forms : ")
if !forms.empty?
print_status(' Forms : ')
end
forms.each do |thisform|
@@ -459,13 +465,13 @@ class MetasploitModule < Msf::Auxiliary
end
def set_cookie(cookie)
@get_data_headers["Cookie"]=cookie
@send_data[:headers]["Cookie"]=cookie
@get_data_headers['Cookie'] = cookie
@send_data[:headers]['Cookie'] = cookie
end
def run
init_fuzzdata()
init_vars()
init_fuzzdata
init_vars
print_status("Grabbing webpage #{datastore['URL']} from #{datastore['RHOST']}")
response = send_request_raw(
@@ -475,9 +481,10 @@ class MetasploitModule < Msf::Auxiliary
'method' => 'GET',
'headers' => @get_data_headers
}, datastore['TIMEOUT'])
if response == nil
print_error("No response")
}, datastore['TIMEOUT']
)
if response.nil?
print_error('No response')
return
end
@@ -493,57 +500,57 @@ class MetasploitModule < Msf::Auxiliary
'version' => '1.1',
'method' => 'GET',
'headers' => @get_data_headers
}, datastore['TIMEOUT'])
}, datastore['TIMEOUT']
)
end
if response == nil
print_error("No response")
if response.nil?
print_error('No response')
return
end
print_status("Code : #{response.code}")
okcode = is_error_code(response.code)
if not okcode
print_error("Server replied with error code. Check URL or set CODE to another value, and try again.")
if !okcode
print_error('Server replied with error code. Check URL or set CODE to another value, and try again.')
return
end
if response.body
formfound = response.body.downcase.index("<form")
formfound = response.body.downcase.index('<form')
if formfound
formdata = get_form_data(response.body)
# fuzz !
# for each form that needs to be fuzzed
formdata.each do |thisform|
if thisform[:name].length > 0
if ((datastore['FORM'].strip == "") || (datastore['FORM'].upcase.strip == thisform[:name].upcase.strip)) && (thisform[:fields].size > 0)
next if thisform[:name].empty?
if ((datastore['FORM'].strip == '') || (datastore['FORM'].upcase.strip == thisform[:name].upcase.strip)) && !thisform[:fields].empty?
print_status("Fuzzing fields in form #{thisform[:name].upcase.strip}")
# for each field in this form, fuzz one field at a time
formfields = thisform[:fields]
formfields.each do |thisfield|
if thisfield[:name]
if fuzz_this_field(thisfield[:name],thisfield[:type]) == 1
next unless thisfield[:name]
next unless fuzz_this_field(thisfield[:name], thisfield[:type]) == 1
print_status(" - Fuzzing field #{thisfield[:name]}")
do_fuzz_field(thisform, thisfield[:name])
init_fuzzdata()
end
end
init_fuzzdata
end
print_status("Done fuzzing fields in form #{thisform[:name].upcase.strip}")
end
# fuzz headers ?
if datastore['FUZZHEADERS']
print_status("Fuzzing header fields")
print_status('Fuzzing header fields')
do_fuzz_headers(thisform, response.headers)
end
end
end
else
print_error("No form found in response body")
print_error('No form found in response body')
print_status(response.body)
return
end
else
print_error("No response data")
end
print_error('No response data')
end
end
end
@@ -3,24 +3,33 @@
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'English'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Fuzzer
def initialize(info = {})
super(update_info(info,
super(
update_info(
info,
'Name' => 'HTTP GET Request URI Fuzzer (Incrementing Lengths)',
'Description' => %q{
This module sends a series of HTTP GET request with incrementing URL lengths.
},
'Author' => [ 'nullthreat' ],
'License' => MSF_LICENSE
))
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SERVICE_DOWN],
'SideEffects' => [],
'Reliability' => []
}
)
)
register_options([
Opt::RPORT(80),
OptInt.new("MAXLENGTH", [true, "The longest string length to try", 16384] ),
OptString.new("URIBASE", [true, "The base URL to use for the request fuzzer", "/"]),
OptString.new("VHOST", [false, "The virtual host name to use in requests"])
OptInt.new('MAXLENGTH', [true, 'The longest string length to try', 16384]),
OptString.new('URIBASE', [true, 'The base URL to use for the request fuzzer', '/']),
OptString.new('VHOST', [false, 'The virtual host name to use in requests'])
])
end
@@ -54,23 +63,23 @@ class MetasploitModule < Msf::Auxiliary
end
begin
r = do_http_get(uri,:timeout => 0.25)
do_http_get(uri, timeout: 0.25)
rescue ::Interrupt
print_status("Exiting on interrupt: iteration #{cnt} using string length #{len}")
raise $!
rescue ::Exception => e
raise $ERROR_INFO
rescue StandardError => e
last_err = e
ensure
disconnect
end
if(not @connected)
if(last_str)
if !@connected
if last_str
print_status("The service may have crashed: iteration:#{cnt - 1} len=#{len} uri=''#{last_str}'' error=#{last_err}")
else
print_status("Could not connect to the service: #{last_err}")
end
return
break
end
last_str = str
@@ -3,23 +3,32 @@
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'English'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Fuzzer
def initialize(info = {})
super(update_info(info,
super(
update_info(
info,
'Name' => 'HTTP GET Request URI Fuzzer (Fuzzer Strings)',
'Description' => %q{
This module sends a series of HTTP GET request with malicious URIs.
},
'Author' => [ 'nullthreat' ],
'License' => MSF_LICENSE
))
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SERVICE_DOWN],
'SideEffects' => [],
'Reliability' => []
}
)
)
register_options([
Opt::RPORT(80),
OptString.new("VHOST", [false, "The virtual host name to use in requests"]),
OptString.new("URIBASE", [true, "The base URL to use for the request fuzzer", "/"])
OptString.new('VHOST', [false, 'The virtual host name to use in requests']),
OptString.new('URIBASE', [true, 'The base URL to use for the request fuzzer', '/'])
])
end
@@ -51,18 +60,18 @@ class MetasploitModule < Msf::Auxiliary
end
begin
r = do_http_get(uri,:timeout => 0.50)
do_http_get(uri, timeout: 0.50)
rescue ::Interrupt
print_status("Exiting on interrupt: iteration #{cnt} using #{@last_fuzzer_input}")
raise $!
rescue ::Exception => e
raise $ERROR_INFO
rescue StandardError => e
last_err = e
ensure
disconnect
end
if(not @connected)
if(last_str)
if !@connected
if last_str
print_status("The service may have crashed: iteration:#{cnt - 1} method=#{last_inp} uri=''#{last_str}'' error=#{last_err}")
else
print_status("Could not connect to the service: #{last_err}")
@@ -13,7 +13,7 @@ class MetasploitModule < Msf::Auxiliary
def initialize
super(
'Name' => 'NTP Protocol Fuzzer',
'Description' => %q(
'Description' => %q{
A simplistic fuzzer for the Network Time Protocol that sends the
following probes to understand NTP and look for anomalous NTP behavior:
@@ -35,9 +35,14 @@ class MetasploitModule < Msf::Auxiliary
* Warn if the "mode" (if applicable) doesn't align with what we expect,
* Filter out the 12-byte mode 6 unsupported opcode errors.
* Fuzz the control message payload offset/size/etc. There be bugs
),
},
'Author' => 'Jon Hart <jon_hart[at]rapid7.com>',
'License' => MSF_LICENSE
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SERVICE_DOWN],
'SideEffects' => [],
'Reliability' => []
}
)
register_options(
@@ -45,7 +50,8 @@ class MetasploitModule < Msf::Auxiliary
Opt::RPORT(123),
OptInt.new('SLEEP', [true, 'Sleep for this many ms between requests', 0]),
OptInt.new('WAIT', [true, 'Wait this many ms for responses', 250])
])
]
)
register_advanced_options(
[
@@ -54,7 +60,8 @@ class MetasploitModule < Msf::Auxiliary
OptString.new('MODE_6_OPERATIONS', [false, 'Mode 6 operations to fuzz (csv)']),
OptString.new('MODE_7_IMPLEMENTATIONS', [false, 'Mode 7 implementations to fuzz (csv)']),
OptString.new('MODE_7_REQUEST_CODES', [false, 'Mode 7 request codes to fuzz (csv)'])
])
]
)
end
def sleep_time
@@ -66,9 +73,9 @@ class MetasploitModule < Msf::Auxiliary
const_name = thing.to_sym
var_name = thing.downcase
if datastore[thing]
instance_variable_set("@#{var_name}", datastore[thing].split(/[^\d]/).select { |v| !v.empty? }.map { |v| v.to_i })
instance_variable_set("@#{var_name}", datastore[thing].split(/[^\d]/).reject(&:empty?).map(&:to_i))
unsupported_things = instance_variable_get("@#{var_name}") - Rex::Proto::NTP.const_get(const_name)
fail "Unsupported #{thing}: #{unsupported_things}" unless unsupported_things.empty?
raise "Unsupported #{thing}: #{unsupported_things}" unless unsupported_things.empty?
else
instance_variable_set("@#{var_name}", Rex::Proto::NTP.const_get(const_name))
end
@@ -196,6 +203,7 @@ class MetasploitModule < Msf::Auxiliary
request = request.to_binary_s if request.respond_to?('to_binary_s')
responses.select! { |r| r[1] }
return if responses.empty?
responses.each do |response|
data = response[0]
descriptions << Rex::Proto::NTP.describe(data)
@@ -3,20 +3,29 @@
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'English'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Fuzzer
def initialize(info = {})
super(update_info(info,
super(
update_info(
info,
'Name' => 'SMB Negotiate SMB2 Dialect Corruption',
'Description' => %q{
This module sends a series of SMB negotiate requests that advertise a
SMB2 dialect with corrupted bytes.
},
'Author' => [ 'hdm' ],
'License' => MSF_LICENSE
))
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SERVICE_DOWN],
'SideEffects' => [],
'Reliability' => []
}
)
)
register_options([
Opt::RPORT(445),
OptInt.new('MAXDEPTH', [false, 'Specify a maximum byte depth to test'])
@@ -52,19 +61,19 @@ class MetasploitModule < Msf::Auxiliary
end
begin
r = do_smb_negotiate(str, 0.25)
do_smb_negotiate(str, 0.25)
rescue ::Interrupt
print_status("Exiting on interrupt: iteration #{cnt} using #{@last_fuzzer_input}")
raise $!
rescue ::Exception => e
raise $ERROR_INFO
rescue StandardError => e
last_err = e
ensure
disconnect
end
if(not @connected)
if(last_str)
print_status("The service may have crashed: iteration:#{cnt-1} method=#{last_inp} string=#{last_str.unpack("H*")[0]} error=#{last_err}")
if !@connected
if last_str
print_status("The service may have crashed: iteration:#{cnt - 1} method=#{last_inp} string=#{last_str.unpack('H*')[0]} error=#{last_err}")
else
print_status("Could not connect to the service: #{last_err}")
end
@@ -3,28 +3,37 @@
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'English'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::SMB::Client
include Msf::Auxiliary::Fuzzer
def initialize(info = {})
super(update_info(info,
super(
update_info(
info,
'Name' => 'SMB Create Pipe Request Fuzzer',
'Description' => %q{
This module sends a series of SMB create pipe
requests using malicious strings.
},
'Author' => [ 'hdm' ],
'License' => MSF_LICENSE
))
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SERVICE_DOWN],
'SideEffects' => [],
'Reliability' => []
}
)
)
end
def do_smb_create(pkt,opts={})
def do_smb_create(pkt, _opts = {})
@connected = false
connect
smb_login
@connected = true
smb_create("\\" + pkt)
smb_create('\\' + pkt)
end
def run
@@ -45,16 +54,16 @@ class MetasploitModule < Msf::Auxiliary
do_smb_create(str, 0.25)
rescue ::Interrupt
print_status("Exiting on interrupt: iteration #{cnt} using #{@last_fuzzer_input}")
raise $!
rescue ::Exception => e
raise $ERROR_INFO
rescue StandardError => e
last_err = e
ensure
disconnect
end
if(not @connected)
if(last_str)
print_status("The service may have crashed: iteration:#{cnt-1} method=#{last_inp} string=#{last_str.unpack("H*")[0]} error=#{last_err}")
if !@connected
if last_str
print_status("The service may have crashed: iteration:#{cnt - 1} method=#{last_inp} string=#{last_str.unpack('H*')[0]} error=#{last_err}")
else
print_status("Could not connect to the service: #{last_err}")
end
@@ -3,22 +3,31 @@
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'English'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::SMB::Client
include Msf::Auxiliary::Fuzzer
def initialize(info = {})
super(update_info(info,
super(
update_info(
info,
'Name' => 'SMB Create Pipe Request Corruption',
'Description' => %q{
This module sends a series of SMB create pipe requests with corrupted bytes.
},
'Author' => [ 'hdm' ],
'License' => MSF_LICENSE
))
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SERVICE_DOWN],
'SideEffects' => [],
'Reliability' => []
}
)
)
register_options([
OptInt.new('MAXDEPTH', [false, 'Specify a maximum byte depth to test']),
OptString.new('SMBPIPE', [true, 'Specify the pipe name to corrupt', "\\BROWSER"])
OptString.new('SMBPIPE', [true, 'Specify the pipe name to corrupt', '\\BROWSER'])
])
deregister_options('SMB::ProtocolVersion')
@@ -35,7 +44,6 @@ class MetasploitModule < Msf::Auxiliary
end
def run
# Connect in order to get the server-assigned user-id/tree-id
connect(versions: [1])
smb_login
@@ -61,19 +69,19 @@ class MetasploitModule < Msf::Auxiliary
end
begin
r = do_smb_login(str, 0.25)
do_smb_login(str, 0.25)
rescue ::Interrupt
print_status("Exiting on interrupt: iteration #{cnt} using #{@last_fuzzer_input}")
raise $!
rescue ::Exception => e
raise $ERROR_INFO
rescue StandardError => e
last_err = e
ensure
disconnect
end
if(not @connected)
if(last_str)
print_status("The service may have crashed: iteration:#{cnt-1} method=#{last_inp} string=#{last_str.unpack("H*")[0]} error=#{last_err}")
if !@connected
if last_str
print_status("The service may have crashed: iteration:#{cnt - 1} method=#{last_inp} string=#{last_str.unpack('H*')[0]} error=#{last_err}")
else
print_status("Could not connect to the service: #{last_err}")
end
@@ -86,13 +94,12 @@ class MetasploitModule < Msf::Auxiliary
end
def make_smb_create
filename = datastore['SMBPIPE']
disposition = 1
impersonation = 2
pkt = Rex::Proto::SMB::Constants::SMB_CREATE_PKT.make_struct
self.simple.client.smb_defaults(pkt['Payload']['SMB'])
simple.client.smb_defaults(pkt['Payload']['SMB'])
pkt['Payload']['SMB'].v['Command'] = Rex::Proto::SMB::Constants::SMB_COM_NT_CREATE_ANDX
pkt['Payload']['SMB'].v['Flags1'] = 0x18
@@ -3,19 +3,28 @@
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'English'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Fuzzer
def initialize(info = {})
super(update_info(info,
super(
update_info(
info,
'Name' => 'SMB Negotiate Dialect Corruption',
'Description' => %q{
This module sends a series of SMB negotiate requests with corrupted bytes
},
'Author' => [ 'hdm' ],
'License' => MSF_LICENSE
))
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SERVICE_DOWN],
'SideEffects' => [],
'Reliability' => []
}
)
)
register_options([
Opt::RPORT(445),
OptInt.new('MAXDEPTH', [false, 'Specify a maximum byte depth to test'])
@@ -51,19 +60,19 @@ class MetasploitModule < Msf::Auxiliary
end
begin
r = do_smb_negotiate(str, 0.25)
do_smb_negotiate(str, 0.25)
rescue ::Interrupt
print_status("Exiting on interrupt: iteration #{cnt} using #{@last_fuzzer_input}")
raise $!
rescue ::Exception => e
raise $ERROR_INFO
rescue StandardError => e
last_err = e
ensure
disconnect
end
if(not @connected)
if(last_str)
print_status("The service may have crashed: iteration:#{cnt-1} method=#{last_inp} string=#{last_str.unpack("H*")[0]} error=#{last_err}")
if !@connected
if last_str
print_status("The service may have crashed: iteration:#{cnt - 1} method=#{last_inp} string=#{last_str.unpack('H*')[0]} error=#{last_err}")
else
print_status("Could not connect to the service: #{last_err}")
end
@@ -3,20 +3,29 @@
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'English'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::SMB::Client
include Msf::Auxiliary::Fuzzer
def initialize(info = {})
super(update_info(info,
super(
update_info(
info,
'Name' => 'SMB NTLMv1 Login Request Corruption',
'Description' => %q{
This module sends a series of SMB login requests using
the NTLMv1 protocol with corrupted bytes.
},
'Author' => [ 'hdm' ],
'License' => MSF_LICENSE
))
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SERVICE_DOWN],
'SideEffects' => [],
'Reliability' => []
}
)
)
register_options([
Opt::RPORT(445),
OptInt.new('MAXDEPTH', [false, 'Specify a maximum byte depth to test'])
@@ -55,19 +64,19 @@ class MetasploitModule < Msf::Auxiliary
end
begin
r = do_smb_login(str, 0.25)
do_smb_login(str, 0.25)
rescue ::Interrupt
print_status("Exiting on interrupt: iteration #{cnt} using #{@last_fuzzer_input}")
raise $!
rescue ::Exception => e
raise $ERROR_INFO
rescue StandardError => e
last_err = e
ensure
disconnect
end
if(not @connected)
if(last_str)
print_status("The service may have crashed: iteration:#{cnt-1} method=#{last_inp} string=#{last_str.unpack("H*")[0]} error=#{last_err}")
if !@connected
if last_str
print_status("The service may have crashed: iteration:#{cnt - 1} method=#{last_inp} string=#{last_str.unpack('H*')[0]} error=#{last_err}")
else
print_status("Could not connect to the service: #{last_err}")
end
@@ -80,11 +89,10 @@ class MetasploitModule < Msf::Auxiliary
end
def make_smb_login
user = "USER"
domain = "DOMAIN"
hash_lm = Rex::Proto::NTLM::Crypt.lanman_des("X", "X" * 8)
hash_nt = Rex::Proto::NTLM::Crypt.ntlm_md4("X", "X" * 8)
user = 'USER'
domain = 'DOMAIN'
hash_lm = Rex::Proto::NTLM::Crypt.lanman_des('X', 'X' * 8)
hash_nt = Rex::Proto::NTLM::Crypt.ntlm_md4('X', 'X' * 8)
data = ''
data << hash_lm
@@ -3,23 +3,32 @@
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'English'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::SMB::Client
include Msf::Auxiliary::Fuzzer
def initialize(info = {})
super(update_info(info,
super(
update_info(
info,
'Name' => 'SMB Tree Connect Request Fuzzer',
'Description' => %q{
This module sends a series of SMB tree connect
requests using malicious strings.
},
'Author' => [ 'hdm' ],
'License' => MSF_LICENSE
))
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SERVICE_DOWN],
'SideEffects' => [],
'Reliability' => []
}
)
)
end
def do_smb_connect(pkt,opts={})
def do_smb_connect(pkt, _opts = {})
@connected = false
connect
simple.login(
@@ -51,16 +60,16 @@ class MetasploitModule < Msf::Auxiliary
do_smb_connect(str, 0.25)
rescue ::Interrupt
print_status("Exiting on interrupt: iteration #{cnt} using #{@last_fuzzer_input}")
raise $!
rescue ::Exception => e
raise $ERROR_INFO
rescue StandardError => e
last_err = e
ensure
disconnect
end
if(not @connected)
if(last_str)
print_status("The service may have crashed: iteration:#{cnt-1} method=#{last_inp} string=#{last_str.unpack("H*")[0]} error=#{last_err}")
if !@connected
if last_str
print_status("The service may have crashed: iteration:#{cnt - 1} method=#{last_inp} string=#{last_str.unpack('H*')[0]} error=#{last_err}")
else
print_status("Could not connect to the service: #{last_err}")
end
@@ -3,22 +3,31 @@
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'English'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::SMB::Client
include Msf::Auxiliary::Fuzzer
def initialize(info = {})
super(update_info(info,
super(
update_info(
info,
'Name' => 'SMB Tree Connect Request Corruption',
'Description' => %q{
This module sends a series of SMB tree connect requests with corrupted bytes.
},
'Author' => [ 'hdm' ],
'License' => MSF_LICENSE
))
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SERVICE_DOWN],
'SideEffects' => [],
'Reliability' => []
}
)
)
register_options([
OptInt.new('MAXDEPTH', [false, 'Specify a maximum byte depth to test']),
OptString.new('SMBTREE', [true, 'Specify the tree name to corrupt', "\\\\SERVER\\IPC$"])
OptString.new('SMBTREE', [true, 'Specify the tree name to corrupt', '\\\\SERVER\\IPC$'])
])
deregister_options('SMB::ProtocolVersion')
@@ -40,7 +49,6 @@ class MetasploitModule < Msf::Auxiliary
end
def run
# Connect in order to get the server-assigned user-id
connect(versions: [1])
smb_login
@@ -66,19 +74,19 @@ class MetasploitModule < Msf::Auxiliary
end
begin
r = do_smb_tree(str, 0.25)
do_smb_tree(str, 0.25)
rescue ::Interrupt
print_status("Exiting on interrupt: iteration #{cnt} using #{@last_fuzzer_input}")
raise $!
rescue ::Exception => e
raise $ERROR_INFO
rescue StandardError => e
last_err = e
ensure
disconnect
end
if(not @connected)
if(last_str)
print_status("The service may have crashed: iteration:#{cnt-1} method=#{last_inp} string=#{last_str.unpack("H*")[0]} error=#{last_err}")
if !@connected
if last_str
print_status("The service may have crashed: iteration:#{cnt - 1} method=#{last_inp} string=#{last_str.unpack('H*')[0]} error=#{last_err}")
else
print_status("Could not connect to the service: #{last_err}")
end
@@ -93,7 +101,7 @@ class MetasploitModule < Msf::Auxiliary
def make_smb_tree
share = datastore['SMBTREE']
pass = ''
data = [ pass, share, '?????' ].collect{ |a| a + "\x00" }.join('');
data = [ pass, share, '?????' ].collect { |a| a + "\x00" }.join('')
pkt = Rex::Proto::SMB::Constants::SMB_TREE_CONN_PKT.make_struct
simple.client.smb_defaults(pkt['Payload']['SMB'])
+48 -47
View File
@@ -8,6 +8,7 @@
# It allows to respect the order or just throw everything at it....
##
require 'English'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Smtp
include Msf::Auxiliary::Fuzzer
@@ -17,20 +18,25 @@ class MetasploitModule < Msf::Auxiliary
super(
'Name' => 'SMTP Simple Fuzzer',
'Description' => 'SMTP Simple Fuzzer',
'References' =>
[
'References' => [
['URL', 'http://www.ietf.org/rfc/rfc2821.txt'],
],
'Author' => 'justme',
'License' => MSF_LICENSE
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SERVICE_DOWN],
'SideEffects' => [],
'Reliability' => []
}
)
register_options([
Opt::RPORT(25),
OptInt.new("STARTLEN", [true, "Length of the string - start number", 100] ),
OptInt.new("INTERACTIONS", [false, "Number of interactions to run", 100] ),
OptBool.new("RESPECTORDER", [false, "Respect order of commands", true] ),
OptEnum.new("CMD", [true,"Command to fuzzer",'EHLO',
OptInt.new('STARTLEN', [true, 'Length of the string - start number', 100]),
OptInt.new('INTERACTIONS', [false, 'Number of interactions to run', 100]),
OptBool.new('RESPECTORDER', [false, 'Respect order of commands', true]),
OptEnum.new('CMD', [
true, 'Command to fuzzer', 'EHLO',
[
'EHLO',
'HELO',
@@ -39,15 +45,15 @@ class MetasploitModule < Msf::Auxiliary
'DATA',
'VRFY',
'EXPN'
], 'EHLO'])
], 'EHLO'
])
])
end
def smtp_send(data='', con=true)
begin
def smtp_send(data = '', con: true)
@result = ''
@coderesult = ''
if (con)
if con
@connected = false
connect
end
@@ -55,13 +61,11 @@ class MetasploitModule < Msf::Auxiliary
sock.put(data)
@result = sock.get_once
@codresult = @result[0..2]
rescue ::Exception => e
rescue StandardError => e
print_error(e.to_s)
end
end
def run_host(ip)
begin
def run_host(_ip)
last_str = nil
last_inp = nil
last_err = nil
@@ -75,76 +79,74 @@ class MetasploitModule < Msf::Auxiliary
cmd = datastore['CMD']
begin
if (datastore['RESPECTORDER'])
if datastore['RESPECTORDER']
case cmd
when "HELO", "EHLO", "VRFY", "EXPN"
c = datastore['CMD'] + " " + str + "\r\n"
smtp_send(c,true)
when 'HELO', 'EHLO', 'VRFY', 'EXPN'
c = datastore['CMD'] + ' ' + str + "\r\n"
smtp_send(c)
# print_status(c)
disconnect
when "MAILFROM"
when 'MAILFROM'
c = "EHLO localhost\r\n"
smtp_send(c,true)
smtp_send(c)
# print_status(c)
c="MAIL FROM:<" + str + ">\r\n"
smtp_send(c,false)
c = 'MAIL FROM:<' + str + ">\r\n"
smtp_send(c)
disconnect
# print_status(c)
when "RCPTTO"
when 'RCPTTO'
c = "EHLO localhost\r\n"
smtp_send(c,true)
smtp_send(c)
# print_status(c)
c="MAIL FROM:<" + datastore['MAILFROM'] + ">\r\n"
smtp_send(c,false)
c = 'MAIL FROM:<' + datastore['MAILFROM'] + ">\r\n"
smtp_send(c, con: false)
# print_status(c)
c="RCPT TO:<" + str + ">\r\n"
smtp_send(c,false)
c = 'RCPT TO:<' + str + ">\r\n"
smtp_send(c, con: false)
# print_status(c)
disconnect
when "DATA"
when 'DATA'
c = "EHLO localhost\r\n"
smtp_send(c,true)
smtp_send(c)
# print_status(c)
c="MAIL FROM:<" + datastore['MAILFROM'] + ">\r\n"
smtp_send(c,false)
c = 'MAIL FROM:<' + datastore['MAILFROM'] + ">\r\n"
smtp_send(c, con: false)
# print_status(c)
c="RCPT TO:<" + datastore['MAILTO'] + ">\r\n"
smtp_send(c,false)
c = 'RCPT TO:<' + datastore['MAILTO'] + ">\r\n"
smtp_send(c, con: false)
# print_status(c)
c = "DATA \r\n"
smtp_send(c,false)
smtp_send(c, con: false)
c = str + "\r\n.\r\n"
smtp_send(c,false)
smtp_send(c, con: false)
# print_status(c)
disconnect
end
else
c = datastore['CMD'] + " " + str + "\r\n"
smtp_send(c,true)
c = datastore['CMD'] + ' ' + str + "\r\n"
smtp_send(c)
# print_status(c)
disconnect
end
print_status("Fuzzing with iteration #{interaction}\n #{@result}")
rescue ::Interrupt
print_status("Exiting on interrupt: iteration #{interaction} using string #{str}")
raise $!
rescue ::Exception => e
raise $ERROR_INFO
rescue StandardError => e
last_err = e
# ensure
# disconnect
end
if(not @connected)
if(last_str)
if !@connected
if last_str
print_status("The service may have crashed: iteration:#{interection - 1} String=''#{last_str}'' error=#{last_err}")
else
print_status("Could not connect to the service: #{last_err}")
end
return
break
end
last_str = str
@@ -152,4 +154,3 @@ class MetasploitModule < Msf::Auxiliary
end
end
end
end
@@ -3,19 +3,28 @@
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'English'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Fuzzer
def initialize(info = {})
super(update_info(info,
super(
update_info(
info,
'Name' => 'SSH Key Exchange Init Corruption',
'Description' => %q{
This module sends a series of SSH requests with a corrupted initial key exchange payload.
},
'Author' => [ 'hdm' ],
'License' => MSF_LICENSE
))
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SERVICE_DOWN],
'SideEffects' => [],
'Reliability' => []
}
)
)
register_options([
Opt::RPORT(22),
OptInt.new('MAXDEPTH', [false, 'Specify a maximum byte depth to test'])
@@ -28,7 +37,7 @@ class MetasploitModule < Msf::Auxiliary
@connected = true
@banner = sock.get_once(-1, opts[:banner_timeout])
return if not @banner
return if !@banner
sock.put("SSH-2.0-OpenSSH_5.1p1 Debian-5ubuntu1\r\n")
sock.put(pkt)
@@ -56,27 +65,27 @@ class MetasploitModule < Msf::Auxiliary
end
begin
r = do_ssh_kexinit(str,:banner_timeout => 5, :kex_timeout => 0.5)
do_ssh_kexinit(str, banner_timeout: 5, kex_timeout: 0.5)
rescue ::Interrupt
print_status("Exiting on interrupt: iteration #{cnt} using #{@last_fuzzer_input}")
raise $!
rescue ::Exception => e
raise $ERROR_INFO
rescue StandardError => e
last_err = e
ensure
disconnect
end
if(not @connected)
if(last_str)
print_status("The service may have crashed: iteration:#{cnt-1} method=#{last_inp} string=#{last_str.unpack("H*")[0]} error=#{last_err}")
if !@connected
if last_str
print_status("The service may have crashed: iteration:#{cnt - 1} 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
if(not @banner)
print_status("The service may have crashed (no banner): iteration:#{cnt-1} method=#{last_inp} string=#{last_str.to_s.unpack("H*")[0]} ")
if !@banner
print_status("The service may have crashed (no banner): iteration:#{cnt - 1} method=#{last_inp} string=#{last_str.to_s.unpack('H*')[0]} ")
return
end
@@ -86,7 +95,8 @@ class MetasploitModule < Msf::Auxiliary
end
def make_kex_init
[0x00, 0x00, 0x03, 0x14, 0x08, 0x14, 0xff, 0x9f,
[
0x00, 0x00, 0x03, 0x14, 0x08, 0x14, 0xff, 0x9f,
0xde, 0x5d, 0x5f, 0xb3, 0x07, 0x8f, 0x49, 0xa7,
0x79, 0x6a, 0x03, 0x3d, 0xaf, 0x55, 0x00, 0x00,
0x00, 0x7e, 0x64, 0x69, 0x66, 0x66, 0x69, 0x65,
@@ -184,6 +194,7 @@ class MetasploitModule < Msf::Auxiliary
0x6d, 0x2c, 0x7a, 0x6c, 0x69, 0x62, 0x2c, 0x6e,
0x6f, 0x6e, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00].pack("C*")
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
].pack('C*')
end
end
+24 -16
View File
@@ -3,19 +3,28 @@
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'English'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Fuzzer
def initialize(info = {})
super(update_info(info,
super(
update_info(
info,
'Name' => 'SSH 1.5 Version Fuzzer',
'Description' => %q{
This module sends a series of SSH requests with malicious version strings.
},
'Author' => [ 'hdm' ],
'License' => MSF_LICENSE
))
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SERVICE_DOWN],
'SideEffects' => [],
'Reliability' => []
}
)
)
register_options([
Opt::RPORT(22)
])
@@ -27,7 +36,8 @@ class MetasploitModule < Msf::Auxiliary
@connected = true
@banner = sock.get_once(-1, opts[:banner_timeout])
return if not @banner
return if !@banner
sock.put("#{pkt}\r\n")
end
@@ -36,40 +46,38 @@ class MetasploitModule < Msf::Auxiliary
last_inp = nil
last_err = nil
ver = make_ssh_version_base
make_ssh_version_base
cnt = 0
fuzz_strings do |str|
cnt += 1
pkt = ver + str
if (cnt % 100 == 0)
print_status("Fuzzing with iteration #{cnt} using #{@last_fuzzer_input}")
end
begin
r = do_ssh_version(str,:banner_timeout => 5)
do_ssh_version(str, banner_timeout: 5)
rescue ::Interrupt
print_status("Exiting on interrupt: iteration #{cnt} using #{@last_fuzzer_input}")
raise $!
rescue ::Exception => e
raise $ERROR_INFO
rescue StandardError => e
last_err = e
ensure
disconnect
end
if(not @connected)
if(last_str)
print_status("The service may have crashed: iteration:#{cnt-1} method=#{last_inp} string=#{last_str.unpack("H*")[0]} error=#{last_err}")
if !@connected
if last_str
print_status("The service may have crashed: iteration:#{cnt - 1} 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
if(not @banner)
print_status("The service may have crashed (no banner): iteration:#{cnt-1} method=#{last_inp} string=#{last_str.unpack("H*")[0]} ")
if !@banner
print_status("The service may have crashed (no banner): iteration:#{cnt - 1} method=#{last_inp} string=#{last_str.unpack('H*')[0]} ")
return
end
@@ -79,6 +87,6 @@ class MetasploitModule < Msf::Auxiliary
end
def make_ssh_version_base
"SSH-1.5-"
'SSH-1.5-'
end
end
+24 -16
View File
@@ -3,19 +3,28 @@
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'English'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Fuzzer
def initialize(info = {})
super(update_info(info,
super(
update_info(
info,
'Name' => 'SSH 2.0 Version Fuzzer',
'Description' => %q{
This module sends a series of SSH requests with malicious version strings.
},
'Author' => [ 'hdm' ],
'License' => MSF_LICENSE
))
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SERVICE_DOWN],
'SideEffects' => [],
'Reliability' => []
}
)
)
register_options([
Opt::RPORT(22)
])
@@ -27,7 +36,8 @@ class MetasploitModule < Msf::Auxiliary
@connected = true
@banner = sock.get_once(-1, opts[:banner_timeout])
return if not @banner
return if !@banner
sock.put("#{pkt}\r\n")
end
@@ -36,40 +46,38 @@ class MetasploitModule < Msf::Auxiliary
last_inp = nil
last_err = nil
ver = make_ssh_version_base
make_ssh_version_base
cnt = 0
fuzz_strings do |str|
cnt += 1
pkt = ver + str
if (cnt % 100 == 0)
print_status("Fuzzing with iteration #{cnt} using #{@last_fuzzer_input}")
end
begin
r = do_ssh_version(str,:banner_timeout => 5)
do_ssh_version(str, banner_timeout: 5)
rescue ::Interrupt
print_status("Exiting on interrupt: iteration #{cnt} using #{@last_fuzzer_input}")
raise $!
rescue ::Exception => e
raise $ERROR_INFO
rescue StandardError => e
last_err = e
ensure
disconnect
end
if(not @connected)
if(last_str)
print_status("The service may have crashed: iteration:#{cnt-1} method=#{last_inp} string=#{last_str.unpack("H*")[0]} error=#{last_err}")
if !@connected
if last_str
print_status("The service may have crashed: iteration:#{cnt - 1} 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
if(not @banner)
print_status("The service may have crashed (no banner): iteration:#{cnt-1} method=#{last_inp} string=#{last_str.unpack("H*")[0]} ")
if !@banner
print_status("The service may have crashed (no banner): iteration:#{cnt - 1} method=#{last_inp} string=#{last_str.unpack('H*')[0]} ")
return
end
@@ -79,6 +87,6 @@ class MetasploitModule < Msf::Auxiliary
end
def make_ssh_version_base
"SSH-2.0-"
'SSH-2.0-'
end
end
@@ -3,19 +3,28 @@
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'English'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Fuzzer
def initialize(info = {})
super(update_info(info,
super(
update_info(
info,
'Name' => 'SSH Version Corruption',
'Description' => %q{
This module sends a series of SSH requests with a corrupted version string
},
'Author' => [ 'hdm' ],
'License' => MSF_LICENSE
))
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SERVICE_DOWN],
'SideEffects' => [],
'Reliability' => []
}
)
)
register_options([
Opt::RPORT(22),
OptInt.new('MAXDEPTH', [false, 'Specify a maximum byte depth to test'])
@@ -28,7 +37,8 @@ class MetasploitModule < Msf::Auxiliary
@connected = true
@banner = sock.get_once(-1, opts[:banner_timeout])
return if not @banner
return if !@banner
sock.put("#{pkt}\r\n")
end
@@ -53,27 +63,27 @@ class MetasploitModule < Msf::Auxiliary
end
begin
r = do_ssh_version(str,:banner_timeout => 5)
do_ssh_version(str, banner_timeout: 5)
rescue ::Interrupt
print_status("Exiting on interrupt: iteration #{cnt} using #{@last_fuzzer_input}")
raise $!
rescue ::Exception => e
raise $ERROR_INFO
rescue StandardError => e
last_err = e
ensure
disconnect
end
if(not @connected)
if(last_str)
print_status("The service may have crashed: iteration:#{cnt-1} method=#{last_inp} string=#{last_str.unpack("H*")[0]} error=#{last_err}")
if !@connected
if last_str
print_status("The service may have crashed: iteration:#{cnt - 1} 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
if(not @banner)
print_status("The service may have crashed (no banner): iteration:#{cnt-1} method=#{last_inp} string=#{last_str.unpack("H*")[0]} ")
if !@banner
print_status("The service may have crashed (no banner): iteration:#{cnt - 1} method=#{last_inp} string=#{last_str.unpack('H*')[0]} ")
return
end
@@ -83,6 +93,6 @@ class MetasploitModule < Msf::Auxiliary
end
def make_ssh_version
"SSH-2.0-OpenSSH_5.1p1 Debian-5ubuntu1"
'SSH-2.0-OpenSSH_5.1p1 Debian-5ubuntu1'
end
end
@@ -3,27 +3,34 @@
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'English'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::MSSQL
include Msf::Auxiliary::Fuzzer
def initialize(info = {})
super(update_info(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
))
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SERVICE_DOWN],
'SideEffects' => [],
'Reliability' => []
}
)
)
end
# A copy of the mssql_login method with the ability to overload each option
def make_login(opts = {})
pkt = ""
idx = 0
db = ""
pkt = ''
db = ''
pkt << [
0x00000000, # Dummy size
@@ -40,11 +47,10 @@ class MetasploitModule < Msf::Auxiliary
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) )
cname = Rex::Text.to_unicode(opts[:cname] || Rex::Text.rand_text_alpha(1..8))
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(1..8))
sname = Rex::Text.to_unicode(opts[:sname] || rhost)
dname = Rex::Text.to_unicode(opts[:dname] || db)
@@ -73,7 +79,7 @@ class MetasploitModule < Msf::Auxiliary
pkt << [idx, 0].pack('vv')
pkt << [idx, dname.length / 2].pack('vv')
idx += dname.length
dname.length
# The total length has to be embedded twice more here
pkt << [
@@ -105,13 +111,13 @@ class MetasploitModule < Msf::Auxiliary
def do_login(pkt, opts = {})
@connected = false
disconnect if self.sock
disconnect if sock
connect
@connected = true
resp = mssql_send_recv(pkt, opts[:timeout])
info = {:errors => []}
info = { errors: [] }
info = mssql_parse_reply(resp, info)
info
end
@@ -131,19 +137,19 @@ class MetasploitModule < Msf::Auxiliary
end
begin
do_login(str,:timeout => 0.50)
do_login(str, timeout: 0.50)
rescue ::Interrupt
print_status("Exiting on interrupt: iteration #{cnt} using #{@last_fuzzer_input}")
raise $!
rescue ::Exception => e
raise $ERROR_INFO
rescue StandardError => 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}")
if !@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
@@ -3,32 +3,39 @@
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'English'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::MSSQL
include Msf::Auxiliary::Fuzzer
def initialize(info = {})
super(update_info(info,
super(
update_info(
info,
'Name' => 'TDS Protocol Login Request Username Fuzzer',
'Description' => %q{
This module sends a series of malformed TDS login requests.
},
'Author' => [ 'hdm' ],
'License' => MSF_LICENSE
))
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SERVICE_DOWN],
'SideEffects' => [],
'Reliability' => []
}
)
)
end
# A copy of the mssql_login method with the ability to overload each option
def do_login(opts = {})
@connected = false
disconnect if self.sock
disconnect if sock
connect
@connected = true
pkt = ""
idx = 0
db = ""
pkt = ''
db = ''
pkt << [
0x00000000, # Dummy size
@@ -45,11 +52,10 @@ class MetasploitModule < Msf::Auxiliary
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) )
cname = Rex::Text.to_unicode(opts[:cname] || Rex::Text.rand_text_alpha(1..8))
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(1..8))
sname = Rex::Text.to_unicode(opts[:sname] || rhost)
dname = Rex::Text.to_unicode(opts[:dname] || db)
@@ -78,7 +84,6 @@ class MetasploitModule < Msf::Auxiliary
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 << [
@@ -107,7 +112,7 @@ class MetasploitModule < Msf::Auxiliary
resp = mssql_send_recv(pkt, opts[:timeout])
info = {:errors => []}
info = { errors: [] }
info = mssql_parse_reply(resp, info)
info
end
@@ -121,6 +126,7 @@ class MetasploitModule < Msf::Auxiliary
fuzz_strings do |str|
# capped at 16-bit lengths
next if str.length > 65535
cnt += 1
if (cnt % 100 == 0)
@@ -128,19 +134,19 @@ class MetasploitModule < Msf::Auxiliary
end
begin
do_login(:uname => str, :timeout => 0.50)
do_login(uname: str, timeout: 0.50)
rescue ::Interrupt
print_status("Exiting on interrupt: iteration #{cnt} using #{@last_fuzzer_input}")
raise $!
rescue ::Exception => e
raise $ERROR_INFO
rescue StandardError => 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}")
if !@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