Securing NTP against MITM attacks

By on 9 Dec 2022

Category: Tech matters

Tags: , , ,

Blog home

The Network Time Protocol (NTP) is one of the oldest Internet protocols that is still widely used. The protocol has no security mechanisms, communication is unencrypted, and there is no authentication between client and server or safeguards against manipulation of network packets. Attacks against NTP can have a serious impact because other protocols are dependent on the accuracy of the system time, such as DNSSEC, Kerberos, and TLS.

Most attacks are based on a machine-in-the-middle (MITM) attack. Once attackers are in this privileged position, they can manipulate server responses to provide a false time, delay or completely drop server responses to prevent the client from continuing to synchronize its system time with one or more servers. This post will demonstrate such an attack, show what measures can be taken to protect the system time and explain the Network Time Security (NTS) protocol, an extension of the NTP protocol to protect against such attacks.

Key points
This is how you secure NTP:
• NTP is an old protocol without security capabilities.
• Protocols like DNSSEC, Kerberos and TLS depend on a correct system time.
• MITM attacks can be used to manipulate NTP responses and thus the system time.
• The system time can be protected against abrupt time jumps by applying hardening measures.
• NTS adds authentication and encryption to NTP and protects against MITM attacks.

Attacks against NTP

An attack requires attackers to be in a position to eavesdrop and manipulate the network traffic of the client and server. This can be done in the form of a MITM attack. For the following example, here are the actors:

  • Bob –
  • Mallory –
  • Gateway –

Mallory will launch an attack on Bob and try to manipulate his system time. Before the attack, Bob synchronizes system time using Chrony and four ‘time servers’ of the NTP Pool Project:

[user@bob ~]$ timedatectl 
               Local time: Tue 2022-08-16 17:08:12 CEST
           Universal time: Tue 2022-08-16 15:08:12 UTC
                 RTC time: Tue 2022-08-16 15:08:12
                Time zone: Europe/Zurich (CEST, +0200)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

The command timedatectl shows that everything is in order on this system.

To demonstrate an attack, a script by Davide Bove can be used. The script has to be tweaked and is available as a fork. When the script is started, an Address Resolution Protocol (ARP) spoofing attack is automatically launched and then the system time of all transmitted NTP packets between the server and client is manipulated:

[user@mallory ~]$ sudo python3 eth0
Running ARP spoofing for target: using the router:
[*] waiting for NTP packages
Received package for: -> Modified!
Received package for: -> Modified!
Received package for: -> Modified!

The script was started on Mallory’s system and as soon as a time was synchronized, the packets were manipulated. The attack was successful, which is evident in the message from Chrony that the system time is wrong by 486,805,679 seconds, and was corrected.

[user@bob ~]$ sudo chronyd -q "server iburst"
2022-08-16T15:11:20Z chronyd version 4.2 starting (+CMDMON +NTP +REFCLOCK +RTC +PRIVDROP +SCFILTER +SIGND +ASYNCDNS +NTS +SECHASH +IPV6 +DEBUG)
2022-08-16T15:11:20Z Initial frequency -9.183 ppm
2022-08-16T15:11:24Z System clock wrong by 486805679.997304 seconds (step)
2038-01-18T22:59:24Z chronyd exiting

[user@bob ~]$ timedatectl 
               Local time: Mon 2038-01-18 23:59:31 CET
           Universal time: Mon 2038-01-18 22:59:31 UTC
                 RTC time: Tue 2022-08-16 15:11:31
                Time zone: Europe/Zurich (CET, +0100)
System clock synchronized: no
              NTP service: inactive
          RTC in local TZ: no

The system time output also shows that the attack was successful and that Bob had accepted a new system time in the future.

Protecting system time

Because the transmission of NTP packets is neither encrypted nor signed, no mitigation against such attacks can be implemented at the protocol level. However, it is possible to protect the system time from time jumps that are too large and abrupt in Chrony’s configuration. Chrony’s FAQ section describes how system time can be protected. The setting maxchange, for example, specifies that the largest possible time jump cannot exceed 100 seconds, otherwise an error occurs and the Chrony daemon terminates:

minsources 3
maxchange 100 0 0
makestep 0.001 1
maxdrift 100
maxslewrate 100
driftfile /var/lib/chrony/drift

The configuration of Chrony was enhanced with the above settings and the attack was relaunched.

systemd[1]: Started NTP client/server.
chronyd[3072]: Selected source (
chronyd[3072]: Adjustment of 486753299.993 seconds exceeds the allowed maximum of 100.000 seconds (exiting)
chronyd[3072]: chronyd exiting
systemd[1]: chronyd.service: Main process exited, code=exited, status=1/FAILURE
systemd[1]: chronyd.service: Failed with result 'exit-code'.

The Chrony logs now show that the time deviation in the manipulated NTP packets was above the permitted 100 seconds and Chrony, therefore, terminated itself. Although it was not possible to manipulate the system, the time synchronization is still unprotected. Moreover, attackers can still manipulate the time, simply with smaller steps.


The NTS mechanism was specified in RFC 8915 and uses Transport Layer Security (TLS) and Authenticated Encryption with Associated Data (AEAD) to secure the client-server mode of NTP. NTS includes the sub-protocols NTS Key Establishment (NTS-KE), which handles initial authentication and key establishment over TLS, and NTS Extension Fields for NTPv4, which controls the encryption and authentication of extension fields in NTP packets during time synchronization.

During initial setup, the NTP client connects to an NTS-KE server via the NTS TCP port, usually 4460/TCP, and performs a TLS handshake. Additional parameters are then negotiated via the TLS channel and the server sends cookies to the client along with the NTP server to be used. In addition, the key material is exchanged via TLS Key Export, defined in RFC 5705. After this, the NTS-KE phase is completed and the NTP client does not need to establish any further connection with the NTS-KE server in the future.

During time synchronization, the NTP client then sends a packet that contains several extension fields, including the cookie, and an authentication tag generated from the NTS-KE handshake’s key material. The NTP server uses the cookie to access the key material on the server side and finally sends back an authenticated response. In addition to the time information, this response also includes a new cookie that is used in the client’s next request.

NTP client configuration

NTP client, Chrony, has supported NTS since version 4. In the configuration of Chrony, the option NTS can be added to each time server — if the time server supports NTS. In addition, the option ntsdumpdir /var/lib/chrony should be included in the configuration file so that the NTS keys and cookies are stored, and the NTS-KE handshake does not have to be performed after each restart of the service. A collection of time servers with NTS is available in the GitHub Gist time servers with NTS support.

A list of servers is added to the /etc/chrony.conf file accordingly. It is not recommended to mix time servers without NTS and those with NTS support.

server iburst nts maxdelay 0.1
server iburst nts maxdelay 0.1
server iburst nts maxdelay 0.1
server iburst nts maxdelay 0.1
server iburst nts maxdelay 0.1
server iburst nts maxdelay 0.1
server iburst nts maxdelay 0.1 
server iburst nts maxdelay 0.1

Afterwards, the command chronyc -N authdata can be used to check whether the NTS-KE handshake was successful.

[user@bob ~]$ sudo chronyc -N authdata
Name/IP address             Mode KeyID Type KLen Last Atmp  NAK Cook CLen
=========================================================================          NTS     1   15  256 188m    0    0    8  100              NTS     2   15  256 191m    0    0    8  100           NTS     2   15  256 191m    0    0    8  100                 NTS     2   15  256 191m    0    0    8  100              NTS     2   15  256 191m    0    0    8  100              NTS     2   15  256 191m    0    0    8  100              NTS     2   15  256 191m    0    0    8  100

The fields KeyID, Type, and KLen should not be 0. A possible source of error would be that the firewall blocks the outgoing connection on port 4460/TCP. The status of the time synchronization can be verified using the command chronyc -N sources.

[user@bob ~]$ chronyc -N sources
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
^+           3  10   377   124   +532us[ +532us] +/-   18ms
^+               2  10   377   828   -617us[ -437us] +/-   12ms
^+            3  10   377   356    +81us[  +81us] +/-   11ms
^*                  2  10   377   439   +330us[ +515us] +/- 6230us
^-               1  10   377   105   +494us[ +494us] +/-   18ms
^-               1  10   377   373   +218us[ +218us] +/-   19ms
^-               1  10   377   613   +745us[ +928us] +/-   18ms

The Reach column should ideally have the value 377. This value indicates that the last eight queries resulted in a valid response, including the NTS validation. If the MITM attack is performed again, Chrony discards the responses and the value in the Reach column remains 0.

[user@bob ~]$ chronyc -N sources
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
^?           0   7     0     -     +0ns[   +0ns] +/-    0ns
^?               0   7     0     -     +0ns[   +0ns] +/-    0ns
^?            0   7     0     -     +0ns[   +0ns] +/-    0ns
^?                  0   7     0     -     +0ns[   +0ns] +/-    0ns
^?               0   7     0     -     +0ns[   +0ns] +/-    0ns
^?               0   7     0     -     +0ns[   +0ns] +/-    0ns
^?               0   7     0     -     +0ns[   +0ns] +/-    0ns

By using NTS, the manipulation of NTP packets by a MITM attack can be prevented. However, attackers are still able to affect the time synchronization because the NTP client no longer receives valid responses.


The introduction of NTS allows defending against known attacks against NTP. NTS is not yet supported in all NTP clients and not all Linux distributions have the updated versions of clients that have implemented NTS. In addition, as of August 2022, only a few servers with NTS support exist. For Windows, there is no support for NTS yet. So, it will take some time for NTS to become widespread.

Since a correct system time is essential for many other protocols, the introduction of a safeguard for the NTP protocol is an important and necessary step. The use of NTS on time servers in a company’s infrastructure should therefore be planned and implemented in the near future.

Michael Schneider (Twitter, Mastodon) is an information security expert focused on penetration testing, hardening, and the detection of vulnerabilities in operating systems. He is well-known for a variety of tools written in PowerShell to find, exploit, and mitigate weaknesses.

This post is adapted from the original at SCIP Labs blog.

Rate this article

The views expressed by the authors of this blog are their own and do not necessarily reflect the views of APNIC. Please note a Code of Conduct applies to this blog.

Leave a Reply

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