Talos Vulnerability Report

TALOS-2016-0082

Network Time Protocol Forced Interleaved Time Spoofing Vulnerability

April 26, 2016

Report ID

CVE-2016-1548

Summary

It is possible to change the time of an ntpd client or deny service to an ntpd client by forcing it to change from basic client/server mode to interleaved symmetric mode. An attacker can spoof a packet from a legitimate ntpd server with an origin timestamp that matches the peer->dst timestamp recorded for that server. After making this switch, the client will reject all future legitimate server responses. It is possible to force the victim client to move time after the mode has been changed. ntpq gives no indication that the mode has been switched.

Tested Versions

ntp 4.2.8p4
NTPSec aa48d001683e5b791a743ec9c575aaf7d867a2b0c

Product URLs

http://www.ntp.org
http://www.ntpsec.org/

CVSSv3 Score

CVSSv2: 6.4 - (AV:N/AC:L/Au:N/C:N/I:P/A:P)
CVSSv3: 7.2 - CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:L/A:L

Details

In basic modes, ntpd attempts to protect against spoofed packets from off-path attackers by using the transmit timestamp in each request as a nonce. ntpd notes the time it transmitted its last request in the peer->aorg variable. When a legitimate peer composes a response, the peer will initialize the origin timestamp in the response packet to the value of the transmit timestamp from the request packet. Any response packet that does not carry the expected origin timestamp should be discarded as bogus.

receive() contains the following check for a bogus packet in basic mode:

  } else if (peer->flip == 0) {
          if (!L_ISEQU(&p_org, &peer->aorg)) {
                  peer->bogusorg++;
                  peer->flash |= TEST2;   /* bogus */
                  msyslog(LOG_INFO,
                          "receive: Unexpected origin timestamp from %s",
                          ntoa(&peer->srcadr));
                  if (  !L_ISZERO(&peer->dst)
                      && L_ISEQU(&p_org, &peer->dst)) {
                          peer->flip = 1;
                          report_event(PEVNT_XLEAVE, peer, NULL);
                  }
                  return; /* Bogus packet, we are done */
          } else {
                  L_CLR(&peer->aorg);
          }
  }

If the incoming packet has an origin timestamp that does not match the origin expected for a basic mode packet (the last client transmit time), there is an additional check that determines if this packet is a valid interleaved mode packet This check compares the incoming origin timestamp to peer->dst, the last time the client received a packet from the peer. If they match, the client moves to interleaved mode (peer->flip = 1; Only the value of peer->flip changes and neither symmetric nor broadcast mode are explicitly enabled, however the change effectively places the client in interleaved symmetric mode and will be discussed as such). This happens even when the client is not configured for interleaved symmetric mode in the ntp.conf file.

Once a client has been changed to interleaved mode, all future legitimate server responses are ignored because the server is still in basic mode. The server sets the origin timestamp in outgoing packets to the transmit time of the client packets it receives. However, the client, instead of doing the above basic mode check, verifies the incoming server packet with this code from receive():

  } else if (   !L_ISZERO(&peer->dst)
             && !L_ISEQU(&p_org, &peer->dst)) {
          peer->bogusorg++;
          peer->flags |= FLAG_XBOGUS;
          peer->flash |= TEST2;           /* bogus */
          return; /* Bogus packet, we are done */
  }

The client is expecting the origin timestamp to match peer->dst rather than its last transmit timestamp. This results in all future legitimate server responses failing with TEST2 and TEST3 (marked elsewhere in the receive() function).

It should be noted that the client never changes the peer modes stored in the peer struct (pmode and hmode). Both continue to be Server (4) and Client (3), respectively. The mode change occurs only through the value of peer->flip. Anytime the peer is reset it comes back in basic mode. The peer is reset every time the clock is stepped (via clear_all()), but the legitimate server will never cause the clock to step since the client is rejecting all its packets. The client can only be switched back to basic mode with a restart of ntpd.

Obtaining peer->dst:

ntpq can be used to retrieve the precise peer->dst time with the following command:

ntpq -c "rv <assoc id> rec" <victim host>

Even if ntpq did not reveal this variable, ntpd’s current design for switching to interleaved mode should be considered vulnerable. If there is ever a weakness that allows an attacker to brute-force peer->dst (e.g. the random fuzz in the timestamp is found to be insufficient to protect against a brute-force attack within a poll period), the attacker only needs to send one packet to switch the mode and DoS the client.

UPDATE: Miroslav Lichvar of RedHat has discovered that NTP leaks peer->dst via the NTP packet reftime field.

Changing Time:

It is possible to set the time on the client after it has changed to interleaved symmetric mode. The attacker must have ongoing access to the current value of peer->dst since it is updated each time the victim receives a spoofed packet. Again, ntpq makes this easier but it is not required.

The attacker can send spoofed time updates with peer->dst in the origin timestamp field to be considered for clock selection. The spoofed packets must set the transmit timestamp (xmt) to this same value in order to minimize delay. The receive timestamp (rec) must be set to the time of peer->dst when the last legitimate server packet was received to approximate what value aorg or borg will be when process_packet() computes the delay and offset. aorg and borg are set to the current system time in peer_xmit() right after the client sends out a packet to the server. They are used alternately depending on the value of flip, which alternates between 1 and -1 every time a poll update is sent. The delay and offset are calculated as:

When flip == 1
    delay  = (rec - borg) - (xmt - peer->dst)
    offset = ((rec - borg) + (xmt - peer->dst)) / 2

When flip == -1
    delay  = (rec - aorg) - (xmt - peer->dst)
    offset = ((rec - aorg) + (xmt - peer->dst)) / 2

The attacker can control rec and xmt. The attacker can gain access to peer->dst through ntpq or by guessing at the delay. But the attacker has no insight into aorg or borg. Both values are sent out alternately in the transmit timestamp field in client packets. But the value sent out is always the last one used, never the one that is about to be used. To keep delay between 0 and 1 seconds and win the clock selection, the attacker must estimate a time for aorg or borg that is within a second of the real values. On modern networks with low delay, if the attacker uses peer->dst time (the time the client received a response to that request) as an estimate, it will generally fall within a second of aorg or borg, the time the packet was sent. If normal delay in a certain network is usually larger, and if it is within a predictable range, the attacker could fudge for that time by adjusting the receive timestamp.

Since the peer will be reset to basic mode after stepping the clock, the attacker must send one more packet with peer->dst as the origin timestamp to pivot the client back to interleaved mode. Once this is done, the attacker does not need to send any more packets to maintain the incorrect time since no legitimate server packets will be processed. The client will continue to move forward in time from the incorrect time the attacker provided. If the attacker wants to change the time further, the client will continue to process spoofed packets as long as the attacker continues to correctly set the origin timestamp.

Ideally, a basic mode client would not move to interleaved mode unless it was explicitly configured to do so. If a dynamic mode transition is required, the client needs a way to detect that the legitimate server it is talking to is in basic mode allowing the client to change back to basic mode without requiring a clock step to occur first. Additionally, the peer->dst value should be treated as sensitive and ntpq should not have access it.

On Nov 12, 2015, Cisco ASIG received notification that Miroslav Lichvar of RedHat had independently discovered and reported this vulnerability to the NTP project.

ASIG’s initial analysis indicated that, with access to ntpq, this vulnerability allows time spoofing. To our knowledge, Miroslav’s initial analysis indicated that this vulnerability was an off-path denial of service. It appears that the attacks can be combined to allow time spoofing by an off-path attacker without access to ntpq.

Mitigation

The only mitigation is to upgrade to ntp-4.2.8p<FIXME>. ntp-4.2.8p<FIXME> fixes a number of other critical issues in addition to this vulnerability. If your system’s ntpd is packaged by the system vendor, apply your vendor’s security update as soon as it becomes available.

There are no other mitigations to prevent an ntpd client from changing to interleaved mode when the origin timestamp matches the peer->dst timestamp. Disabling ntpq access will make it more difficult, though not impossible, for an attacker to determine the peer->dst timestamp. ntpq can be disabled via restrict configuration directives as in:

restrict -4 default noquery ...
restrict -6 default noquery ...

Credit

Discovered by Jonathan Gardner of Cisco ASIG. On Nov 12, 2015, Cisco ASIG received notification that Miroslav Lichvar of RedHat had independently discovered and reported this vulnerability.

Timeline

2015-10-30 - Initial Discovery by Cisco ASIG, analysis begins
2015-11-12 - Reported to NTP project by Miroslav Lichvar of RedHat after independent discovery
2015-11-12 - Miroslav Lichvar of RedHat notifies Cisco ASIG of independent discovery
2016-01-19 - CERT reports to NTP