ISC BIND: Absturz durch negatives DNS-Caching

BIND ist einer der am häufigsten eingesetzten Nameserver. Vor wenigen Tagen ist eine Sicherheitslücke publik geworden, die beim negativem Caching von DNSSEC-signierten Zonen auftritt.

RFC 2308 spezifiziert zusätzlich zum DNS-Caching auch ein negatives DNS-Caching. Die Idee dahinter ist, dass nicht-existente Domains nicht ständig neu abgefragt werden müssen, sondern im Cache als nicht-existent gespeichert werden. “NXDOMAIN”- oder “NODATA/NOERROR”-DNS-Antworten landen so direkt im Cache. Die entdeckte Schwachstelle tritt auf, wenn dieses negative Caching zusammen mit DNSSEC zum Einsatz kommt.

DNSSEC wurde ursprünglich in RFC 2535 vorgestellt, doch diese Implementierung hat sich in der Praxis aufgrund zu komplexer Schlüsselverwaltung nicht durchgesetzt. Erst 2005 gab es eine Überarbeitung von DNSSEC, die nun immer häufiger zum Einsatz kommt. DNSSEC gewährt die Datenintegrität von DNS-Transaktionen durch ein
asymmetrisches Kryptosystem (private/öffentliche Schlüssel), das beispielsweise Cache-Poisoning-Attacken verhindern soll. Realisiert wird DNSSEC durch den RRSIG-Resource-Record, der einer Zone einen Zonenschlüssel zuordnet.

Neben den SOA-Records (Start of Authority) werden auch die RRSIG-Records im Cache gespeichert. Das oben erwähnte Problem tritt bei dem negativen Caching sehr großer RRSIG-Records auf. Eine erfolgreiche Attacke kann damit den Nameserver zum Absturz bringen.

Bei dem Programmierfehler handelt es sich um einen Off-by-One-Fehler. Das bedeutet, dass die Programmierer sich bei der Größe eines Puffers um eins vertan haben. Ein typischer Off-by-One-Fehler sieht so aus:

#include <stdio.h>
#define MAX_ENTRIES 10
int main(void)
{ int n, data[MAX_ENTRIES]; for (n=0; n<=MAX_ENTRIES; n++) data[n]=n; return 0;
}

Die For-Schleife beschreibt “data[MAX_ENTRIES]”, was falsch ist, da die Deklaration der Variable nur bis “MAX_ENTRIES-1” geht. C toleriert zwar diesen Fehler, beim Ausführen des Programms kann er aber unvorhersagbare Folgen haben, denn so werden andere Daten auf dem Stack überschrieben.

Die Attacke auf den Nameserver ist nicht ganz einfach durchzuführen. Zunächst muss der Angreifer im Besitz eines DNSSEC-signierten autoritativen DNS-Servers sein. Den darauf verwendete RRSIG-Eintrag wählt er dann sehr groß. Nun muss er nur noch einen anderen Nameserver dazu bringen, nach einem nicht-existentem Host seiner Domain zu fragen. Das ginge zum Beispiel einfach mit Hilfe einer Mail an einen Mitarbeiter jener Firma, deren Nameserver der Angreifer zum Absturz bringen möchte. In dieser Mail bringt er einen Link zu dem nicht-existenten Host unter. Ein Klick auf diesen Link führt dann zum Absturz des BIND-Servers.

Betroffen sind die BIND-Versionen 9.4-ESV-R3, 9.6-ESV-R2, 9.6.3, 9.7.1, 9.8.0 and jeweils folgende Versionen. Der Hersteller empfiehlt ein Upgrade.

Für diejenigen, die sich für allgemeine Details von DNS-Protokoll und Namensauflösung interessieren, empfiehlt es sich, ein wenig mit “dig” zu spielen. Beispielsweise so:

mark@tux:~$ dig +trace +additional -t A www.google.de
; <<>> DiG 9.7.0-P1 <<>> +trace +additional -t A www.google.de
;; global options: +cmd
. 344236 IN NS m.root-servers.net.
. 344236 IN NS g.root-servers.net.
. 344236 IN NS a.root-servers.net.
. 344236 IN NS k.root-servers.net.
. 344236 IN NS d.root-servers.net.
. 344236 IN NS l.root-servers.net.
. 344236 IN NS e.root-servers.net.
. 344236 IN NS b.root-servers.net.
. 344236 IN NS j.root-servers.net.
. 344236 IN NS h.root-servers.net.
. 344236 IN NS i.root-servers.net.
. 344236 IN NS c.root-servers.net.
. 344236 IN NS f.root-servers.net.
a.root-servers.net. 499908 IN A 198.41.0.4
c.root-servers.net. 604796 IN A 192.33.4.12
e.root-servers.net. 604729 IN A 192.203.230.10
;; Received 276 bytes from 131.142.10.1#53(131.142.10.1) in 1 ms
de. 172800 IN NS a.nic.de.
de. 172800 IN NS f.nic.de.
de. 172800 IN NS l.de.net.
de. 172800 IN NS s.de.net.
de. 172800 IN NS z.nic.de.
a.nic.de. 172800 IN A 194.0.0.53
f.nic.de. 172800 IN A 81.91.164.5
l.de.net. 172800 IN A 77.67.63.105
s.de.net. 172800 IN A 195.243.137.26
z.nic.de. 172800 IN A 194.246.96.1
a.nic.de. 172800 IN AAAA 2001:678:2::53
f.nic.de. 172800 IN AAAA 2a02:568:0:2::53
l.de.net. 172800 IN AAAA 2001:668:1f:11::105
;; Received 287 bytes from 199.7.83.42#53(l.root-servers.net) in 159 ms
google.de. 86400 IN NS ns2.google.com.
google.de. 86400 IN NS ns4.google.com.
google.de. 86400 IN NS ns3.google.com.
google.de. 86400 IN NS ns1.google.com.
;; Received 113 bytes from 77.67.63.105#53(l.de.net) in 86 ms
www.google.de. 345600 IN CNAME www.google.com.
www.google.com. 604800 IN CNAME www.l.google.com.
www.l.google.com. 300 IN A 74.125.93.105
www.l.google.com. 300 IN A 74.125.93.99
www.l.google.com. 300 IN A 74.125.93.147
www.l.google.com. 300 IN A 74.125.93.103
www.l.google.com. 300 IN A 74.125.93.106
www.l.google.com. 300 IN A 74.125.93.104
;; Received 175 bytes from 216.239.34.10#53(ns2.google.com) in 24 ms

Damit lässt sich schön verfolgen, wie “www.google.de” sukzessive aufgelöst wird, angefangen mit den DNS-Rootservern.

Nach oben