Talos Vulnerability Report

TALOS-2016-0260

Network Time Protocol Origin Timestamp Check Denial of Service Vulnerability

March 29, 2017
CVE Number

CVE-2016-9042

Summary

An exploitable denial of service vulnerability exists in the origin timestamp check functionality of ntpd 4.2.8p9. A specially crafted unauthenticated network packet can be used to reset the expected origin timestamp for target peers. Legitimate replies from targeted peers will fail the origin timestamp check (TEST2) causing the reply to be dropped and creating a denial of service condition.

Tested Versions

NTP 4.2.8p9

Product URLs

http://www.ntp.org

CVSSv3 Score

CVSSv2: 4.3 - (AV:N/AC:M/Au:N/C:N/I:N/A:P) CVSSv3: 3.7 - CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L

Details

In most modes, NTP prevents spoofing by off-path attackers by verifying that the origin timestamp of an incoming NTP packet matches the transmit timestamp on the daemon’s last outgoing packet — using the transmit and origin timestamps as a per-request nonce. This test described in RFC 5905 and dubbed TEST2 in ntpd’s source code. To prevent an NTP daemon from accepting responses to duplicated request packets, RFC 5095 also specifies that the expected origin timestamp should be set to zero after successfully validating the origin timestamp of an incoming packet. Unfortunately, ntpd releases before 4.2.8p9 did not correctly reject incoming packets bearing a zero origin timestamp. This allowed a trivial bypass of TEST2, the origin timestamp check, by setting the origin timestamp on spoofed packets equal to zero (CVE-2015-8138,CVE-2016-7431).

ntp-4.2.8p9 fixes CVE-2015-8138 by rejecting packets with zero origin timestamps in all modes where that is not expected legitimate behavior. However, for reasons unknown, before rejecting a packet bearing a zero origin timestamp, ntp-4.2.8p9 clears the expected origin timestamp (peer->aorg) as can be seen in the following abstracted code:

if (0) {
} else if (L_ISZERO(&p_org)) {
        char *action;

        L_CLR(&peer->aorg);
        ...
        peer->bogusorg++;
        peer->flash |= TEST2;	/* bogus */
        ... /* packet will be dropped */
} else if (!L_ISEQU(&p_org, &peer->aorg)) {
        peer->bogusorg++;
        peer->flash |= TEST2;        /* bogus */
        ... /* packet will be dropped */
} else {
        L_CLR(&peer->aorg);
}

This leads to a trivial denial of service. An unauthenticated network attacker who knows the address of one of the peers of a victim ntpd process can send the victim ntpd spoofed packets with the source address of the peer and a zero origin timestamp in order to reset peer->aorg for that peer. This will cause the next packet sent from the peer to fail the origin timestamp check (TEST2) and be dropped. The attacker can repeat this each poll period for all known peers in order to prevent their packets from being accepted by the victim ntpd.

This attack is very effective against symmetric associations where the duration between an outgoing packet from the victim ntpd and its “response” will be on the order of seconds to minutes. The attack is more difficult for client-server associations where the request-response window is likely to be on the order of milliseconds. However, if the attacker can observe the victim ntpd’s request packet, it can attempt to race the remote peer’s legitimate response.

An attacker can learn the currently selected peer of a victim ntpd process by sending the victim a client mode request and reading the peer’s address from the refid field of the victim’s response. This allows the attacker to target the currently selected peer one at a time until it has learned and targeted all peers of the victim ntpd process. If the victim allows NTP control queries or the attacker can observe the victim’s NTP traffic, the attacker can easily learn all the victim’s peers.

The call to L_CLR(&peer->aorg) when a zero-origin timestamp packet is received appears unnecessary and should be removed. To see that clearing peer->aorg is unnecessary, let’s consider the operation of each NTP mode in turn after omitting the L_CLR(&peer->aorg):

  • Client-Server: Servers are stateless, so the change has no effect on them. Clients should not be sending requests with zero transmit timestamps and, therefore, should not be receiving responses with zero origin timestamps. Thus, removing the L_CLR(&peer->aorg) should have no effect on legitimate client-server behavior.

  • Broadcast: Broadcast packets are handled separately and thus are not influenced by the behavior of this code.

  • Symmetric (Active and Passive): When two symmetric peers are synchronized to a legitimate time source (0 < stratum < 16) and the association between them is fully operational, the origin timestamp on incoming packets will be non-zero and equal to peer->aorg, thus avoiding the L_CLR(&peer->aorg). The interesting cases occur when there is packet loss or one peer resets their association (e.g. ntpd is restarted).

    Without loss of generality, let A be the sender and B the recipient of the first packet with pkt->org != peer->aorg. If A reset its association with B, pkt->org == 0. Otherwise, pkt->org != 0 && pkt->org != peer->aorg. In either case, B will mark the packet as having failed TEST2. However, if the packet is authenticated correctly for the association, B will update peer->xmt = pkt->xmt before rejecting the packet due to failing TEST2. In B’s next packet to A, it will set pkt->org = peer->xmt and peer->aorg = pkt->xmt, ensuring that the packet will pass TEST2 at A, causing it to be accepted by A, and overwriting any previous value of peer->aorg at B. A will update its peer variables for B as well, ensuring that A’s next packet will be accepted by B. From this point on, the symmetric association between A and B has successfully resynchronized.

    Thus, we see that recovery from packet loss or peer restart is not hampered by allowing peer->aorg to maintain its previous value when a packet with a zero origin timestamp is received. Further to the point, ntpd versions prior to ntp-4.2.8p6 did not clear peer->aorg upon receipt of a packet bearing a zero origin timestamp.

Mitigation

The only ntpd-based mitigations for this vulnerability are to try to make it harder for an attacker to guess the peers of ntpd instances and to monitor ntpd logs for messages such as the following:

ntpd[16767]: receive: Drop 0 origin timestamp from sym_active@192.168.33.12 xmt 0xdbe84918.63324800

ntpd[16767]: receive: Unexpected origin timestamp 0xdbe849a1.279a6fea does not match aorg 0000000000.00000000 from sym_active@192.168.33.12 xmt 0xdbe849a4.52a12e3a

All ntpd instances should be configured to block control queries from untrusted servers. This is best practice.

All ntpd clients should block all incoming traffic that does not originate from a known peer address. This can be accomplished with a stateful firewall.

Because peer->aorg is cleared before authentication is enforced, enabling NTP authentication does not prevent exploitation of this vulnerability.

Timeline

2017-01-04 - Vendor Disclosure
2017-03-29 - Public Release

Credit

Discovered by Matthew Van Gundy of Cisco ASIG.