|
6 | 6 | require 'msf/core'
|
7 | 7 |
|
8 | 8 | class Metasploit3 < Msf::Auxiliary
|
9 |
| - |
10 |
| - |
11 |
| - include Msf::Exploit::Remote::Udp |
12 | 9 | include Msf::Auxiliary::Report
|
13 |
| - include Msf::Auxiliary::Scanner |
14 |
| - |
| 10 | + include Msf::Exploit::Remote::Udp |
| 11 | + include Msf::Auxiliary::UDPScanner |
| 12 | + include Msf::Auxiliary::NTP |
| 13 | + include Msf::Auxiliary::DRDoS |
15 | 14 |
|
16 | 15 | def initialize(info = {})
|
17 | 16 | super(update_info(info,
|
18 | 17 | 'Name' => 'NTP Clock Variables Disclosure',
|
19 |
| - 'Description' => %q{ |
20 |
| - This module reads the system internal NTP variables. These variables contain |
| 18 | + 'Description' => %q( |
| 19 | + This module reads the system internal NTP variables. These variables contain |
21 | 20 | potentially sensitive information, such as the NTP software version, operating
|
22 | 21 | system version, peers, and more.
|
23 |
| - }, |
24 |
| - 'Author' => [ 'Ewerson Guimaraes(Crash) <crash[at]dclabs.com.br>' ], |
| 22 | + ), |
| 23 | + 'Author' => |
| 24 | + [ |
| 25 | + 'Ewerson Guimaraes(Crash) <crash[at]dclabs.com.br>', # original Metasploit module |
| 26 | + 'Jon Hart <jon_hart[at]rapid7.com>' # UDPScanner version for faster scans |
| 27 | + ], |
25 | 28 | 'License' => MSF_LICENSE,
|
26 | 29 | 'References' =>
|
27 | 30 | [
|
28 |
| - [ 'URL','http://www.rapid7.com/vulndb/lookup/ntp-clock-variables-disclosure' ], |
| 31 | + [ 'URL', 'http://www.rapid7.com/vulndb/lookup/ntp-clock-variables-disclosure' ] |
29 | 32 | ]
|
30 | 33 | )
|
31 | 34 | )
|
32 |
| - register_options( |
33 |
| - [ |
34 |
| - Opt::RPORT(123) |
35 |
| - ], self.class) |
36 | 35 | end
|
37 | 36 |
|
38 |
| - def run_host(ip) |
| 37 | + def scanner_process(data, shost, _sport) |
| 38 | + @results[shost] ||= [] |
| 39 | + @results[shost] << Rex::Proto::NTP::NTPControl.new(data) |
| 40 | + end |
39 | 41 |
|
40 |
| - connect_udp |
| 42 | + def scan_host(ip) |
| 43 | + if spoofed? |
| 44 | + datastore['ScannerRecvWindow'] = 0 |
| 45 | + scanner_spoof_send(@probe, ip, datastore['RPORT'], datastore['SRCIP'], datastore['NUM_REQUESTS']) |
| 46 | + else |
| 47 | + scanner_send(@probe, ip, datastore['RPORT']) |
| 48 | + end |
| 49 | + end |
41 | 50 |
|
42 |
| - readvar = "\x16\x02\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" #readvar command |
43 |
| - print_status("Connecting target #{rhost}:#{rport}...") |
| 51 | + def scanner_prescan(batch) |
| 52 | + @results = {} |
| 53 | + print_status("Sending NTP v2 READVAR probes to #{batch[0]}->#{batch[-1]} (#{batch.length} hosts)") |
| 54 | + @probe = Rex::Proto::NTP::NTPControl.new |
| 55 | + @probe.version = datastore['VERSION'] |
| 56 | + @probe.operation = 2 |
| 57 | + end |
44 | 58 |
|
45 |
| - print_status("Sending command") |
46 |
| - udp_sock.put(readvar) |
47 |
| - reply = udp_sock.recvfrom(65535, 0.1) |
48 |
| - if not reply or reply[0].empty? |
49 |
| - print_error("#{rhost}:#{rport} - Couldn't read NTP variables") |
50 |
| - return |
51 |
| - end |
52 |
| - p_reply = reply[0].split(",") |
53 |
| - arr_count = 0 |
54 |
| - while ( arr_count < p_reply.size) |
55 |
| - if arr_count == 0 |
56 |
| - print_good("#{rhost}:#{rport} - #{p_reply[arr_count].slice(12,p_reply[arr_count].size)}") #12 is the adjustment of packet garbage |
57 |
| - arr_count = arr_count + 1 |
| 59 | + def scanner_postscan(_batch) |
| 60 | + @results.keys.each do |k| |
| 61 | + # TODO: check to see if any of the responses are actually NTP before reporting |
| 62 | + report_service( |
| 63 | + host: k, |
| 64 | + proto: 'udp', |
| 65 | + port: rport, |
| 66 | + name: 'ntp', |
| 67 | + info: @results[k].map { |r| r.payload.slice(0,r.payload_size) }.join.inspect |
| 68 | + ) |
| 69 | + |
| 70 | + peer = "#{k}:#{rport}" |
| 71 | + response_map = { @probe => @results[k] } |
| 72 | + vulnerable, proof = prove_amplification(response_map) |
| 73 | + what = 'NTP Mode 6 READVAR DRDoS' |
| 74 | + if vulnerable |
| 75 | + print_good("#{peer} - Vulnerable to #{what}: #{proof}") |
| 76 | + report_vuln( |
| 77 | + host: k, |
| 78 | + port: rport, |
| 79 | + proto: 'udp', |
| 80 | + name: what, |
| 81 | + refs: references |
| 82 | + ) |
58 | 83 | else
|
59 |
| - print_good("#{rhost}:#{rport} - #{p_reply[arr_count].strip}") |
60 |
| - arr_count = arr_count + 1 |
| 84 | + vprint_status("#{peer} - Not vulnerable to #{what}: #{proof}") |
61 | 85 | end
|
62 | 86 | end
|
63 |
| - disconnect_udp |
64 |
| - |
65 | 87 | end
|
66 |
| - |
67 | 88 | end
|
0 commit comments