Binary analysis of NTP protocol

In this article I wish to share some insights into the NTP (Network Time Protocol). We do not usually do much apart from making sure its default port (123 udp) is open through firewalls and ensure the configuration of the service is provided with synchronisation servers.

There are,however, several exploits that seem to exploit the notorious buffer overflow and get some code execution, but as of now (late 2019), these exploits all seem to apply to some older versions of NTP, mostly for unix environments…Anyway, none of them worked for me against recent equipment (CentOS 7.x, Cisco and HPE switches, VMWare VMs).

NTP defines its protocol in several RFC-s , depending on the version of the NTP you deploy. This is why some of the below links may be of use:


Kali comes with several Metasploit modules that allow you to quickly check if NTP is flowed against the below vulnerabilities – none of them, according to my knowledge does the buffer overflow. They all seem to check the NTP packets amplification attacks and denial of service. All of them will work with changing only the RHOSTS parameter to read the IP address of your NTP agent.

So let us have a look at one NTP exploit that will be launched from Metasploit. This attack will try to exploit the READVAR vulnerability. The point here is not primarily to exploit the NTP but to see information and structure is contained within NTP packets.
The tcpdump session run on the destination host confirms that there is no response sent.
Note that the NTP message does not say mode "client" but rather "reserved for NTP control message" (Flags: 0x16 - "no warning" + "NTP Version 2" + "reserved for NTP control message")
RFC can help us understand what these parameters are (Leap indicator, version number, mode). Have a look at the RFC definition of the “Mode: reserved for NTP Control Message (6)”.  Flags 2 (see below screenshot) (0x02) confirm that ("Opcode:READVAR (2) " is a reserved/control message) and this is the one that our above metasploit probe checks.
So, Flags 0x16 is "reserved for NTP control message" + "NTP version 2" + "no waiting". Flags 0x02 is "opcode:READVAR". The rest of the message ("Sequence", "Status", "AssociationID", "Offset" and "Count" are all set to 0)
We can consult an RFC (for NTP version 2 , in our case) to understand what these are. 
Given all the explanations of the NTP parameters and following our Wireshark PCAP structure of the request, we can try to simulate an NTP request via nping, for example. I put “dead beef” string to the end of the NTP request to locate it easier in the Wireshark capture.
This upper one indeed returns the response. So , lets first look at the request.
Note the “dead beef” in the wireshark capture- so we know where our packet ends. Note the “0xd3” as the start of our NTP packet. I outlined the whole packet in blue to make it more visible. Flags:0xd3 equals to: "Leap indicator:Clock unsynchronized" + "NTP Version 2" + "mode:client")
The below response is : Flags 0x14 ("no warning" + "NTP version 2" + "mode:server")
This is another case where we sent a legitimate NTP sync request.
A legitimate NTP sync request was sent from a local centos local VM (10.0.2.15) and the reply was received from 85.91.1.164. Note where this remote NTP uses the "Reference ID:188.125.64.6" which is embedded in the NTP response from 85.91.1.164).
Note that in the example above we managed to obtain the IP address of the NTP sync server (193.120.10.3) that NTP that we are exploiting (193.120.10.3) will use.
This is an example of an NTP "chatty" server on the HPE switch which responds to the "READVAR" opcode.
Asking for a sync data from public server with our reconstructed valid NTP request works ok. We do receive replies (Flags 0xd302) after submitting NTP request via nping.
However, READVAR request (Flags 0x16) against it does not return any response (0x1602) meaning the destination NTP is vulnerable to reading NTP variables (hence READVAR).
A small proof of concept is on the https://github.com/adenosine-phosphatase/ntp where a python script retrieves the NTP upstream server IP address from the IP address you specify.
The assumption is that the upstream NTP server will be a higher-precision stratum level.




Comments

Popular posts from this blog

Signature verification bypass vulnerability in some Huawei routers

Attacking encrypted VOIP (SIP) protocols

Investigating suspicious emails