Penetration Test Report (Cure53): pentest report ntpsec

Dr.-Ing. Mario Heiderich, Cure53
Rudolf Reusch Str. 33
D 10367 Berlin
cure53.de · mario@cure53.de
Pentest-Report NTPsec 01.2017
Cure53, Dr.-Ing. M. Heiderich, M. Wege, MSc. N. Krein, BSc. D. Weißer
Index
Introduction
Scope
Test Coverage
Identified Vulnerabilities
NTP-01-002 NTP: Buffer Overflow in ntpq when fetching reslist (Critical)
NTP-01-012 NTPsec: Authenticated DoS via Malicious Config Option (High)
NTP-01-015 NTPsec: Regression in ctl_putdata() leads to Endless Loop (High)
NTP-01-016 NTPsec: Denial of Service via Malformed Config (High)
Miscellaneous Issues
NTP-01-001 NTPsec: Makefile does not enforce Security Flags (Low)
NTP-01-003 NTPsec: Improper use of snprintf() in mx4200_send() (Low)
NTP-01-004 NTPsec: Potential Overflows in ctl_put() functions (Medium)
NTP-01-005 NTPsec: Off-by-one in Oncore GPS Receiver (Low)
NTP-01-006 NTP: Copious amounts of Unused Code (Info)
NTP-01-007 NTP: Data Structure terminated insufficiently (Low)
NTP-01-008 NTP: Stack Buffer Overflow from Command Line (Low)
NTP-01-009 NTP: Privileged execution of User Library code (Low)
NTP-01-010 NTP: ereallocarray()/eallocarray() underused (Info)
NTP-01-011 NTP: ntpq_stripquotes() returns incorrect Value (Low)
NTP-01-013 NTPsec: Inclusion of obsolete NTPclassic-dependent Script (Info)
NTP-01-014 NTP: Buffer Overflow in DPTS Clock (Low)
Conclusion
Cure53, Berlin · 03.02.17 1/18
Dr.-Ing. Mario Heiderich, Cure53
Rudolf Reusch Str. 33
D 10367 Berlin
cure53.de · mario@cure53.de
Introduction
“Welcome to the NTPsec project - a secure, hardened, and improved implementation of
Network Time Protocol derived from NTP Classic, Dave Mills’s original.
NTPsec, as its name implies, is a more secure NTP. Our goal is to deliver code that can
be used with confidence in deployments with the most stringent security, availability, and
assurance requirements.
Towards that end we apply best practices and state-of-the art technology in code
auditing, verification, and testing. We begin with the most important best practice: true
open-source code review. The NTPsec code is available in a public git repository. One of
our goals is to support broader community participation.”
From https://www.ntpsec.org/
This report documents the findings of a source code audit of the NTPsec software. The
project was completed by Cure53 team in January 2017. Four members of the Cure53
participated in this assignment, which required a total of thirty-two days of testing in
order for a satisfactory level of coverage to be reached.
The audit constituted a joint project dedicated to both the NTPsec and the NTP. The
code base of the NTP was examined in parallel and the two components of the scope
were given the same amount of attention and scrutiny. While this document primarily
pertains to the NTPsec element, the relevant results applicable to NTP are also briefly
recalled. At the same time, a separate report has been created to discuss the NTP
issues in detail and at length. In the latter NTP-related document, the discoveries
connected to NTPsec are analogically given less space and specificity in reporting.
As for the test’s approach, the investigations were rooted in the so-called white-box
methodology, meaning that the testing team was granted full access to relevant sources
and the like. Prior to initiating the audit, the Cure53 team established solid
communication channels for the two respective software items in scope, liaising with the
development teams of the NTPsec and NTP, respectively.
The document proceeds with describing the test’s scope, then discusses coverage and
findings, ultimately delivering conclusions and verdicts about the general level of security
discovered, and the state of the audited code for the two software products in question.
Cure53, Berlin · 03.02.17 2/18
Dr.-Ing. Mario Heiderich, Cure53
Rudolf Reusch Str. 33
D 10367 Berlin
cure53.de · mario@cure53.de
Scope
• NTPsec 0.9.6
◦ https://ftp.ntpsec.org/pub/releases/ntpsec-0.9.6.tar.gz
Test Coverage
One can consult an overview of the test’s coverage below. The listing shows the
percentage of the coverage reached by the code audit per directory. All directories
belong to the downloaded code base.
Coverage in % SLOC Directory
100 38094 ntpd
20 6175 libntp
n/a 5933 tests
100 3955 include
n/a 3884 ntpclients
n/a 3745 libparse
40 2822 libisc
n/a 2220 wafhelpers
n/a 1679 pylib
n/a 950 libjsmn
100 483 ntpfrob
100 471 libsodium
100 435 ntptime
100 416 attic
n/a 130 devel
n/a 111 contrib
The directories marked with “n/a” were explicitly left out of scope along with all of the
subcomponents written in Python and the testing framework unity.
Cure53, Berlin · 03.02.17 3/18
Dr.-Ing. Mario Heiderich, Cure53
Rudolf Reusch Str. 33
D 10367 Berlin
cure53.de · mario@cure53.de
Identified Vulnerabilities
The following sections list both vulnerabilities and implementation issues spotted during
the testing period. Note that findings are listed in a chronological order rather than by
their degree of severity and impact. The aforementioned severity rank is simply given in
brackets following the title heading for each vulnerability. Each vulnerability is
additionally given a unique identifier (e.g. NTP-01-001) for the purpose of facilitating any
future follow-up correspondence.
NTP-01-002 NTP: Buffer Overflow in ntpq when fetching reslist (Critical)
Note: This issue affects NTP only and is not present in the NTPsec code.
A stack buffer overflow can be triggered by a malicious server when a client (using ntpq)
requests the restriction list from the server. This is due to a missing length check in the
reslist() function. It occurs whenever the function parses the server’s response and
encounters a flagstr variable of an extensive length. The string will be copied into a
fixed-size buffer, leading to an overflow on the function’s stack-frame.
NTP-01-012 NTPsec: Authenticated DoS via Malicious Config Option (High)
Note: This issue affects both NTP and NTPsec and is present in both code bases.
A vulnerability found in the NTPsec server allows an authenticated remote attacker to
crash the daemon by sending an invalid setting via the :config function. The unpeer
option expects either a number or an address as argument. In case the value is “0”, a
segmentation fault occurs. An example is given in the following listing.
Configurating the server remotely:
ntpq> :config unpeer 0
Keyid: 1
MD5 [CREDENTIAL_REDACTED]: timed out, nothing received
***Request timed out
The submission of the configuration crashes the NTPsec server right away. An
observation performed with the GDB demonstrates that the error occurs in ntp_config.c
and is due to a null pointer dereference.
Segmentation fault:
(gdb) r
[...]
Program received signal SIGSEGV, Segmentation fault.
Cure53, Berlin · 03.02.17 4/18
Dr.-Ing. Mario Heiderich, Cure53
Rudolf Reusch Str. 33
D 10367 Berlin
cure53.de · mario@cure53.de
0x[PII_REDACTED]407c1e in config_unpeers (ptree=0x65c0b0)
at ../../ntpd/ntp_config.c:3042
3042 AF(&peeraddr) = curr_unpeer->addr->type;
(gdb) p *curr_unpeer
$1 = {link = 0x0, assocID = 0, addr = 0x0}
The unpeer configuration options are processed in the config_unpeers() function in
ntpd/ntp_config.c. The curr_unpeer struct contains the provided parameter which is
either a number or an address. While assocID holds numeric values, the addr is a
pointer to another struct for when the parameter is an address. If the curr_unpeer-
>assocID is zero, then the code expects curr_unpeer->addr. However, this is not
necessarily the case. Setting “unpeer 0” leads to a completely empty curr_unpeer struct
and thereby crashes the server.
Affected File:
ntpsec/ntpd/ntp_config.c
Affected Code:
config_unpeers(
config_tree *ptree
)
{
[...]
curr_unpeer = HEAD_PFIFO(ptree->unpeers);
for (; curr_unpeer != NULL; curr_unpeer = curr_unpeer->link) {
[...]
if (curr_unpeer->assocID) {
[...]
continue;
}
ZERO(peeraddr);
AF(&peeraddr) = curr_unpeer->addr->type;
Verifying the addr element in case the assocID is zero is a way towards mitigating thi