MaraDNS' security
For people who just want to quickly get current with MaraDNS' security
history should jump to the history section.
MaraDNS should be a secure DNS server.
The reason why I say should be instead of "is" is because I
find claims of security very pretentious. There is no way that I can
guarantee that a piece of code as complex as a recursive DNS server
is completely free from security bugs.
What I can guarantee, however, is that such bugs are very unlikely in
MaraDNS, since the design has security checks and balances which
minimize the chance of there being a security hazard in the code.
Why code is insecure
The main reason why code is insecure is because the code in question has
undefined results when fed data which is in a different form than what the
author of the code expected. The simplest case of this is the
buffer
overflow, where a program is fed a string far longer than the program
was designed to handle.
Another example is the "cache poison" bug which ancient versions of
another DNS implementation had. With this bug, it was a trivial matter to
tell the DNS server that, for example, www.yahoo.com had an ip address of
say, 10.69.69.69, which really points to some sleazy
site that installs spyware. Why did this bug exist? Because the
original authors of this server did not expect remote servers to
deliberately give out incorrect IP addresses.
How MaraDNS avoids these problems
First of all, MaraDNS uses a special string library which is resistant to
buffer overflows. It does this by having a maximum allowed size for a
string--any attempt to make a string larger than the maximum allowed size
causes the string library to return an error instead of overflowing a
buffer. In addition, the string library allocates an extra three bytes
for each string object, as a cushion against possible boundary conditions
(there was one case with another program which strived to be secure where
a one-byte buffer overflow resulted in a remote root exploit).
Second of all, MaraDNS protects herself from cache poisoning without ever
discarding glue records is by handling out-of-bailiwick records
differently, depending on where the offending records are. The actual
rules are fairly complex, and detailed in a document
called "cache.poison.protection
".
Third of all, I have extensively read Dan Bernstein's notes on DNS
implementation before implementing MaraDNS. Two ideas for
implementing DNS security discussed on Dan's pages have been implemented in
MaraDNS:
-
When the recursive nameserver is performing queries, MaraDNS uses a
securely generated pseudo-random-number-generator to generate the query ID,
and the lower 12 bits of the query source port. This means that a given
attempt to spoof a reply to MaraDNS has less than a 1 in 250 million
chance of succeeding.
-
MaraDNS uses a FIFO queue to delete unused records when the cache
starts to fill up. The algorithm is simple: Every time a record is
accessed, it is placed at the top of the list. When memory fills up,
MaraDNS deletes records at the bottom of the list. This allows MaraDNS
to act in a very graceful manner when the cache starts to fill up.
Some known security problems are avoided: MaraDNS does not use printf() in
a manner which would make format string vulnerabilities possible; MaraDNS
does not use any of the potentially dangerous globing functions; and
MaraDNS will not have signal handlers until I can figure out a way to make
sure that the DNS server is not vulnerable to the known security pitfalls
of poor signal handler construction.
I go though the code, and when I find anything which has the possibility
of allowing the data to be in an undefined state, I revise the code in
question. For example, when I was looking through the code in the 0.8.35
release of MaraDNS; I found a case where the data could potentially
become undefined. In more detail, if certain strings could not be
allocated or copied over--cases which can never happen--the code which
removes elements from the cache would attempt to free() unallocated memory
later on. Even though this was a case where it was impossible to exploit
the code in question, I felt it was prudent to update the code to not have
this problem--hence the vaguely worded "security update" for the 0.8.99
release of MaraDNS.
MaraDNS also mandates that the server is run as an unprivileged user, and
strongly encourages MaraDNS to be run in a chroot() environment. In
addition, the DNS cache uses a separate data structure than the local DNS
records, making it difficult, if not impossible, for the cache at affect
the local records. This design means that, even if there is a security
hole in MaraDNS, the possibility of such a security hole allowing the
attacker having elevated privileges is next to zero.
The security history of MaraDNS
There have been a few security problems found with MaraDNS: two fairly
major, and one minor security bug. There was also a major security problem
caused by broken behavior in Linux's kernel, a minor security problem in
the
fetchzone tool in the 1.1/1.2 branch of MaraDNS, and
some theoretical (less than minor) security problems caused by some
research in to AES' implementation on modern cached processors.
Here are all of the security problems ever discovered with MaraDNS:
-
The first major security problem was discovered by Roy Arends, one of the BIND
developers, and was caused by the fact that very early versions of
MaraDNS did not check to see whether a given DNS packet was a question
or an answer. This was fixed well before the 1.0 release of MaraDNS.
Since a DNS answer looks like a DNS question, with the exception of a
one-bit difference, this bug allowed an attacker to send a spoofed DNS
packet which would result in MaraDNS sending an answer to herself (or to
another MaraDNS server), which would result in another answer being sent,
and so on.
The reason this security glitch passed through was because of an
overzealous effort to honor the RFC spirit to be "liberal in what one
accepts and conservative in what one sends". Since then, I have gone over
the DNS spec to see if their are any other cases where a malformed packet
could cause this kind of security problem, and have made an effort that
any such cases in MaraDNS no longer exist.
Impact: Remote denial of service.
-
Another major security problem was found by myself when performing an
audit of the code during the beta test cycle. It involved the
decompression code, and was caused because DNS compression is difficult to
implement, and easy to create security holes with. I resolved this issue
by completely rewriting the code in question with security in mind.
This security problem was fixed in MaraDNS 0.9.01 (the rewrite came
later).
Impact: Remote denial of service.
-
Another major problem, which allowed a remote denial of service, was caused
by some broken behavior in the Linux kernel. People using BSD or other
kernels were not affected by this security problem. This security problem
was fixed in MaraDNS 1.0.28 and in MaraDNS 1.1.35.
Impact: Remote denial of service.
-
One old minor security problem involved the seed for the pseudo-random number
generator. In cases where there was an ASCII null in the key for the
pseudo-random number generator, MaraDNS would have less than a full 128
bits of entropy for the seed. There was also a related issue, even more
minor, where, in certain rare circumstances, multiple instances of MaraDNS
could potentially generate the same pseudo-random numbers, if two copies of
MaraDNS used the same static random seed file, and were started at the
same time. These issues were fixed before the release of MaraDNS 0.8.24.
Impact: Theoretical spoofing of DNS records.
-
Another minor problem, more recently discovered, was only present in the
development (1.1) branch of MaraDNS. The fetchzone tool did not
perform enough input validation and was vulnerable to specially formed
packets that could send out-of-bailiwick data. I fixed this problem
both ways; first by giving the fetchzone tool more input validation.
Later on, I modified the csv2 parser to not accept the kind of data which
would have triggered the fetchzone security bug. This issue was
fixed in MaraDNS 1.1.38 (the csv2 improvments appeared in MaraDNS
1.1.47).
Impact: Spoofing of DNS records.
-
A theoretical security problem with the underlying random number generator
that MaraDNS uses to generate secure random numbers was discovered by
D. J. Bernstein. Since the underlying random number generator uses a fairly
simple key schedule (well, a simple key schedule for a cryptographic routine),
and since the random number generator uses table lookups, modern CPUs will
very slighly vary (on the order of billionths of a second) in the amount
of time used to generate a secure random number, depending on the underlying
key. Bernstein needed to examine over 200 million packets, obtaining very
precise timing information on each packet, to extract a key.
I worked around this security problem by having the random number generator
rekey every million packets. These changes were done in MaraDNS 1.0.27 and
1.1.35.
Mailing
list posting describing this issue
Impact: Theoretical remote spoofing of DNS records.
-
More recently, Dag Arne Osvik, Adi Shamir (the "S" in RSA), and Eran Tromer
discovered some sophisticated cache data leakage attacks against AES,
the algorithm from which MaraDNS' secure random number generator is
derived. I have responded to this issue by tweaking MaraDNS' secure
random number generator to essentially not leak sensitive key data
via cache lookups. These updates were fixed in MaraDNS 1.0.35 and
MaraDNS 1.1.56.
Patch
which describes the issue and how I work around it
Impact: Theoretical local spoofing of DNS records.