DNSSEC Amplification Attack

Nun bin ich schuld(tm). Ich habe fremde Systeme angegriffen. Dabei habe ich einfach nur meine Arbeit getan.

Stellt man einem DNS Server eine Anfrage, so beantwortet er diese. Das ist sein Job. Und DNS ist ein Dienst, der manchmal unter sehr hoher Last steht. Die Serversoftware ist also darauf optimiert, möglichst viele Anfragen beantworten zu können. DNS Anfragen und Antworten werden per UDP ausgetauscht, einem statuslosen Protokoll. Auf ein einzelenes Anfragpaket hin gibt es ein einzelnes Antwortpaket und dann ist für beide Seiten die Sache vergessen. Das geht rasend schnell.

Allerdings kann niemand prüfen, ob die Anfragen auch vom richtigen System kamen. Das einkommende Paket wird schlicht beantwortet und die Antwort geht an die (vorgebliche) Absender-IP-Adresse. Und die kann man fälschen (spoofen). Damit gehen die Antworten an eine anderes System.

Normalerweise ist eine solche Adressfälschung ohne größere Probleme, weil der Angreifer genauso viele Pakete aussenden muß, wie auch ankommen. Problematisch wird es, wenn die Antwort deutlich größer ist als die Anfrage. Dann gewinnt der Angreifer Bandbreite. Mit DNSSEC sieht das Zahlenverhältnis ungefähr so aus: Aus einer 43 Byte großen Anfrage enstand eine 2796 Byte große Antwort. Eine Versechzigfachung!

IP 217.17.207.133.53378 > 217.17.192.66.53:  51078+ [1au] ANY? donnerhacke.de. (43)
IP 217.17.192.66.53 > 217.17.207.133.53378:  51078* 14/0/11 NS avalon.iks-jena.de.,
 NS broceliande.iks-jena.de., MX mailv4.donnerhacke.de. 6, MX mailv6.donnerhacke.de. 4,
 SOA, Type46, Type46, Type46, Type47, Type46, Type46, Type46, Type48[|domain] (2796)

Der Effekt tritt auch bei anderen Diensten auf und ist wohlbekannt. Allerdings gibt es bisher keine gute Lösung. Jeder Ansatz zerstört das DNS irgendwie. Trotzdem mußte jetzt schnell eine Lösung her, denn es liegt eine Beschwerde aus Schweden vor, der Server hier würde die Schulen dort als Teil eine dDoS-Netzwerkes angreifen. Die paar Mbps waren mir gar nicht aufgefallen.

Zuerst habe ich mir die gerade aktuelle Version von BIND gezogen, und ganz normal in Betrieb genommen. Es gibt selbstverständlich erstmal keine Änderung am Verhalten. Des kommen weiterhin Tausende von "ANY"-Anfragen über UDP an die gehosten Zonen.

Glücklicherweise ist der Sourcecode an dieser Stelle für einen Quick-Hack ganz übersichtlich:

--- bin/named/query.c.ORIG      2012-09-10 18:34:44.000000000 +0200
+++ bin/named/query.c   2012-09-10 17:43:23.000000000 +0200
@@ -7326,6 +7326,10 @@
        if (dns_rdatatype_ismeta(qtype)) {
                switch (qtype) {
                case dns_rdatatype_any:
+                       if ((client->attributes & NS_CLIENTATTR_TCP) == 0) {
+                               query_error(client, DNS_R_REFUSED, __LINE__);
+                               return;
+                       }
                        break; /* Let query_find handle it. */
                case dns_rdatatype_ixfr:
                case dns_rdatatype_axfr:

Wenn also jemand nach "ANY" fragt und die Anfrage per UDP reinkommt, dann wird die Anfrage schlicht abgelehnt. Damit ist die Antwort kleiner als die Anfrage und der Angriff lohnt sich nicht mehr. Bis das aber die Angreifer merken, kann es dauern. Es stört nur etwas, daß überhaupt Antwortpakete rausgehen. Zum kommentarlosen Wegwerfen kann ich mich aktuell nicht überwinden.

Andererseits ist schon bekannt, welche Systeme damit Probleme haben werden. Die Software qmail stellt standardmäßig "ANY" Anfragen, um die Mailsserver zu bestimmen. Das wird nun nicht mehr klappen.

Eine korrekte Lösung kann nur sein, ein Dampening einzuführen. Anhand von Strafpunkten für jede Art von Anfrage und Antwort kann dann einfach das Antworten komplett eingestellt werden. Da Strafpunkte mit der Zeit verfallen, wird es dann automatisch irgendwann wieder gehen. Das wird eine spannende Aufgabe.

Avatar
Kai Kellner 07.09.2016 10:34
Hab das mal grad durchgelesen. Das mit dem Sourcecode ist eine sehr gute Idee. Es gibt aber eine einfachere Möglich "ANY" total zu überwinden; über die IPTABLES:

iptables --insert INPUT -p udp --dport 53 -m string --algo bm --hex-string '|00ff|' -j DROP -m comment --comment "DROP DNS Q ANY NOT ALLOWED HERE"

'|00ff|' ist der String Wert für ANY und schon ist das Problem gelöst.

Gruß

1 Kommentare

Post a comment

Verwandter Inhalt