NTP CVE-2016-7434 Vulnerability Analysis

Last week, the Network Time Foundation’s NTP Project released a new version, NTP 4.2.8p9,  to fix 10 security vulnerabilities. We noticed that after the new release came out, the original research published a POC for exploiting CVE-2016-7434. This blog is about the verifying the exploit published and a deep analysis about this vulnerability.

NTP MRU and the Rxploit

NTPD maintains a “Most Recently Used” (MRU) list of source IP addresses seen in incoming NTP packets. The reason for this MRU feature is to monitor the client traffic (ex: to track service time for a specific client) and dramatically decline service to some clients.

CVE-2016-7434 will not be triggered if the remote NTP server doesn’t enable MRU because the affected function “read_mru_list” won’t be called.

In my exploit verification process, I used the last vulnerable version which is NTP 4.2.8p8. Below is my NTP server status before triggering the exploit.


After sending the exploit remotely, you can see that my NTP server crashed and the service stopped.


The exploit does work and can crash my NTP server remotely. The exploit simply sends a UDP package to the remote server.


This UDP package will be passed to the vulnerable function “read_mru_list”. The payload here will be stored in a variable called “in_parms” in that function.

in_parms = NULL;

set_var(&in_parms, nonce_text, sizeof(nonce_text), 0);

set_var(&in_parms, frags_text, sizeof(frags_text), 0);

set_var(&in_parms, limit_text, sizeof(limit_text), 0);

set_var(&in_parms, mincount_text, sizeof(mincount_text), 0);

set_var(&in_parms, resall_text, sizeof(resall_text), 0);

set_var(&in_parms, resany_text, sizeof(resany_text), 0);

set_var(&in_parms, maxlstint_text, sizeof(maxlstint_text), 0);

set_var(&in_parms, laddr_text, sizeof(laddr_text), 0);

Root Cause of CVE-2016-7434

When MRU is enabled, the vulnerable function “read_mru_list” will be called to parse fields from it. As you can see below.


The function will save every field in the payload to the “in_parms” as I listed above. The next step of this function is to process each field one by one using a while loop and store the value of that field into the address of val.

while (NULL != (v = ctl_getitem(in_parms, &val)) &&

      !(EOV & v->flags)) {

But if the value of field is empty (like laddr = [] in the exploit), the val becomes a NULL pointer.


The return value of “ctl_getitem” is a pointer to a structure.  So the “NULL !=” won’t detect the empty value which will be used later in line 4041. The function “estrdup” in line 4041 is a macro to “estrdup_impl” which will finally calls “strlen” with the input pointer.


When the NTP server tries to call “strlen” on the NULL pointer, it will receive an immediate segmentation fault which will crash the process. So this is a typical Null Pointer Dereference vulnerability.

Exploit Variant

Since we understand the root cause of this vulnerability now, let’s look back to the POC published.

The exploit sends a MRU package with field “laddr=[]” to trigger the Null Pointer Dereference. I already gave a list of fields the vulnerable function will process. So if we change the exploit a little bit by using another field, we should still trigger this vulnerability.


After changing the field from “laddr” to “limit”, the NTP server still crashed. For IDS vendors , all the field in the list should be checked to detect the active exploit of this vulnerability.


A single UDP package will crash the NTP server. And because of the nature of the protocol UDP, attackers can spoof the source IP address to launch the attack. This makes tracking the attack and defending the attack by IP blocking nearly impossible.  After the exploit was made public, the attacking threat of this vulnerability became higher. Qualys has released a QID: 38651 to detect this vulnerability. We highly recommend that customers scan their environment for this QID to identify these assets remotely.








Leave a Reply

Your email address will not be published. Required fields are marked *