Skip to content

Commit 00452b4

Browse files
committed
Gut admin functions from R7-2014-12 NTP modules
None of these are admin modules. All of that stuff should eventually go in auxiliary/admin
1 parent ed3ccdc commit 00452b4

File tree

5 files changed

+10
-289
lines changed

5 files changed

+10
-289
lines changed

modules/auxiliary/scanner/ntp/ntp_peer_list_dos.rb

Lines changed: 2 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,6 @@ def initialize
2727
'Author' => 'Jon Hart <jon_hart[at]rapid7.com>',
2828
'License' => MSF_LICENSE
2929
)
30-
31-
register_options(
32-
[
33-
OptBool.new('SHOW_PEERS', [false, 'Show peers', 'false'])
34-
], self.class)
3530
end
3631

3732
# Called for each IP in the batch
@@ -63,90 +58,21 @@ def scanner_prescan(batch)
6358

6459
# Called for each response packet
6560
def scanner_process(data, shost, sport)
66-
this_peer = "#{shost}:#{sport}"
67-
# sanity check that the reply is not overly large/small
68-
if data.length < 8
69-
print_error("#{this_peer} -- suspiciously small (#{data.length} bytes) NTP PEER_LIST response")
70-
return
71-
elsif data.length > 500
72-
print_error("#{this_peer} -- suspiciously large (#{data.length} bytes) NTP PEER_LIST response")
73-
return
74-
end
75-
76-
# try to parse this response, alerting and aborting if it is invalid
77-
response = Rex::Proto::NTP::NTPPrivate.new(data)
78-
unless contains_relevant_message?(response, @probes)
79-
print_error("#{this_peer} -- unexpected NTP PEER_LIST response: #{response.inspect}")
80-
return
81-
end
82-
83-
if response.error != 0
84-
vprint_status("#{this_peer} -- error #{response.error} response to NTP PEER_LIST request")
85-
return
86-
end
87-
88-
if response.record_size != 32 || response.record_count == 0 || response.record_count > 15
89-
print_error("#{this_peer} -- suspicious NTP PEER_LIST response with #{response.record_count} #{response.record_size}-byte entries: #{response.inspect}")
90-
return
91-
end
92-
93-
these_results = []
94-
response.records.each do |record|
95-
# TODO: Rex this
96-
# u_int32 addr; /* address of peer */
97-
# u_short port; /* port number of peer */
98-
# u_char hmode; /* mode for this peer */
99-
# u_char flags; /* flags (from above) */
100-
# u_int v6_flag; /* is this v6 or not */
101-
# u_int unused1; /* (unused) padding for addr6 */
102-
# struct in6_addr addr6; /* v6 address of peer */
103-
104-
src_addr4, src_port = record[0,6].unpack('Nn')
105-
is_v6 = record[8,4].unpack('N').first
106-
107-
if is_v6 == 0
108-
src_addr = Rex::Socket.addr_itoa(src_addr4)
109-
else
110-
# XXX: according to the struct, this should be record[16,16], but that doesn't work. Why?
111-
src_addr6_parts = record[12, 16].unpack("N*")
112-
src_addr6 = 0
113-
0.upto(3) do |off|
114-
src_addr6 = src_addr6 | src_addr6_parts[off]
115-
src_addr6 <<= 32
116-
end
117-
src_addr = Rex::Socket.addr_itoa(src_addr6, true)
118-
end
119-
these_results << [ src_addr, src_port ]
120-
if datastore['SHOW_LIST']
121-
print_status("#{this_peer} peers with #{src_addr}:#{src_port}")
122-
end
123-
end
124-
12561
@results[shost] ||= []
126-
@results[shost] << these_results
127-
62+
@results[shost] << Rex::Proto::NTP::NTPPrivate.new(data)
12863
end
12964

13065
# Called after the scan block
13166
def scanner_postscan(batch)
13267
@results.keys.each do |k|
13368
packets = @results[k]
134-
peers = packets.flatten(1)
135-
print_good("#{k}:#{rport} NTP PEER_LIST request permitted (#{packets.size} packets with #{peers.size} peers total)")
69+
# TODO: check to see if any of the responses are actually NTP before reporting
13670
report_service(
13771
:host => k,
13872
:proto => 'udp',
13973
:port => rport,
14074
:name => 'ntp'
14175
)
142-
143-
report_note(
144-
:host => k,
145-
:proto => 'udp',
146-
:port => rport,
147-
:type => 'ntp.peer_list',
148-
:data => {:peer_list => @results[k]}
149-
)
15076
end
15177
end
15278
end

modules/auxiliary/scanner/ntp/ntp_peer_list_sum_dos.rb

Lines changed: 2 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,6 @@ def initialize
2727
'Author' => 'Jon Hart <jon_hart[at]rapid7.com>',
2828
'License' => MSF_LICENSE
2929
)
30-
31-
register_options(
32-
[
33-
OptBool.new('SHOW_PEERS', [false, 'Show peers', 'false'])
34-
], self.class)
3530
end
3631

3732
# Called for each IP in the batch
@@ -41,77 +36,8 @@ def scan_host(ip)
4136

4237
# Called for each response packet
4338
def scanner_process(data, shost, sport)
44-
this_peer = "#{shost}:#{sport}"
45-
# sanity check that the reply is not overly large/small
46-
if data.length < 8
47-
print_error("#{this_peer} -- suspiciously small (#{data.length} bytes) NTP PEER_LIST_SUM response")
48-
return
49-
elsif data.length > 500
50-
print_error("#{this_peer} -- suspiciously large (#{data.length} bytes) NTP PEER_LIST_SUM response")
51-
return
52-
end
53-
54-
# try to parse this response, alerting and aborting if it is invalid
55-
response = Rex::Proto::NTP::NTPPrivate.new(data)
56-
unless [ @version, @implementation, @request_code ] == [ response.version, response.implementation, response.request_code ]
57-
print_error("#{this_peer} -- unexpected NTP PEER_LIST_SUM response: #{response.inspect}")
58-
return
59-
end
60-
61-
if response.error != 0
62-
vprint_status("#{this_peer} -- error #{response.error} response to NTP PEER_LIST request")
63-
return
64-
end
65-
66-
if response.record_size != 72 || response.record_count == 0 || response.record_count > 9
67-
print_error("#{this_peer} -- suspicious NTP PEER_LIST_SUM response with #{response.record_count} #{response.record_size}-byte entries: #{response.inspect}")
68-
return
69-
end
70-
71-
these_results = []
72-
response.records.each do |record|
73-
# TODO: Rex this
74-
# u_int32 dstadr; /* local address (zero for undetermined) */
75-
# u_int32 srcadr; /* source address */
76-
# u_short srcport; /* source port */
77-
# u_char stratum; /* stratum of peer */
78-
# s_char hpoll; /* host polling interval */
79-
# s_char ppoll; /* peer polling interval */
80-
# u_char reach; /* reachability register */
81-
# u_char flags; /* flags, from above */
82-
# u_char hmode; /* peer mode */
83-
# s_fp delay; /* peer.estdelay */ (int32)
84-
# l_fp offset; /* peer.estoffset */ (2x int32)
85-
# u_fp dispersion; /* peer.estdisp */ (u_int32)
86-
# u_int v6_flag; /* is this v6 or not */
87-
# u_int unused1; /* (unused) padding for dstadr6 */
88-
# struct in6_addr dstadr6; /* local address (v6) */
89-
# struct in6_addr srcadr6; /* source address (v6) */
90-
91-
dst_addr4, src_addr4, src_port, stratum = record[0,12].unpack('NNnC')
92-
is_v6 = record[32,4].unpack('N').first
93-
94-
if is_v6 == 0
95-
src_addr = Rex::Socket.addr_itoa(src_addr4)
96-
else
97-
# XXX: is there a better way to do this?
98-
src_addr6_parts = record[52, 16].unpack("N*")
99-
src_addr6 = 0
100-
0.upto(3) do |off|
101-
src_addr6 = src_addr6 | src_addr6_parts[off]
102-
src_addr6 <<= 32
103-
end
104-
src_addr = Rex::Socket.addr_itoa(src_addr6, true)
105-
end
106-
these_results << [ src_addr, src_port, stratum]
107-
if datastore['SHOW_LIST']
108-
print_status("#{this_peer} peers with #{src_addr}:#{src_port} (stratum #{stratum})")
109-
end
110-
end
111-
11239
@results[shost] ||= []
113-
@results[shost] << these_results
114-
40+
@results[shost] << Rex::Proto::NTP::NTPPrivate.new(data)
11541
end
11642

11743
# Called before the scan block
@@ -128,22 +54,13 @@ def scanner_prescan(batch)
12854
def scanner_postscan(batch)
12955
@results.keys.each do |k|
13056
packets = @results[k]
131-
peers = packets.flatten(1)
132-
print_good("#{k}:#{rport} NTP PEER_LIST_SUM request permitted (#{packets.size} packets with #{peers.size} peers total)")
57+
# TODO: check to see if any of the responses are actually NTP before reporting
13358
report_service(
13459
:host => k,
13560
:proto => 'udp',
13661
:port => rport,
13762
:name => 'ntp'
13863
)
139-
140-
report_note(
141-
:host => k,
142-
:proto => 'udp',
143-
:port => rport,
144-
:type => 'ntp.peer_list_sum',
145-
:data => {:peer_list_sum => @results[k]}
146-
)
14764
end
14865
end
14966
end

modules/auxiliary/scanner/ntp/ntp_req_nonce_dos.rb

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -37,24 +37,8 @@ def scan_host(ip)
3737

3838
# Called for each response packet
3939
def scanner_process(data, shost, sport)
40-
this_peer = "#{shost}:#{sport}"
41-
# sanity check that the reply is not overly large/small
42-
if data.length < 12
43-
print_error("#{this_peer} -- suspiciously small (#{data.length} bytes) NTP req_nonce response")
44-
return
45-
elsif data.length > 500
46-
print_error("#{this_peer} -- suspiciously large (#{data.length} bytes) NTP req_nonce response")
47-
return
48-
end
49-
50-
# try to parse this response, alerting and aborting if it is invalid
51-
response = Rex::Proto::NTP::NTPControl.new(data)
52-
if [ @probe.version, @probe.operation ] == [ response.version, response.operation ]
53-
@results[shost] ||= []
54-
@results[shost] << response
55-
else
56-
print_error("#{this_peer} -- unexpected NTP req_nonce response: #{response.inspect}")
57-
end
40+
@results[shost] ||= []
41+
@results[shost] << Rex::Proto::NTP::NTPControl.new(data)
5842
end
5943

6044
# Called before the scan block
@@ -76,13 +60,7 @@ def scanner_postscan(batch)
7660
:port => rport,
7761
:name => 'ntp'
7862
)
79-
report_note(
80-
:host => k,
81-
:proto => 'udp',
82-
:port => rport,
83-
:type => 'ntp.req_nonce',
84-
:data => {:req_nonce => @results[k]}
85-
)
63+
8664
total_size = packets.map(&:size).reduce(:+)
8765
if packets.size > 1 || total_size > @probe.size
8866
print_good("#{k}:#{rport} NTP req_nonce request permitted with amplified response (#{packets.size} packets, #{total_size} bytes)")

modules/auxiliary/scanner/ntp/ntp_reslist_dos.rb

Lines changed: 1 addition & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,6 @@ def initialize
2929
'Author' => 'Jon Hart <jon_hart[at]rapid7.com>',
3030
'License' => MSF_LICENSE
3131
)
32-
33-
register_options(
34-
[
35-
OptBool.new('SHOW_LIST', [false, 'Show the restrictions list', 'false'])
36-
], self.class)
37-
3832
end
3933

4034
# Called for each IP in the batch
@@ -44,69 +38,8 @@ def scan_host(ip)
4438

4539
# Called for each response packet
4640
def scanner_process(data, shost, sport)
47-
this_peer = "#{shost}:#{sport}"
48-
# sanity check that the reply is not overly large/small
49-
if data.length < 12
50-
print_error("#{this_peer} -- suspiciously small (#{data.length} bytes) NTP reslist response")
51-
return
52-
elsif data.length > 500
53-
print_error("#{this_peer} -- suspiciously large (#{data.length} bytes) NTP reslist response")
54-
return
55-
end
56-
57-
# try to parse this response, alerting and aborting if it is invalid
58-
response = Rex::Proto::NTP::NTPPrivate.new(data)
59-
unless [ @version, @implementation, @request_code ] == [ response.version, response.implementation, response.request_code ]
60-
print_error("#{this_peer} -- unexpected NTP reslist response: #{response.inspect}")
61-
return
62-
end
63-
64-
if response.record_size != 56 || response.record_count == 0 || response.record_count > 9
65-
print_error("#{this_peer} -- suspicious NTP reslist response with #{response.record_count} #{response.record_size}-byte entries: #{response.inspect}")
66-
return
67-
end
68-
69-
these_results = []
70-
response.records.each do |record|
71-
# TODO: Rex this
72-
# u_int32 addr; /* match address */
73-
# u_int32 mask; /* match mask */
74-
# u_int32 count; /* number of packets matched */
75-
# u_short flags; /* restrict flags */
76-
# u_short mflags; /* match flags */
77-
# u_int v6_flag; /* is this v6 or not */
78-
# u_int unused1; /* unused, padding for addr6 */
79-
# struct in6_addr addr6; /* match address (v6) */
80-
# struct in6_addr mask6; /* match mask (v6) */
81-
82-
addr4, mask4, count, rflags, mflags, is_v6 = record[0,20].unpack("NNNnnnn")
83-
84-
if is_v6 == 0
85-
addr = Rex::Socket.addr_itoa(addr4)
86-
mask = Rex::Socket.addr_itoa(mask4)
87-
else
88-
# XXX: is there a better way to do this?
89-
addr6_parts = record[20, 16].unpack("N*")
90-
mask6_parts = record[36, 16].unpack("N*")
91-
addr6 = 0
92-
mask6 = 0
93-
0.upto(3) do |off|
94-
addr6 = addr6 | addr6_parts[off]
95-
addr6 <<= 32
96-
mask6 = mask6 | mask6_parts[off]
97-
mask6 <<= 32
98-
end
99-
addr = Rex::Socket.addr_itoa(addr6, true)
100-
mask = Rex::Socket.addr_itoa(mask6, true)
101-
end
102-
these_results << [ addr, mask, rflags, mflags]
103-
if datastore['SHOW_LIST']
104-
print_status("#{this_peer} #{addr}/#{mask} (count: #{count}, restrict flags: #{rflags}, match flags: #{mflags})")
105-
end
106-
end
107-
10841
@results[shost] ||= []
109-
@results[shost] << these_results
42+
@results[shost] << Rex::Proto::NTP::NTPPrivate.new(data)
11043
end
11144

11245
# Called before the scan block
@@ -123,22 +56,12 @@ def scanner_prescan(batch)
12356
def scanner_postscan(batch)
12457
@results.keys.each do |k|
12558
packets = @results[k]
126-
entries = packets.flatten(1)
127-
print_good("#{k}:#{rport} NTP reslist request permitted (#{packets.size} packets with #{entries.size} total entries)")
12859
report_service(
12960
:host => k,
13061
:proto => 'udp',
13162
:port => rport,
13263
:name => 'ntp'
13364
)
134-
135-
report_note(
136-
:host => k,
137-
:proto => 'udp',
138-
:port => rport,
139-
:type => 'ntp.reslist',
140-
:data => {:reslist => @results[k]}
141-
)
14265
end
14366
end
14467
end

0 commit comments

Comments
 (0)