Penetration Test Report (Cure53): Dnsmasq report

Dr.-Ing. Mario Heiderich, Cure53
Rudolf Reusch Str. 33
D 10367 Berlin
cure53.de · mario@cure53.de
Pentest-Report dnsmasq 05.-06.2016
Cure53, Dr.-Ing. Mario Heiderich, Mike Wege, Dario Weißer
Index
Introduction
Scope
Identified Vulnerabilities
DM -01-001 Uninitialized buffer leads to memory leakage ( Medium )
DM -01-003 Makefile lacks security parameters for gcc ( Low )
DM -01-006 Allocated memory is no t cleared ( Low )
Miscellaneous Issues
DM -01-002 Unchecked return value can lead to NULL pointer dereference ( Low )
DM -01-004 Wrong assumption abou t return value o f snprint f () / vsnprint f () ( Low )
DM -01-005 Hardcoded values in fscan f () forma t strings with aliased buffers ( Low )
Conclusion
Introduction
“Dnsmasq provides network infrastructure for small networks: DNS, DHCP, router
advertisement and network boot. It is designed to be lightweight and have a small
footprint, suitable for resource constrained routers and firewalls.
It has also been widely used for tethering on smartphones and portable hotspots, and to
support virtual networking in virtualisation frameworks. Supported platforms include
Linux (with glibc and uclibc), Android, *BSD, and Mac OS X. Dnsmasq is included in
most Linux distributions and the ports systems of FreeBSD, OpenBSD and NetBSD.
Dnsmasq provides full IPv6 support.”
From http :/ / www . thekelleys . org . uk / dnsmasq / doc .html
This report documents the findings of the penetration test and security assessment
conducted by the Cure53 team against the dnsmasq server. The project was generously
funded from the SOS programme run by Mozilla. Carried out over a period of two weeks
in May and June 2016, this assignment involved three members of the Cure53 team.
Cure53, Berlin · 06/22/16 1/10
Dr.-Ing. Mario Heiderich, Cure53
Rudolf Reusch Str. 33
D 10367 Berlin
cure53.de · mario@cure53.de
Regarding the approach and scope, the test was performed as a tool-assisted code
audit. Getting full coverage of the available dnsmasq sources was attempted and the
tests were aimed at several specific attacks and vulnerability patterns, namely buffer
overflows, parsing errors, information leaks, cryptographic errors and usage of weak
functions.
As for the results, the tests have only uncovered six issues, with three among them
classified as actual security vulnerabilities. It has to be underscored that neither issues
with “Critical” nor with “High” severity rankings were found, denoting that the discoveries
are not particularly salient in terms of their impact, scope, and the risk they pose.
Scope
• dnsmasq Sources
◦ http :/ / thekelleys . org . uk / gitweb /? p = dnsmasq . gi t ; a = summary
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. DM-01-001) for the purpose of facilitating any
future follow-up correspondence.
DM-01-001 Uninitialized buffer leads to memory leakage (Medium)
It was discovered that the application does not properly initialize the buffer for incoming
and outgoing packets. This leads to a partial disclosure of the previously received or
sent packets. Taking advantage of this issue made it possible to leak up to
[28+tftp_prefix_length] bytes from a packet that another party had sent to the server. The
attack is limited in scope and impact since only the network data can be leaked. It is
further constrained by the condition that the packets must be greater than 530 bytes in
size. However, it cannot be excluded that an attacker could work around these
limitations by using other services, although this option has not been investigated further
during this test.
In the following example one can observe a setup comprising the server, a victim and an
attacker. The victim sends a long packet (around 550 bytes) to the server. Since this is
only a proof of concept the content is inconsequential here.
Cure53, Berlin · 06/22/16 2/10
Dr.-Ing. Mario Heiderich, Cure53
Rudolf Reusch Str. 33
D 10367 Berlin
cure53.de · mario@cure53.de
Victim → Server:
perl -e 'print "LeakMe"x91' | nc -u 192.168.1.1 53
Having completed sending assignments, the daemon->packet buffer is filled with the
data from the client’s request. In essence, the attacker can now run their attack aimed at
leaking a few bytes. The packet that is used here is a TFTP1 request to read a file.
Attacker → Server:
perl -e 'print "\x00\x01".("A"x500)."\x00octet\x00"' | nc -u 192.168.1.1 69
The file is not accessible and the server responds with the corresponding error
message. Since the buffer holding the packet is not flushed, it still holds the contents
from the previous communication with the victim.
Server → Attacker:
17:39:33.558152 IP (tos 0x0, ttl 64, id 65025, offset 0, flags [none], proto UDP
(17), length 570)
192.168.1.1.47255 > 192.168.1.3.50423: [udp sum ok] UDP, length 542
0x0000: 0800 27d0 e35c 0800 2788 9fcd 0800 4500 ..'..\..'.....E.
0x0010: 023a fe01 0000 4011 f75c c0a8 0101 c0a8 .:....@..\......
0x0020: 0103 b897 c4f7 0226 9f78 0005 0000 6361 .......&.x....ca
0x0030: 6e6e 6f74 2072 6561 6420 2f6c 656c 2f41 nnot.read./lel/A
0x0040: [PII_REDACTED] [PII_REDACTED] AAAAAAAAAAAAAAAA
...
0x0210: [PII_REDACTED] [PII_REDACTED] AAAAAAAAAAAAAAAA
0x0220: [PII_REDACTED] 4c65 616b 4d65 4c65 A.ctet.eLeakMeLe
0x0230: 616b 4d65 4c65 616b 4d65 4c65 616b 4d65 akMeLeakMeLeakMe
0x0240: 4c65 616b 4d65 4c65 LeakMeLe
It is evident that the message sent to the attacker should by no means contain data sent
by the victim. The vulnerability is caused by two different flaws described next.
1. No initialization of buffers:
The packet buffer “packet” located in the “daemon” structure is used to store requests
and responses for different protocols. The server does not fork when UDP packets are
received, signifying that the buffer becomes reusable for different connections from
different hosts. Because the memory is not cleared between the connections, the buffer
might technically contain old data.
1 https :// en . wikipedia . org / wik i / Trivia l _ File _ Transfer _ Protocol
Cure53, Berlin · 06/22/16 3/10
Dr.-Ing. Mario Heiderich, Cure53
Rudolf Reusch Str. 33
D 10367 Berlin
cure53.de · mario@cure53.de
2. Incorrect use of snprintf():
It can be inferred from the existing schemes that the author of the code probably
believed that the return value of snprintf()2 equals the number of bytes written into the
destination buffer. In fact this is only the case if the source string is smaller or equal to
the limit value. Snprintf returns the number of bytes that could have been written if there
was no limitation in place.
The tftp_request function is called frequently in order to check for new requests on the
tftp socket. Basically, the file requests are handled here but, prior to a file being available
for reading, the accessibility needs to be verified. After checking the permissions and
potentially reading the requested file, a response of size len is sent to the client.
Affected File:
/src/tftp.c
Affected Code:
void tftp_request(struct listener *listen, time_t now)
{
…
if ((transfer->file = check_tftp_fileperm(&len, prefix))) {
...
}
while (sendto(transfer->sockfd, packet, len, 0,
(struct sockaddr *)&peer, sa_len(&peer)) == -1
&& errno == EINTR);
Check_tftp_fileperm performs a permission check and tries to open the file. If it turns out
impossible then an error message is generated and written into the packet buffer.
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix)
{
…
if ((fd = open(namebuff, O_RDONLY)) == -1)
{
if (errno == ENOENT)
{
*len = tftp_err(ERR_FNF, packet,
_("file %s not found"), namebuff);
return NULL;
}
else if (errno == EACCES)
2 https :// en . wikipedia . or