Area41 2024 - Ein Rückblick
Michael Schneider
So sichern Sie das Network Time Protocol
Die meisten Angriffe basieren auf einer Machine-in-the-Middle-Attacke (MITM). Sobald Angreifer sich in dieser privilegierten Position befinden, können diese Antworten des Servers manipulieren und damit eine falsche Zeit vorgeben, die Antworten von Servern verzögern oder vollständig verwerfen um zu verhindern, dass der Client weiterhin seine Systemzeit mit einem oder mehreren Servern abgleichen kann. Wir demonstrieren ein solcher Angriff, zeigen mit welchen Massnahmen die Systemzeit geschützt werden kann und stellen mit dem Protokoll Network Time Security eine Erweiterung des NTP-Protokolls zum Schutz gegen solche Angriffe vor.
Für einen Angriff müssen sich Angreifer in einer Position befinden, um den Netzwerkverkehr von Client und Server mitlesen und manipulieren zu können. Dies kann in Form einer MITM-Attacke realisiert werden. Für das folgende Beispiel gibt es die Akteure:
Mallory wird einen Angriff auf Bob durchführen und versuchen dessen Systemzeit zu manipulieren. Vor dem Angriff verfügt Bob über eine synchronisierte Systemzeit und verwendet als NTP-Client die Software chrony und vier Zeitserver des NTP Pool Projekts.
[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
Der Aufruf des Befehls timedatectl
zeigt, dass auf dem System alles in Ordnung scheint.
Als Demonstration für einen Angriff kann das Skript von Davide Bove verwendet werden. Das Skript musste noch angepasst werden, und steht als Fork zur Verfügung. Bei der Ausführung des Skripts wird automatisch eine ARP-Spoofing-Attacke durchgeführt und danach die Systemzeit aller übermittelten NTP-Pakete manipuliert.
[user@mallory ~]$ sudo python3 ntpspoof.py 192.168.244.130 eth0 Running ARP spoofing for target: 192.168.244.130 using the router: 192.168.244.2 [*] waiting for NTP packages Received package for: 192.168.244.130 -> Modified! Received package for: 192.168.244.130 -> Modified! Received package for: 192.168.244.130 -> Modified!
Das Skript wurde auf dem System Mallory gestartet und sobald eine Zeitsynchronisation durchgeführt wurde, wurden die Pakete manipuliert. Der Angriff verlieft erfolgreich, was ersichtlich ist in der Meldung von chrony, dass die Systemzeit um 486805679 Sekunden falsch läuft und korrigiert wurde.
[user@bob ~]$ sudo chronyd -q "server 0.ch.pool.ntp.org 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
Auch die Ausgabe der Systemzeit zeigt, dass der Angriff erfolgreich war und das System Bob eine neue Systemzeit in der Zukunft übernommen hatte.
Da die Übertragung von NTP-Paketen weder verschlüsselt noch signiert erfolgt, kann auf Protokollebene keine Mitigation gegen solche Angriffe vorgenommen werden. Es ist aber möglich in der Konfiguration von chrony die Systemzeit von zu grossen respektive abrupten Zeitsprüngen zu schützen. In der FAQ-Sektion von chrony ist beschrieben, wie die Systemzeit geschützt werden kann. Die Einstellung maxchange
gibt beispielsweise vor, dass der grösstmögliche Zeitsprung nicht mehr als 100 Sekunden betragen kann, ansonsten tritt ein Fehler auf und der chrony Daemon beendet sich.
minsources 3 maxchange 100 0 0 makestep 0.001 1 maxdrift 100 maxslewrate 100 driftfile /var/lib/chrony/drift rtcsync
Die Konfiguration von chrony wurde um die obenstehenden Einstellungen erweitert, und der Angriff nochmals durchgeführt.
systemd[1]: Started NTP client/server. chronyd[3072]: Selected source 31.3.135.232 (1.ch.pool.ntp.org) 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'.
In den Logs von chrony zeigt sich nun, dass die Abweichung mit der Zeit in den manipulierten NTP-Pakete über den erlaubten 100 Sekunden war und sich chrony daher selbst beendet hat. Die Manipulation der System war zwar nicht möglich, aber die Zeitsynchronisation ist immer noch ungeschützt. Zudem können Angreifer die Zeit weiterhin manipulieren, einfach mit kleineren Schritten.
Der Mechanismus Network Time Security (NTS) wurde im RFC 8915 spezifiziert und verwendet Transport Layer Security (TLS) und Authenticated Encryption with Associated Data (AEAD) um den Client-Server-Modus von NTP abzusichern. NTS umfasst die Subprotokolle NTS Key Establishment (NTS-KE), was die initiale Authentisierung und die Einrichtung der Schlüssel über TLS handhabt, sowie NTS Extension Fields for NTPv4, welches die Verschlüsselung und Authentisierung von Erweiterungsfeldern in NTP-Paketen während der Zeitsynchronisation steuert.
Beim Initialaufbau verbindet sich der NTP-Client mit einem NTS-KE-Server über den NTS-TCP-Port, normalerweise 4460/tcp, und es wird ein TLS-Handshake durchgeführt. Über den TLS-Kanal werden dann weitere Parameter ausgehandelt und der Server sendet dem Client Cookies, dies zusammen mit dem zu verwendenden NTP-Server. Zudem wird über TLS Key Export, definiert in RFC 5705, Schlüsselmaterial ausgetauscht. Danach ist die NTS-KE-Phase abgeschlossen und der NTP-Client braucht zukünftig keine weitere Verbindung mehr mit dem NTS-KE-Server aufzubauen.
Bei der Zeitsynchronisation sendet der NTP-Client dann ein Paket, dass mehrere Erweiterungsfelder enthält, unter anderem befindet sich dabei das Cookie und ein Authentication-Tag, der aus dem Schlüsselmaterial aus dem NTS-KE-Handshake generiert wurde. Der NTP-Server verwendet das Cookie um server-seitig auf das Schlüsselmaterial zuzugreifen und sendet schlussendlich eine authentisierte Antwort zurück. Neben den Zeitangaben umfasst diese Antwort auch ein neues Cookie, das im nächsten Request des Clients verwendet wird.
Der NTP-Client Chrony unterstützt NTS seit der Version 4. In der Konfiguration von Chrony kann bei jedem Zeitserver die Option NTS aktiviert werden – falls der Zeitserver NTS unterstützt. Zudem sollte die Option ntsdumpdir /var/lib/chrony
in die Konfigurationsdatei aufgenommen werden, damit die NTS-Schlüssel und Cookies gespeichert werden und der NTS-KE-Handshake nicht nach jedem Neustart des Dienst durchgeführt werden muss. Eine Sammlung von Zeitservern mit NTS liegt im GitHub Gist Time Servers with NTS support vor.
Die Datei /etc/chrony.conf
wird entsprechend um eine Liste von Servern ergänzt. Es empfiehlt sich nicht Zeitserver ohne NTS- und solche mit NTS-Unterstützung zu mischen.
server time.cloudflare.com iburst nts maxdelay 0.1 server ntp.trifence.ch iburst nts maxdelay 0.1 server ntp.zeitgitter.net iburst nts maxdelay 0.1 server ntp.3eck.net iburst nts maxdelay 0.1 server nts.netnod.se iburst nts maxdelay 0.1 server ptbtime1.ptb.de iburst nts maxdelay 0.1 server ptbtime2.ptb.de iburst nts maxdelay 0.1 server ptbtime3.ptb.de iburst nts maxdelay 0.1
Danach kann mit dem Befehl chronyc -N authdata
geprüft werden, ob der NTS-KE-Handshake erfolgreich war.
[user@bob ~]$ sudo chronyc -N authdata Name/IP address Mode KeyID Type KLen Last Atmp NAK Cook CLen ========================================================================= time.cloudflare.com NTS 1 15 256 188m 0 0 8 100 ntp.trifence.ch NTS 2 15 256 191m 0 0 8 100 ntp.zeitgitter.net NTS 2 15 256 191m 0 0 8 100 ntp.3eck.net NTS 2 15 256 191m 0 0 8 100 ptbtime1.ptb.de NTS 2 15 256 191m 0 0 8 100 ptbtime2.ptb.de NTS 2 15 256 191m 0 0 8 100 ptbtime3.ptb.de NTS 2 15 256 191m 0 0 8 100
Die Felder KeyID, Type, und KLen sollten nicht 0 sein. Eine mögliche Fehlerquelle wäre, dass die Firewall die ausgehende Verbindung auf den Port 4460/tcp blockt. Der Status der Zeitsynchronisation kann mittels des Befehls chronyc -N sources
verifiziert werden.
[user@bob ~]$ chronyc -N sources MS Name/IP address Stratum Poll Reach LastRx Last sample =============================================================================== ^+ time.cloudflare.com 3 10 377 124 +532us[ +532us] +/- 18ms ^+ ntp.trifence.ch 2 10 377 828 -617us[ -437us] +/- 12ms ^+ ntp.zeitgitter.net 3 10 377 356 +81us[ +81us] +/- 11ms ^* ntp.3eck.net 2 10 377 439 +330us[ +515us] +/- 6230us ^- ptbtime1.ptb.de 1 10 377 105 +494us[ +494us] +/- 18ms ^- ptbtime2.ptb.de 1 10 377 373 +218us[ +218us] +/- 19ms ^- ptbtime3.ptb.de 1 10 377 613 +745us[ +928us] +/- 18ms
Die Spalte Reach hat idealerweise den Wert 377
. Dieser Wert gibt an, dass die letzten 8 Abfragen eine valide Antwort ergaben, inklusive der NTS-Validierung. Wenn nun der MITM-Angriff nochmals durchgeführt wird, dann verwirft chrony die Antworten und der Wert in der Spalte Reach bleibt auf 0
.
[user@bob ~]$ chronyc -N sources MS Name/IP address Stratum Poll Reach LastRx Last sample =============================================================================== ^? time.cloudflare.com 0 7 0 - +0ns[ +0ns] +/- 0ns ^? ntp.trifence.ch 0 7 0 - +0ns[ +0ns] +/- 0ns ^? ntp.zeitgitter.net 0 7 0 - +0ns[ +0ns] +/- 0ns ^? ntp.3eck.net 0 7 0 - +0ns[ +0ns] +/- 0ns ^? ptbtime1.ptb.de 0 7 0 - +0ns[ +0ns] +/- 0ns ^? ptbtime2.ptb.de 0 7 0 - +0ns[ +0ns] +/- 0ns ^? ptbtime3.ptb.de 0 7 0 - +0ns[ +0ns] +/- 0ns
Durch den Einsatz von NTS kann die Manipulation von NTP-Paketen durch einen MITM-Angriff verhindert werden. Angreifer haben zwar noch die Möglichkeit die Zeitsynchronisation zu beeinträchtigen, da der NTP-Client keine gültigen Antworten mehr erhält.
Mit der Einführung von NTS können bekannte Angriffe gegen NTP abgewehrt werden. NTS wird noch nicht in allen NTP-Clients unterstützt und nicht alle Linux Distributionen verfügen über die aktualisierten Versionen von Clients, die NTS implementiert haben. Zudem existieren im August 2022 erst wenige Server mit NTS-Unterstützung. Für Windows gibt es noch keine Unterstützung von NTS. Für eine grossflächige Verbreitung von NTS braucht es also noch Zeit.
Da eine korrekte Systemzeit für viele weitere Protokolle essentiell ist, ist die Einführung einer Absicherung des NTP-Protokolls ein wichtiger und notwendiger Schritt. Der Einsatz von NTS auf den Zeitservern in der Firmeninfrastruktur sollte daher geplant und in nächster Zeit umgesetzt werden.
Unsere Spezialisten kontaktieren Sie gern!
Michael Schneider
Michael Schneider
Michael Schneider
Michael Schneider
Unsere Spezialisten kontaktieren Sie gern!