Skip to content

Commit 8be481f

Browse files
committed
Land rapid7#2681, @mcantoni and @todb-r7's support for chargen
2 parents 7b80fad + 12efa99 commit 8be481f

File tree

3 files changed

+105
-0
lines changed

3 files changed

+105
-0
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
##
2+
# This module requires Metasploit: http//metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
7+
require 'msf/core'
8+
9+
class Metasploit3 < Msf::Auxiliary
10+
11+
include Msf::Auxiliary::Scanner
12+
include Msf::Auxiliary::Report
13+
include Msf::Exploit::Remote::Udp
14+
15+
def initialize
16+
super(
17+
'Name' => 'Identifies Open Chargen Service Checking The Answer.',
18+
'Description' => %q{
19+
Chargen is a debugging and measurement tool and a character
20+
generator service. A character generator service simply sends
21+
data without regard to the input.
22+
Chargen is susceptible to spoofing the source of transmissions
23+
as well as use in a reflection attack vector. The misuse of the
24+
testing features of the Chargen service may allow attackers to
25+
craft malicious network payloads and reflect them by spoofing
26+
the transmission source to effectively direct it to a target.
27+
This can result in traffic loops and service degradation with
28+
large amounts of network traffic.
29+
},
30+
'Author' => 'Matteo Cantoni <goony[at]nothink.org>',
31+
'License' => MSF_LICENSE,
32+
'References' =>
33+
[
34+
[ 'CVE', '1999-0103' ],
35+
[ 'URL', 'https://www.cert.be/pro/docs/chargensnmp-ddos-attacks-rise' ],
36+
[ 'URL', 'http://tools.ietf.org/html/rfc864' ],
37+
],
38+
'DisclosureDate' => 'Feb 08 1996')
39+
40+
register_options([
41+
Opt::RPORT(19)
42+
])
43+
44+
deregister_options('RHOST')
45+
end
46+
47+
def run_host(rhost)
48+
begin
49+
connect_udp
50+
pkt = Rex::Text.rand_text_alpha_lower(1)
51+
udp_sock.write(pkt)
52+
r = udp_sock.recvfrom(65535, 0.1)
53+
54+
if r and r[1]
55+
vprint_status("#{rhost}:#{rport} - Response: #{r[0].to_s}")
56+
res = r[0].to_s.strip
57+
if (res.match(/ABCDEFGHIJKLMNOPQRSTUVWXYZ/i) || res.match(/0123456789/))
58+
print_good("#{rhost}:#{rport} answers with #{res.length} bytes (headers + UDP payload)")
59+
report_service(:host => rhost, :port => rport, :name => "chargen", :info => res.length)
60+
end
61+
end
62+
rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused
63+
nil
64+
ensure
65+
disconnect_udp if self.udp_sock
66+
end
67+
end
68+
end

modules/auxiliary/scanner/discovery/udp_probe.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ def initialize
4646
@probes << 'probe_pkt_citrix'
4747
@probes << 'probe_pkt_pca_st'
4848
@probes << 'probe_pkt_pca_nq'
49+
@probes << 'probe_chargen'
4950

5051
end
5152

@@ -204,6 +205,11 @@ def parse_reply(pkt)
204205

205206
case pkt[2]
206207

208+
when 19
209+
app = 'chargen'
210+
return unless chargen_parse(pkt[0])
211+
@results[hkey] = true
212+
207213
when 53
208214
app = 'DNS'
209215
ver = nil
@@ -362,6 +368,13 @@ def db2disco_parse(data)
362368
"#{res[2]}_#{res[1]}"
363369
end
364370

371+
#
372+
# Validate a chargen packet.
373+
#
374+
def chargen_parse(data)
375+
data =~ /ABCDEFGHIJKLMNOPQRSTUVWXYZ|0123456789/i
376+
end
377+
365378
#
366379
# Validate this is truly Citrix ICA; returns true or false.
367380
#
@@ -397,6 +410,11 @@ def mssql_ping_parse(data)
397410
# The probe definitions
398411
#
399412

413+
def probe_chargen(ip)
414+
pkt = Rex::Text.rand_text_alpha_lower(1)
415+
return [pkt, 19]
416+
end
417+
400418
def probe_pkt_dns(ip)
401419
data = [rand(0xffff)].pack('n') +
402420
"\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00"+

modules/auxiliary/scanner/discovery/udp_sweep.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def initialize
4141
@probes << 'probe_pkt_citrix'
4242
@probes << 'probe_pkt_pca_st'
4343
@probes << 'probe_pkt_pca_nq'
44+
@probes << 'probe_chargen'
4445
end
4546

4647
def setup
@@ -153,6 +154,12 @@ def scanner_process(data, shost, sport)
153154

154155
case sport
155156

157+
when 19
158+
app = 'chargen'
159+
ver = nil
160+
return unless chargen_parse(data)
161+
@results[hkey] = true
162+
156163
when 53
157164
app = 'DNS'
158165
ver = nil
@@ -306,6 +313,13 @@ def scanner_process(data, shost, sport)
306313
print_status("Discovered #{app} on #{shost}:#{sport} (#{inf})")
307314
end
308315

316+
#
317+
# Validate a chargen packet.
318+
#
319+
def chargen_parse(data)
320+
data =~ /ABCDEFGHIJKLMNOPQRSTUVWXYZ|0123456789/i
321+
end
322+
309323
#
310324
# Parse a db2disco packet.
311325
#
@@ -349,6 +363,11 @@ def mssql_ping_parse(data)
349363
# The probe definitions
350364
#
351365

366+
def probe_chargen(ip)
367+
pkt = Rex::Text.rand_text_alpha_lower(1)
368+
return [pkt, 19]
369+
end
370+
352371
def probe_pkt_dns(ip)
353372
data = [rand(0xffff)].pack('n') +
354373
"\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00"+

0 commit comments

Comments
 (0)