Skip to content

Commit 2a18ea0

Browse files
jhart-r7Brian Patterson
authored andcommitted
Initial commit of generic module for detecting UDP amplification vulnerabilities
1 parent f7f28a0 commit 2a18ea0

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
##
2+
# This module requires Metasploit: http://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
8+
class MetasploitModule < Msf::Auxiliary
9+
include Msf::Auxiliary::DRDoS
10+
include Msf::Auxiliary::Report
11+
include Msf::Auxiliary::UDPScanner
12+
13+
def initialize
14+
super(
15+
'Name' => 'UDP Amplification Scanner',
16+
'Description' => 'Detect UDP endpoints with UDP amplification vulnerabilities',
17+
'Author' => 'Jon Hart <jon_hart[at]rapid7.com>',
18+
'License' => MSF_LICENSE,
19+
'References' =>
20+
[
21+
['URL', 'https://www.us-cert.gov/ncas/alerts/TA14-017A']
22+
]
23+
)
24+
25+
register_options(
26+
[
27+
OptString.new('PORTS', [true, 'Ports to probe', '1-1024']),
28+
OptString.new('PROBE', [false, 'UDP payload/probe to send. Unset for an empty UDP datagram, or the `file://` resource to get content from a local file', 'test'])
29+
]
30+
)
31+
32+
# RPORT is unused in this scanner module because it supports multiple ports
33+
deregister_options('RPORT')
34+
end
35+
36+
def setup
37+
super
38+
39+
unless (@ports = Rex::Socket.portspec_crack(datastore['PORTS']))
40+
fail_with(Failure::BadConfig, "Unable to extract list of ports from #{datastore['PORTS']}")
41+
end
42+
43+
@probe = datastore['PROBE'] ? datastore['PROBE'] : ''
44+
end
45+
46+
def scanner_prescan(batch)
47+
print_status("Sending #{@probe.length}-byte probes to #{@ports.length} port(s) on #{batch[0]}->#{batch[-1]} (#{batch.length} hosts)")
48+
@results ||= {}
49+
end
50+
51+
def scan_host(ip)
52+
@ports.each do |port|
53+
scanner_send(@probe, ip, port)
54+
end
55+
end
56+
57+
# Called for each response packet, overriding UDPScanner's so that we can
58+
# store all responses on a per-host, per-port basis
59+
def scanner_process(data, shost, sport)
60+
@results[shost] ||= {}
61+
@results[shost][sport] ||= []
62+
@results[shost][sport] << data
63+
end
64+
65+
def scanner_postscan(batch)
66+
batch.each do |shost|
67+
next unless @results.key?(shost)
68+
@results[shost].each_pair do |sport, responses|
69+
report_service(host: shost, port: sport, proto: 'udp', info: responses.inspect, state: 'open')
70+
vulnerable, proof = prove_amplification(@probe => responses)
71+
next unless vulnerable
72+
print_good("#{shost}:#{sport} - susceptible to UDP amplification: #{proof}")
73+
report_vuln(
74+
host: shost,
75+
port: sport,
76+
proto: 'udp',
77+
name: 'UDP amplification',
78+
refs: references
79+
)
80+
end
81+
end
82+
end
83+
end

0 commit comments

Comments
 (0)