On-Path & Byzantine Attacks


On-path and Byzantine attacks require either routing-layer access or infiltration of upstream time infrastructure. The payoff is proportionally larger: slower drift, wider geographic reach, and in some cases continent-scale impact without touching a single client directly. Nation-state adversaries and sophisticated criminal actors operate in this space.

Small-Step-Big-Step initialisation
CVE-2015-5300 — residual window in `ntpd`

ntpd enters a permissive initialisation phase on every boot or daemon restart. During this window it must accept large time steps to reach reality from an unknown starting state — it has no baseline against which to judge whether a server is lying. CVE-2015-5300 exploited a flaw in this logic: any initial step during initialisation temporarily disabled the panic threshold entirely, allowing a second, arbitrarily large jump immediately after.

The original exploit — stepping the clock by years — was patched in ntpd 4.2.8p4. The initialisation window was not closed. An on-path attacker who intercepts traffic at boot can still deliver a step of up to 999 seconds (16.5 minutes) without triggering any block. (Malhotra et al., NDSS 2016)

In any distributed system context, 16 minutes is not a recoverable nuisance. It corrupts causal ordering in distributed databases, terminates active TLS sessions, breaks Kerberos authentication across a domain, and disrupts any timestamp-based sequencing mechanism. An attacker does not need to time this precisely — forcing a connection drop to trigger a daemon restart is trivial on a compromised upstream path.

Banks and financial institutions

For institutions running real-time gross settlement, a 16-minute clock shift corrupts RTGS transaction ordering and invalidates timestamp compliance windows. For trading operations, MiFID II requires clock synchronisation within 100 microseconds of UTC. A daemon restart with an on-path attacker present can push the clock outside that window immediately, invalidating the entire day's transaction log for regulatory purposes.

Pool injection and Marzullo manipulation

This is not a patchable software flaw. It is an architectural property of the global NTP pool infrastructure.

Pool membership requires no identity verification. Registering a server in pool.ntp.org requires no cryptographic identity proof. The pool monitors availability and declared stratum; it trusts operator-declared capacity. A strategic adversary tunes malicious servers’ declared capacity, bandwidth attributes, and geographic metadata to inflate their selection weight in the pool’s geo-DNS allocation. Beverly and Rye (2026) demonstrated that an adversary operating ten or fewer malicious servers can capture the majority of NTP pool traffic in 90% of all countries. At that point the adversary controls the consensus.

Marzullo subversion. NTP clients apply a modified Marzullo intersection algorithm to select a time estimate from their configured peers. The algorithm identifies the time interval where the majority of servers agree and drops outliers — the falsetickers. Against a single rogue server the algorithm works as intended. Once an attacker occupies the majority of a client’s assigned pool slots, the algorithm defaults to the malicious consensus. The legitimate server becomes the outlier that gets dropped. (Perry et al., 2021; Deutsch et al., 2018)

Nation-state drift profile. Nation-state adversaries do not execute large steps that trigger panic thresholds. They drift all injected servers simultaneously by a few milliseconds per hour. Within days, clients are synchronised to a false timeline. No local error state fires. By the time an inconsistency surfaces in audit logs or transaction records, the window for attributing the cause has closed.

DNS cache poisoning and the Chronos paradox

NTP pool membership is resolved through DNS. A poisoned resolver redirects queries to attacker-controlled addresses before NTS or any application-layer protection is in scope. The attack requires no NTP-specific capability — standard off-path DNS cache poisoning techniques suffice.

The IETF response was Chronos (RFC 9523). Chronos queries up to 24 servers per sync cycle and applies aggressive statistical pruning to prevent any attacker-controlled subset from shifting consensus. Against Marzullo manipulation it is a meaningful improvement.

Against DNS poisoning it is worse than the standard client it replaces.

A standard NTP client issues 1–4 DNS queries per sync cycle. Chronos issues up to 24. Each query is an independent race condition for an off-path attacker attempting cache poisoning. The attacker needs to win one. Jeitner et al. (2020) demonstrated that poisoning a single transaction is sufficient to inject a falseticker directly into Chronos’s pruning filter, collapsing the statistical defence entirely.

Hardening the time-selection algorithm while leaving the name-resolution layer unauthenticated does not close the vector. It widens it.

These are not bugs waiting for patches

The Kiss-of-Death rate-limiting isolation via “Priming the Pump” (CVE-2015-7705) is unresolved by design. The rate-limiting mechanism that enables it is a core feature of the NTP specification. IPv4 fragmentation injection operates at Layer 3 — below the NTP daemon’s visibility. The Small-Step-Big-Step residual window exists because NTP must solve an unsolvable bootstrap problem. Pool injection and Marzullo manipulation are properties of open, volunteer-run infrastructure with no admission controls. DNS poisoning as a time attack vector exists because NTP depends on DNS and DNS was not designed to be authenticated.

The protocol is forty years old. It was designed for a cooperative internet. The threat model has changed. The protocol has not.

The industry’s response is Network Time Security (NTS), which addresses the authentication gap at the transport layer. NTS is a necessary step. The next section explains why deploying NTS against a public provider is not sufficient.

CNX Precision Time eliminates pool membership entirely — there is no geo-DNS allocation, no volunteer operator pool, and no Marzullo consensus to subvert. Clients synchronise to a single fixed, authenticated Stratum-1 source. CVE-2015-5300 is addressed by NTS authenticated transport — no unauthenticated large step is accepted. DNS cache poisoning is closed by removing DNS from the synchronisation path via a local hostname pin. The Chronos paradox does not apply: CNX clients issue one authenticated session, not 24 unauthenticated queries.