[ntp:security] [Bug 3361] 0rigin (zero origin) DoS

bugzilla-daemon at ntp.org bugzilla-daemon at ntp.org
Wed Jan 4 01:01:59 UTC 2017


http://bugs.ntp.org/show_bug.cgi?id=3361

Harlan Stenn <stenn at ntp.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P5                          |P2
                 CC|                            |mvangund at cisco.com
           Severity|enhancement                 |critical

--- Comment #1 from Harlan Stenn <stenn at ntp.org> 2017-01-04 01:01:59 UTC ---
TALOS-2016-0260
CVE-2016-9042

Affects: 4.2.8p9 (other 0rigin bugs affect earlier versions)

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 at 192.168.33.12
xmt 0xdbe84918.63324800

    ntpd[16767]: receive: Unexpected origin timestamp 0xdbe849a1.279a6fea does
not match aorg 0000000000.00000000 from sym_active at 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.


### Credit

Discovered by Matthew Van Gundy of Cisco ASIG.


### Timeline

2017-01-04 - Vendor Disclosure
YYYY-MM-DD - Public Release

-- 
Configure bugmail: http://bugs.ntp.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.


More information about the security mailing list