Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/auxiliary/scanner/ntp/ntp_monlist.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary6include Msf::Auxiliary::Report7include Msf::Exploit::Remote::Udp8include Msf::Auxiliary::UDPScanner9include Msf::Auxiliary::NTP10include Msf::Auxiliary::DRDoS1112def initialize13super(14'Name' => 'NTP Monitor List Scanner',15'Description' => %q{16This module identifies NTP servers which permit "monlist" queries and17obtains the recent clients list. The monlist feature allows remote18attackers to cause a denial of service (traffic amplification)19via spoofed requests. The more clients there are in the list, the20greater the amplification.21},22'References' =>23[24['CVE', '2013-5211'],25['URL', 'https://www.cisa.gov/uscert/ncas/alerts/TA14-013A'],26['URL', 'https://support.ntp.org/bin/view/Main/SecurityNotice'],27['URL', 'https://nmap.org/nsedoc/scripts/ntp-monlist.html'],28],29'Author' => 'hdm',30'License' => MSF_LICENSE31)3233register_options(34[35OptInt.new('RETRY', [false, "Number of tries to query the NTP server", 3]),36OptBool.new('SHOW_LIST', [false, 'Show the recent clients list', false])37])3839register_advanced_options(40[41OptBool.new('StoreNTPClients', [true, 'Store NTP clients as host records in the database', false])42])43end4445# Called for each response packet46def scanner_process(data, shost, sport)47@results[shost] ||= { messages: [], peers: [] }48@results[shost][:messages] << Rex::Proto::NTP::NTPPrivate.new.read(data).to_binary_s49@results[shost][:peers] << extract_peer_tuples(data)50end5152# Called before the scan block53def scanner_prescan(batch)54@results = {}55@aliases = {}56@probe = Rex::Proto::NTP.ntp_private(datastore['VERSION'], datastore['IMPLEMENTATION'], 42, "\0" * 40).to_binary_s57end5859# Called after the scan block60def scanner_postscan(batch)61@results.keys.each do |k|62response_map = { @probe => @results[k][:messages] }63peer = "#{k}:#{rport}"6465# TODO: check to see if any of the responses are actually NTP before reporting66report_service(67:host => k,68:proto => 'udp',69:port => rport,70:name => 'ntp'71)7273peers = @results[k][:peers].flatten(1)74unless peers.empty?75print_good("#{peer} NTP monlist request permitted (#{peers.length} entries)")76# store the peers found from the monlist77report_note(78:host => k,79:proto => 'udp',80:port => rport,81:type => 'ntp.monlist',82:data => {:monlist => peers}83)84# print out peers if desired85if datastore['SHOW_LIST']86peers.each do |ntp_peer|87print_status("#{peer} #{ntp_peer}")88end89end90# store any aliases for our target91report_note(92:host => k,93:proto => 'udp',94:port => rport,95:type => 'ntp.addresses',96:data => {:addresses => peers.map { |p| p.last }.sort.uniq }97)9899if (datastore['StoreNTPClients'])100print_status("#{peer} Storing #{peers.length} NTP client hosts in the database...")101peers.each do |r|102maddr,mport,mserv = r103next if maddr == '127.0.0.1' # some NTP servers peer with themselves..., but we can't store loopback104report_note(105:host => maddr,106:type => 'ntp.client.history',107:data => {108:address => maddr,109:port => mport,110:server => mserv111}112)113end114end115end116117vulnerable, proof = prove_amplification(response_map)118what = 'NTP Mode 7 monlist DRDoS (CVE-2013-5211)'119if vulnerable120print_good("#{peer} - Vulnerable to #{what}: #{proof}")121report_vuln({122:host => k,123:port => rport,124:proto => 'udp',125:name => what,126:refs => self.references127})128else129vprint_status("#{peer} - Not vulnerable to #{what}: #{proof}")130end131end132133end134135# Examine the monlist response +data+ and extract all peer tuples (saddd, dport, daddr)136def extract_peer_tuples(data)137return [] if data.length < 76138139# NTP headers 8 bytes140ntp_flags, ntp_auth, ntp_vers, ntp_code = data.slice!(0,4).unpack('C*')141pcnt, plen = data.slice!(0,4).unpack('nn')142return [] if plen != 72143144idx = 0145peer_tuples = []1461.upto(pcnt) do147# u_int32 firsttime; /* first time we received a packet */148# u_int32 lasttime; /* last packet from this host */149# u_int32 restr; /* restrict bits (was named lastdrop) */150# u_int32 count; /* count of packets received */151# u_int32 addr; /* host address V4 style */152# u_int32 daddr; /* destination host address */153# u_int32 flags; /* flags about destination */154# u_short port; /* port number of last reception */155156_,_,_,_,saddr,daddr,_,dport = data[idx, 30].unpack("NNNNNNNn")157158peer_tuples << [ Rex::Socket.addr_itoa(saddr), dport, Rex::Socket.addr_itoa(daddr) ]159idx += plen160end161peer_tuples162end163end164165166