DNS Zonen mit DNSSEC signieren (mit Bind)

DNS Antworten können signiert werden, damit man überprüfen kann, ob es sich um eine richtige und vertrauenswürdige Antwort handelt. Die DNS Antworten werden vom authoritativen DNS Server signiert. Die Schlüssel, welche die Antworten signieren, werden von dem DNS Server eine Zone höher signiert. Über diese Chain-of-Trust können Anwendungssoftware und DNS Resolver prüfen, ob eine Antwort vertrauenswürdig ist oder nicht. Mit dem DNS Server bind kann man seine Zonen selber signiert anbieten. Ich zeige das am Beispiel der Domain example.org.

NSEC vs. NSEC3

Die Nichtexistenz einer Domain (NXDOMAIN) wird mittels eines NSEC Records (Next SEcure Record) bewiesen. Fragt man einen Nameserver nach einer nicht existierenden Domain, sagt dieser “diese Domain gibt es nicht, aber folgendes ist die nächst gültige…”. So werden alle existierenden Domains in einer Art Linked List verkettet. Damit ist es sehr einfach die ganze Zone durchzugehen und so alle existierenden DNS Einträge zu bekommen. Das geht z. B. mit dem Tool ldns-walk. Bei der neueren Version NSEC3 geht das nicht mehr, da dort der Eintrag mit einem Salt und mehreren Iterationen gehashed werden kann. Ein Angreifer kann mit einer Rainbowtable die Hashes vorberechnen und so offline probieren die Zone zu enumerieren, was sehr aufwändig ist (aber möglich). Deshalb sollte man heutzutage NSEC3 und nicht mehr nur NSEC verwenden.

Key Signing Key (KSK) erstellen

Der Key Signing Key (KSK) benötigt man um sich seinen Zone Signing Key (ZSK) zu signieren. Der eigene KSK wird von einer DNS Zone weiter oben signiert. Alle folgenden Arbeiten werden im Verzeichnis /etc/bind durchgeführt. So erstellt man ein Key Signing Key:

dnssec-keygen -3 -a RSASHA512 -b 4096 -n ZONE -r /dev/urandom -f KSK example.org
  • -3 aktiviert NSEC3
  • -a RSASHA512 Typ der Signatur
  • -b 4096 Blockgrösse

Dabei entstehen folgende Dateien:

  • Kexample.org.+007+28736.key: DNSKEY Record: Öffentlicher Schlüssel.
    Dient zum Verifizieren der ZSK Keys. Wird von der höheren Zone signiert.
  • Kexample.org.+007+28736.private: Privater Schlüssel zum Signieren des
    öffentlichen ZSK.

Der öffentliche Schlüssel beinhaltet einen DNSKEY Record:

# cat Kexample.org.+007+28736.key
; This is a key-signing key, keyid 28736, for example.org.
; Created: 20140902110043 (Tue Sep 2 13:00:43 2014)
; Publish: 20140902110043 (Tue Sep 2 13:00:43 2014)
; Activate: 20140902110043 (Tue Sep 2 13:00:43 2014)
example.org. IN DNSKEY 257 3 10 BQEAAAABwZTL[...]mDR7eaIPPjBTihK7w==

Darin sind folgende Werte zu sehen:

Zone Signing Key (ZSK) erstellen

Der Zone Signing Key (ZSK) Schlüssel wird vom eigenen KSK signiert. Die ganze Zone wird mit diesem Schlüssel signiert. So erstellt man ein Zone Signing Key:

dnssec-keygen -3 -a NSEC3RSASHA1 -b 2048 -n ZONE -r /dev/urandom example.org

Dabei entstehen folgende Dateien:

  • Kexample.org.+007+60310.key: Öffentlicher Schlüssel, DNSKEY Record. Dient zum Verifizieren der DNS Antworten
  • Kexample.org.+007+60310.private: Privater Schlüssel zum Signieren der Ressource Records
# cat Kexample.org.+007+50575.key
; This is a zone-signing key, keyid 50575, for example.org.
; Created: 20140902111305 (Tue Sep 2 13:13:05 2014)
; Publish: 20140902111305 (Tue Sep 2 13:13:05 2014)
; Activate: 20140902111305 (Tue Sep 2 13:13:05 2014)
example.org. IN DNSKEY 256 3 10 BQEAAAAB[...]KttL/MZLnPs=
  • 256: Nur Bit 7 vom flags Feld: Zone Signing Key (ZSK)
  • 3: Fix vom Protokoll definiert.
  • 10: RSASHA512

Zone signieren

Die neuen öffentlichen Schlüssel bindet man im Zonenfile mit der $INCLUDE Direktive ein:

# vi /etc/bind/db.example.org
; DNSSEC
$INCLUDE Kexample.org.+007+28736.key
$INCLUDE Kexample.org.+007+50575.key

Nebenbei ein Tipp für vi Benutzer: Die Dateinamen holt man in vi am einfachsten mit mit :r!ls Kexample.org.*.key.

Jetzt kann man die Zonen signieren. Dabei bekommt man eine neue Zone mit dem Suffix .signed.

# dnssec-signzone -3 `head -c 512 /dev/urandom | sha1sum | cut -b 1-16` \
  -H 330 -t -o example.org db.example.org
Verifying the zone using the following algorithms: RSASHA512.
Zone signing complete:
Algorithm: RSASHA512: KSKs: 1 active, 0 stand-by, 0 revoked
                      ZSKs: 1 active, 0 stand-by, 0 revoked
db.motd.ch.signed
Signatures generated:                       42
Signatures retained:                         0
Signatures dropped:                          0
Signatures successfully verified:            0
Signatures unsuccessfully verified:          0
Signing time in seconds:                 1.189
Signatures per second:                  35.296
Runtime in seconds:                      1.289
  • -3 aktiviert NSEC3 und benötigt als Parameter einen Salt, welcher aus den ersten 16 Zeichen einer SHA1 gehashten Zufallszahl besteht. Es wird empfohlen
    bei jedem signieren einen neuen Hash zu generieren.
  • -H gibt an wieviele Iterationen für den Hash gemacht werden müssen. Empfehlungen dazu gibt es im RFC4641 (DNSSEC Operational Practices): http://www.ietf.org/rfc/rfc4641.txt
  • -t zeigt am Schluss eine Statistik an
  • -o gibt die Zone an
  • am Schluss gibt man das das Zonenfile an

Falls man die Keys in einem anderen Verzeichnis hat, kann man dies mit -K angeben.

Die neue Datei der signierten Zone heisst db.example.org.signed und beinhaltet folgendes:

  • Alle Ressource Records lexographisch (alphabetisch) sortiert.
  • Nach jedem Ressource Record wird ein NSEC3 Record eingefügt, welcher auf den nächsten Ressource Record zeigt (gehashed).
  • Alle Ressource Records (auch die neuen NSEC3 Records) haben ein RRSIG Record bekommen, welches die Signatur vom Record ist. Erstellt wurde diese Signatur mit dem ZSK.

Bei jeder Änderung in der Zone, muss diese neu signiert werden.

Die signierte Zone ist 30 Tage lang gültig und muss danach wieder erneut signiert werden. Mit -e YYYYMMDDHHMMSS kann dnssec-signzone eine eingene Endzeit angegeben werden.

DNSSEC in Bind aktivieren

In Bind kann man dnssec in den globalen Optionen aktivieren:

# vi /etc/bin/named.conf.options
dnssec-enable yes;

Danach aktiviert man für die zu signierende Zone das neue Zonenfile mit dem Suffix .signed:

# vi /etc/bind/named.conf.local
zone "example.org" {
  type master;
  file "/etc/bind/db.example.org.signed";
  allow-transfer { "slaves"; };
  notify yes;
};

Key beim Registrar eintragen

Jetzt muss man DNSSEC bei seinem Registrar aktivieren. Dies geschieht zum Beispiel online. Beim Aktivieren wird man nach dem richtigen KSK gefragt, was man gestätigen muss.

Die Zone höher muss die Delegation Signer Ressource Records (DS-RR) für die darunterliegende Zone eintragen. Sind die DS-RR eine Zone höher eingetragen, kann die Zone nun verifiziert werden. Die DS-RR werden zum erstellen der Chain-of-Trust benötigt.

Es dauert es je nach dem eine Weile bis man die DS-RR sieht:

$ dig example.org ds @a.nic.ch +multiline
; <<>> DiG 9.9.2-P2 <<>> example.org ds @a.nic.ch +multiline
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58471
;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;example.org.    IN DS

;; ANSWER SECTION:
example.org.   3600 IN DS 7127 7 1 (
        5D904BEC66E4D793C190B09954C56B592A46C278 )
example.org.   3600 IN DS 7127 7 2 (
        3002E43C7AF9CCB31FD1CCD90F9BFD8A6DC5BB0097F8
        6A6146D2C57B85145502 )
example.org.   3600 IN DS 7127 7 4 (
        AD09B9B7DAB830AA9F6371C7A69A5C122B70501DEAFE
        14F13A6D0DE36E8703049C6A4824A28BC6019AD54030
        53DB8BD0 )

;; Query time: 13 msec
;; SERVER: 130.59.1.80#53(130.59.1.80)
;; WHEN: Tue Sep  2 16:09:07 2014
;; MSG SIZE  rcvd: 191

In den DS Records sieht man den KSK, welcher hier die ID 7127 trägt.

Auch der whois Eintrag zeigt, dass DNSSEC aktiviert ist:

$ whois example.org | grep DNSSEC
DNSSEC:Y

DNSSEC Testen

Jetzt können die Nameserver, welche die DNSSEC Validierung aktiviert haben, die Antworten für unsere Zonen validieren.

Die öffentlichen DNS Schlüssel (KSK und ZSK) können so abgerufen werden:

$ dig example.org dnskey +noall +answer +multiline
; <<>> DiG 9.9.2-P2 <<>> example.org dnskey +noall +answer +multiline
;; global options: +cmd
example.org.   86400 IN DNSKEY 256 3 7 (
        BQEAAAABv2VU7NB5EcAJxCUWS3Mn7ULEDOejyKhgqg98
        oTGO8KmJBwJ2jxz3lkUwp4GfypSon9q1KDYUr/gmOX+9
        ukU3BBNUrFYBieuxMCnpGZbLSFF0uSWKiLQUWKtXfbBt
        aqw/vJ2pLCPJTOT9ezmJ9MIR8LiVzlSMPL1HCOWufn8K
        /oPbTvq+tWINBKQ/Oh+pre31TOvQg47JW/Nel9nBhGo/
        tLCOCqQ1McEImYTWp8rpdlHmvAgbJD6s9MDB6pvbxs9B
        LsV1Ahwa98ksOAgccZDJxq2NgLZ32F2IjUHsMfMJSni9
        TaCgBlPCwz5aSkUpSaicM524pSjFsbwmCkb/c7m+Nw==
        ) ; ZSK; alg = NSEC3RSASHA1; key id = 6826
example.org.   86400 IN DNSKEY 257 3 7 (
        BQEAAAABuUUu5vLyfNru1Et/SV/S3X8Q23qs2tx3HRQb
        X0w7Qadevocg2BLRTAQIbOOrPfhvB5F3f73GrnsRBxTy
        XBtCbIMfQ8WNMHKzOp6vEVCx2o8FuRa8c1SIiuaYKfAH
        38A/wj/8Y52UDaRV0KZrcEUZsv3goq3hSL0dZgHHfbXb
        BesHW1jQiBd0kkrDmoe08ls9dw1dRHH3/mos6sEw6bER
        ++TwmYRXGsm+hv3h2J3zLY8DZOqMpw8IEcgVkL7dux72
        XK8zrkgQeTlHCsj36ZDb1w7ApAMLHZkbG0kFTX+U2AT6
        2rtvVA7VGEaTCnx7Nuu9zg9BnGkcmwGRhMtOx0QkNjBy
        JPy6kSMMfYOtx1LcY4pV2jtlBKoNdxcbrBeG05FFur3O
        QqCKJd+I7mnX8zjXgBH6jgHz5zN2jn/I0ZDtcancT09v
        T51+ViC4weAs3LZEwMl1at8MhjRdb9uvbS6dS3fMtPp5
        2sO3OpZ2WwGy1Bgmi303swqZDgOd9UvMQbMfdGfNuaoF
        6kVVKH3JRe7BBY872rcEhrkdbelB60EBINo5edepd8Sq
        ZrvtCYdJX0RmtRBrBedOcbahGJ2hq5mylxCdmTkxCU83
        lhoiu8N49bjsK2kkxZkxlkITe1XPEvhdDvW94naTSHpZ
        XzhGiQ2MFZe3N73g9AhK9EvGOdBsLUU=
        ) ; KSK; alg = NSEC3RSASHA1; key id = 7127

Zu jedem Record bekommt man jetzt ein RRSIG Record, welcher die Signatur darstellt. Dies kann mit der Option +dnssec in dig aktiviert werden:

$ dig example.org. A +dnssec @ns1.motd.ch +m
; <<>> DiG 9.9.2-P2 <<>> example.org. A +dnssec @ns1.motd.ch +m
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7176
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 3, ADDITIONAL: 5
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;example.org.    IN A

;; ANSWER SECTION:
example.org.   86400 IN A 5.45.105.71
example.org.   86400 IN RRSIG A 7 2 86400 (
        20141002105145 20140902105145 6826 example.org.
        DmBi5IbgmlTLfeABOg1sXx7kRzD4D5n07pY/K31rgmYT
        Cd5Lq7gy51veKxtd+qNxu8ahxp5wZ3redASjBAVY2sui
        m03oczA8ET051G8dmdHKT4nL4h5/Z9RYIoH7i8D+otQP
        mMz5mrZkfg6MwUUdd4GCkc/7nf9y31dLZXi/zi4HElOx
        2Qt2yCVn4qrtp3f8YgocReOUZaaONYlPaROfenaIHYjT
        n3jIMMqCZ4sEMZRh1EMWSziGPomq+S4UHZkJzWc1as32
        ad5aNe50m3mOukZCr+IDsVWZW+Bn0YIBNIm8W24NrrZG
        ZAonGLx8z3q4zmbBW6dYfFcRejYi1l2LBQ== )
[...]

In Firefox gibt es das Plugin DNSSEC Validator, welches einem den Status von DNSSEC der Domain einer Webseite anzeigt:

dnssec-validator

Es gibt auch Webseiten, welche einem die DNSSEC Konfiguration prüfen. Hier ein Beispiel vom DNSSEC-Debugger von Verisign Labs (http://dnssec-debugger.verisignlabs.com):

verisignlabs

Weitere Schritte/Ideen

  • Einpflegen von SSHFP Records für SSH Public Keys
  • Einfplegen von PGP Key im DNS
  • Einpflegen von TLSA Records für DANE Unterstützung (SSL Fingerprint im DNS)
  • Automatisches Signieren der Zonen bevor sie ungültig werden
  • Resolver nutzen, welche ungültige DNSSEC Antworten ablehnen
  • Automatisches Signieren von Zonen mit Dynamischen Updates
  • Sich Gedanken machen, wie man die Schlüssel am einfachsten wechselt und den ZSK regelmässig wechseln.
  • Signierte Zone in einem Monitoringtool eintragen, damit man bei Problemen benachrichtigt wird

Links, Quellen und weitere Informationen

12 thoughts on “DNS Zonen mit DNSSEC signieren (mit Bind)”

  1. Es gelingt mir einfach nicht, mit

    :/var/lib/named/keys # dnssec-signzone -3 `head -c 512 /dev/urandom | sha1sum | cut -b 1-16` -H 330 -t /var/lib/named/master/mydomain.de.zone
    dnssec-signzone: fatal: No signing keys specified or found.

    Alle Versuche mit unterschiedlichen Konstellationen schlagen fehl. Wie kann man nur ein solches Werkzeug programmieren.

    • Du hast eine etwas andere Verzeichnisstruktur als ich.

      Falls du nicht bereits im Verzeichnis mit all den Keys drin bist, gibt dies mit -K /path/to/keydir an.

      Der Dateiname der Keys ist folgendermassen aufgebaut: Kname+algorithm+keyid. Der jeweilige Key muss in der Zone included sein. Dann wird der Key automatisch gefunden.

      Mit der -k keyfile Option, kannst du den Key, mit welcher die Zone signiert werden soll, auch direkt angeben.

      Hat das geholfen?

      GRZ
      Emanuel

  2. Hi, danke erstmal für deine ausführliche Ausarbeitung!
    Wofür steht der Operator -e in dem dnssec-keygen-Befehl? Auf der Manpage konnte ich dazu nichts finden.

    • Hi.

      Bitte gerngeschehen 🙂

      Wenn ich jetzt mit einer aktuellen Version den Befehl ausführe, erhalte ich folgende Meldung “phased-out option -e (was ‘use (RSA) large exponent)”:

      $ /usr/sbin/dnssec-keygen -3 -a RSASHA512 -b 4096 -n ZONE   -e -r /dev/urandom -f KSK example.org                                                                                                                                                          
      phased-out option -e (was 'use (RSA) large exponent)
      Generating key pair...........................................................................................................................................................................................++ .............................................
      ..........................................................................................................................................................................++
      Kexample.org.+010+27081

      In älteren manpages befindet sich noch die Doku dazu:

      -e
          If generating an RSAMD5/RSASHA1 key, use a large exponent.

      Das ist also eine veraltete Option um den Public Exponent explizit bei grösser zu setzen.

      Bei einer aktuellen Version sieht das so aus:

      $ grep PublicExponent Kexample.org.+010+02832.private
      PublicExponent: AQAB

      Das hat den Hex wert 10001:

      $ base64 -d <<< AQAB | xxd -p
      010001

      Die Keys, welche ich früher generiert habe, haben folgenden Wert:

      $ grep PublicExponent *.private
      Kemanuelduss.ch.+007+06826.private:PublicExponent: AQAAAAE=

      Das ist in Hex:

      $ base64 -d <<< AQAAAAE= | xxd -p
      0100000001

      Das bestätigt die Manpage von früher. Heute wird aber die Option ignoriert.

      Dies hat mit Geschwindigkeit bei den kryptographischen Operationen zutun. Je grösser der Exponent, je länger dauert die verifikation der DNSSEC Signaturen. Grössere Werte, bedeuten aber nicht unbedingt, dass die Signatur stärker ist. Siehe dazu folgenden Post: https://www.imperialviolet.org/2012/03/16/rsae.html

      Merci für die Info, ich hab den Blogpost angepasst und die -e Option entfernt.

      Gruss,
      Emanuel

  3. Hallo,

    Ich danke auch erstmals für die gute Erklärung jene von Wikipedia und heise sind fürs nichts. Erst als ich diesen Artikel fand klärten sich sehr viele Fragen. Danke dafür!

    Ich lese im Artikel nie etwas vom RRset. Werden nicht die RRsets signiert und danach mit NEC3 alphabetisch sortiert und anschliessend gehasht? Was ich nicht genau verstehe: Weshalb werde die Domains gehasht bei NEC3, was bringt es einem Angreifer zu wissen, wessen domains im Zonefile existieren. NSEC3 löst ja damit dieses Zone walking Problem welches bei NSEC existierte…

    Liebe Grüsse
    Nicolas

    • Hey Nicolas

      Bitte gerngeschehen 🙂

      Bzgl. RRsets: Laut RFC 8499 “DNS Terminology” [1] und RFC 2181 “Clarifications to the DNS Specification” sind RRSet eine Gruppe von DNS Records mit dem selben Label, Class und Type aber unterschiedlichen Daten (damit diese nicht mehrmals vom DNS Server im DNS Paket übertragen werden müssen). Dies ist nicht explizit etwas von DNSSEC.

      Bei DNSSec werden einzelne DNS Records signiert. Bei DNSSEC werden alle DNS Einträge der Reihe nach sortiert und dann für jeden Eintrag ein NSEC bzw. NSEC3 Record generiert. Dies wird so gemacht, damit man pro Domain einen eigenen NXDOMAIN ähnlichen Record hat um die Nichtexistenz eines Records zu signieren (weil wenn nur der NXDOMAIN Record signiert wäre, könnte man diesen in einer Replay Attacke an den Resolver senden und er würde glauben dass es eine bestimmte Domain nicht gibt).

      Wie du korrekt geschrieben hast, kann man somit DNS Zonen enummerieren und mit NSEC3 ist das nicht mehr so einfach möglich (man muss die Hashes knacken um die Einträge rauszubekommen).

      Was bringt das einem Angreifer? Ein Angreifer kann so sehr viel über ein Netzwerk lernen. Welche Hosts es gibt, welche Software eingesetzt wird (Beispiel: confluence.example.com), wann ein neuer Host dazukommnt (indem man das regelmässig macht und den Unterschied vergleicht), etc. Zudem bieten Webserver je nach Hostnamen einen anderen Inhalt an (das wird anhand des Host HTTP Request Headers entschieden). Wenn man im Browser über die IP Adresse zugreift, erhält man vielleicht nur eine Default Seite, mit einem Hostnamen wie splunk.example.com, eine installierte Webapplikation. Ein Angreifer hat somit mehr Infos und die Angriffsfläche ist grösser.

      Natürlich sollte die Sicherheit einer Infrastruktur nicht darin bestehen, indem man Hostnamen geheim hält. Dies nennt man “security through obscurity” und sollte nicht dazu verwendet werden um Systeme sicher zu machen. Man kann damit jedoch die Angriffsfläche etwas reduzieren.

      Angenommen es gibt eine gravierenden Sicherheitslücke in der neusten Splunk Version und über DNS Zone walking findet jemand raus, dass es den Hostnamen splunk-3007-bern.example.com gibt, dann kann dies von Angreifern sehr schnell rausgefunden und ausgenutzt werden. Wenn dies jedoch nicht öffentlich im Internet bekannt ist, dass es diesen Hostnamen gibt, dann ist die Chance kleiner dass das jemand ausnutzt.

      Es gibt jedoch viele weitere Methoden um an Hostnamen zu kommen. Geh mal nach https://crt.sh und suche nach %.example.com: Dann hat man sehr schnell sehr viele Hosts auf der example.com Domain beisammen.

      Ich hoffe das konnte deine Frage klären.

      Beste Grüsse,
      Emanuel

      [1] https://tools.ietf.org/html/rfc8499#section-5
      [2] https://tools.ietf.org/html/rfc2181#section-5

      • Hallo,

        Allgemeine Frage vorab zur Grundlage von DNSSEC:

        Ich habe je 2 Files beim KSK und ZKS. Ein File vom KSK beinhaltet ja einen private Key welches den privaten ZKS-Key unterzeichnet das zweite File behinhaltet den Public Key welches als Hash-Wert in die übergeordnete Domain übergeben wird. Der ZKS hat auch einen privaten Key welches später die Signatur der jeweiligen diversen RRSIGs unterscrheibt. Der öffentliche Key vom ZKS wird 1:1 vom File .key ins Zonefile der Kopiert.

        Meine Frage nun, wenn ich einen DNS Resolver von einer beliebigen Domain nach dem DNSKEY befrage und ich 2 öffentliche DNSKEYs vom KSK bekomme, kann dass sein oder nicht? Ich würde mal Nein sagen, weil die übergeordnete Domain würde diesen ja so nicht kennen und diese übergeordentete Zone kennt ja nur einen Key. Beim ZKS hingegen ists glaube ich möglich oder? Der ZSK kann mehrere DNSKEYs in der Zonendatei haben oder und somit mehrere öffentliche Schlüssel (DNSKEYs)?

        Zum 1. Abschnitt:

        Also als Label wird eine Subdomain bezeichnet oder? Also “www.”example.org und “test.”example.org wären also zwei unterschiedliche Label und diese würden daher nicht als RRset gruppiert. Umgekehrt würden alle RR-Typen (z. B A,AAAA,NS…) vom Label “www.”example.org gruppiert werden. Wenn ich also nach A-Typ einen DNS Resolver befrage antwortet er mir ja oft mit einem Additional Records. Sind das diese gruppierten RRSets welche mitgeliefert werden? Ich vermute ich mal ja…? Pro Label existiert also auch nur eine RR-Signatur? Ausser ich möchte nicht, dass meine Signatur / Key aufeinmal verfällt und ich daher auf ein double Keyrollout setzte?

        Zum 2. Abschnitt bezüglich NSEC3:

        Das verstehe ich jetzt gar nicht. Meinst du mit Domain pro Subdomain oder pro Domain wie example.de? Pro Domain wird doch in der Regel ein Zonefile erstellt? Was ich weiss ist nur, dass “NXDOMAIN” soviel heisst wie keine Ahung, ich weiss nichts über diese Zone. Den ServFail gibts auch noch wenn ich mich nicht täusche. NSEC3 verkettet meines wissens Domains zum Beispiel a.example.ch -> b.example.ch / b.example.ch -> c.example.ch / c.example.ch -> a.example.ch dabei verstehe ich nicht wie dadurch verhindert werden soll, dass ein Angreifer die Antwort so manipulieren soll, dass eine Lücke entsteht. Vorallem müsste ja die ganze Liste aller Subdomains von a-c.example.ch übermittelt werden, damit überprüft werden, kann obs eine Lücke gibt oder nicht. Das geschieht ja vermutlich nicht, weil ja nur der angefragte Ressourcen Record und eventuell Additional Records an den Subresolver gesendet werden oder? Weiter wird der NSEC-RR auch signiert wozu wird dann die ganze NSEC-Kette erstellt mit dem nachfolgenden Subdomains? Irgendwie verstehe ich bei NSEC zur Zeit nicht gerade viel…

        Gruss
        Nicolas

        • Hey Nicolas

          Bzgl. mehrere KSK.

          Es kann gut sein, dass du mehrere KSK erhältst.

          Beispiel von icann.org:

          $ dig icann.org dnskey +multiline

          ; <<>> DiG 9.14.1 <<>> icann.org dnskey +multiline
          ;; global options: +cmd
          ;; Got answer:
          ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 26362
          ;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 1

          ;; OPT PSEUDOSECTION:
          ; EDNS: version: 0, flags:; udp: 512
          ;; QUESTION SECTION:
          ;icann.org.   IN DNSKEY

          ;; ANSWER SECTION:
          icann.org.    3600 IN DNSKEY 256 3 7 (
                  AwEAAa64Dnm1zYNVp3ImBheex+CW6Q8fLbcvCZ+2BNlg
                  A35KR0CV2sqK9PcZ+jv/LA+YHnFYm4lBkI7znbwMekOd
                  ruoYPIhNkSECa9HVbMe8738cabB1DHF0NIOknrd0iVdu
                  pwOBfpr8aEemSWB07GLP7fGpg2s9KTlP98vOHs3jvOHV
                  ) ; ZSK; alg = NSEC3RSASHA1 ; key id = 64452
          icann.org.    3600 IN DNSKEY 257 3 7 (
                  AwEAAaxEcKY6A65zj+LOPz61QMjhiSFTjuw77gmHUtrA
                  H2IZ53i61DdNjh7h5LhujGjVR7+XsL+DzQJhJQUSrIil
                  aNv2sHlzjjDdXKsD4TxaziLCvbog/5J9DIc1piDOp5Bk
                  y5l2YoX25AyQIbm1t4mxiMCkjW6ItXO3FGFdP2W+yQXL
                  zK5b+oC8UmlBViZaR2N8+By1uDtSTT+hPWCUXx7BbK1q
                  UuKrOHYW5wtklzn9zuPYRaT1IAU6nYQeRVAjyqEnllk7
                  ybhT4Jic4yyUIaEJaHxJHQwW2Uu+YLhstrJgkf6XZ+O2
                  XhtFAXRh09peoIaKpB0ldrj602qaXRWahiRQqq8=
                  ) ; KSK; alg = NSEC3RSASHA1 ; key id = 18060
          icann.org.    3600 IN DNSKEY 257 3 7 (
                  AwEAAdKq+ROFFjVRGHeuAMC1vhI2HicoXKy9bGbcWZIc
                  DEA90NynbT08cBeM9Is7Bd88KFWCLaan4mcOKU5tN+ZQ
                  5rE3XT0ieQwf1AuusyQWIoRvg8RsYFHbANAZ/4pu09Gb
                  w/QUe6b6aoCLXTKDwdDBXm8B6H7tyiMUMd5krz2gLZ9N
                  f3qBL3oodJDCDuO9XWglww+YixmoVfqahCOS+brGVrzw
                  0ShbQsO89vE0Q3FRlaERiLF0HTih4G2SlMaSBcZiw1vF
                  DFAs3/RAVl4mYkjPD9TEnZAB4Ocz4GwToH58dO9P4Pr1
                  iah0sSZD/fklVgD5NDA5iWVe23MANlLDoPM/j4s=
                  ) ; KSK; alg = NSEC3RSASHA1 ; key id = 23584
          icann.org.    3600 IN DNSKEY 256 3 7 (
                  AwEAAdU9iH07Nr6i1Z/Qcz4d6iNz6mZ1OjVQcBVwHW8u
                  oF9Q+9gK3uf6O06MemwTWTK6rPNIBTp4ctWp38x/k4sX
                  vRcdCIHSCmaE63AlfWbNUoALva73UHvDUtJb07MpF2Tj
                  dBUz/O8lUTHx+fe2SZH/sQW7JkNiVggr/q2q6A5yeP+z
                  ) ; ZSK; alg = NSEC3RSASHA1 ; key id = 21255
          icann.org.    3600 IN DNSKEY 256 3 7 (
                  AwEAAbl3XPdJwPEGDxwyWkhqcWK+p+Qvgj0W18m54cE4
                  tkQ34hCr8zZjjpzkBAVEYYkTVKpJOVTMp2I4fn481N6z
                  cteS39TK5DcZcFEGs4q7r97S06iruGOscpFeR3RTNIhY
                  kcJt4/BMAIForXnVsqIc5lV7jYCMTy1rnzYWbcMJmmmf
                  ) ; ZSK; alg = NSEC3RSASHA1 ; key id = 36728

          ;; Query time: 26 msec
          ;; SERVER: 192.168.23.1#53(192.168.23.1)
          ;; WHEN: Mon May 13 22:33:16 CEST 2019
          ;; MSG SIZE  rcvd: 1034

          Hier gibt es auch zwei KSK:

          • KSK; alg = NSEC3RSASHA1 ; key id = 18060
          • KSK; alg = NSEC3RSASHA1 ; key id = 23584

          Deshalb ist es auch möglich, dass die übergeordnete Zone mehr als nur 1 KSK kennt:

          $ dig icann.org ds +multiline

          ; <<>> DiG 9.14.1 <<>> icann.org ds +multiline
          ;; global options: +cmd
          ;; Got answer:
          ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21424
          ;; flags: qr rd ra; QUERY: 1, ANSWER: 10, AUTHORITY: 0, ADDITIONAL: 1

          ;; OPT PSEUDOSECTION:
          ; EDNS: version: 0, flags:; udp: 512
          ;; QUESTION SECTION:
          ;icann.org.   IN DS

          ;; ANSWER SECTION:
          icann.org.    86400 IN DS 18060 7 1 (
                  04CF77A76FD328458005D2B35E416F209A3420A0 )
          icann.org.    86400 IN DS 18060 7 2 (
                  6BE021818B9F10ED981A03ACBF74F01E31FB15C58680
                  AD0C4BAA464BF37A7523 )
          icann.org.    86400 IN DS 32134 7 1 (
                  3D54D51109645E8315F59790B920323D361B065F )
          icann.org.    86400 IN DS 32134 7 2 (
                  6C321409786B95BEEE60E6D42F3713ACC3A9B5D18442
                  091A792FBDD1EA8E4655 )
          icann.org.    86400 IN DS 41334 7 1 (
                  49D712CF7A8984B7545FDC7E69D7372782339B3A )
          icann.org.    86400 IN DS 41334 7 2 (
                  C299FAF7D6F9BCB310200ECF2EA216A2E83F7ACB15C8
                  D72D79641FA8DFACF9A9 )
          icann.org.    86400 IN DS 41643 7 1 (
                  93358DB22E956A451EB5AE8D2EC39526CA6A87B9 )
          icann.org.    86400 IN DS 41643 7 2 (
                  B8AB67D895E62087F0C5FC5A1A941C67A18E4B096F6C
                  622AEFAE30DD7B1EA199 )
          icann.org.    86400 IN DS 17248 7 1 (
                  88151C40E4673E7023E6AD1902A8AE055F3DDF61 )
          icann.org.    86400 IN DS 17248 7 2 (
                  885CF8A6CF35FD5C619E1D48B59AFB23063BBA9FEC52
                  FF25F99094CBA10910A2 )

          ;; Query time: 15 msec
          ;; SERVER: 192.168.23.1#53(192.168.23.1)
          ;; WHEN: Mon May 13 22:38:44 CEST 2019
          ;; MSG SIZE  rcvd: 458

          Dies wird beispielsweise so gemacht, wenn der KSK ausgetauscht wird. Weil DNS viele Caching-Mechanismen verwendet, kann man nicht einfach den alten Key löschen und einen neuen anlegen. Dann muss man gleichzeitige den neuen KSK einfügen und anhand der TTL sicherstellen, dass der alte nicht mehr im Cache vorhanden ist. Ein Beispiel ist in einem Report von ICANN beschrieben: https://www.icann.org/en/system/files/files/review-2018-dnssec-ksk-rollover-04mar19-en.pdf.

          Beim ZSK ist es genau dasselbe. Dort kann ich auch mehrere haben um beispielsweise ein Key Rollover durchzuführen.

          Bzgl. den RRSets:

          Wenn du zum Beispiel nach dem MX Record fragst werden diese zusammengefasst (weil gleiche diese dasselbe Label, die Class und den Typ haben. Diese werden deshalb zusammen signiert:

          $ dig icann.org mx +dnssec

          ; <<>> DiG 9.14.1 <<>> icann.org mx +dnssec
          ;; global options: +cmd
          ;; Got answer:
          ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32025
          ;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 1

          ;; OPT PSEUDOSECTION:
          ; EDNS: version: 0, flags: do; udp: 512
          ;; QUESTION SECTION:
          ;icann.org.     IN  MX

          ;; ANSWER SECTION:
          icann.org.    600 IN  MX  10 pechora6.icann.org.
          icann.org.    600 IN  MX  10 pechora8.icann.org.
          icann.org.    600 IN  MX  10 pechora1.icann.org.
          icann.org.    600 IN  MX  10 pechora2.icann.org.
          icann.org.    600 IN  RRSIG MX 7 2 600 20190603035755 20190512173015 36728 icann.org. SS+h0jx/uGX6wMWkK8C0hUDGoWQXWeogWv1YAZLvu2PPVnpa5J8Hbpfo PV//DnJ9/3Do3PjSdMvVyzUQbLjtJxdYgHFuNW3HUljIYOj0JTUPHMQf oMly3fs2FPIGKbW3dWAc7jXsk3oPMERLRfFw5CwxdnnaM9+7MeIqkVKT WNo=

          ;; Query time: 94 msec
          ;; SERVER: 192.168.23.1#53(192.168.23.1)
          ;; WHEN: Mon May 13 22:47:46 CEST 2019
          ;; MSG SIZE  rcvd: 307

          Dies hab nichts mit der Additional Section zutun. Dies sind jeweils eigenständige zusätzliche Antworten, welche auch wieder separat signiert werden:

          $ dig switch.ch ns +dnssec

          ; <<>> DiG 9.14.1 <<>> switch.ch ns +dnssec
          ;; global options: +cmd
          ;; Got answer:
          ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10730
          ;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 9

          ;; OPT PSEUDOSECTION:
          ; EDNS: version: 0, flags: do; udp: 512
          ;; QUESTION SECTION:
          ;switch.ch.     IN  NS

          ;; ANSWER SECTION:
          switch.ch.    86400 IN  NS  ns2.switch.ch.
          switch.ch.    86400 IN  NS  ns3.switch.ch.
          switch.ch.    86400 IN  NS  scsnms.switch.ch.
          switch.ch.    86400 IN  RRSIG NS 13 2 86400 20190602122025 20190509151955 30131 switch.ch. d4fttzlqhQ0DN0amAMEJgKtHX3MOJVNDK1ZTV2pmPiClPtkLzHuXbmUw fKY1qizEac4VEOD8xUr9EZYsaootZg==

          ;; ADDITIONAL SECTION:
          scsnms.switch.ch. 65482 IN  A 130.59.31.26
          scsnms.switch.ch. 65482 IN  RRSIG A 13 3 86400 20190530001821 20190501040529 30131 switch.ch. AIURBFsYJMJoUJXeEWce/aQTJ4zAzfFR4TkNbTnGzZXvW+LLYzCgl0hJ 3W4BcTYejCgKhJSar3A7hm2kRXmONA==
          scsnms.switch.ch. 65212 IN  AAAA  2001:620:0:ff::a7
          scsnms.switch.ch. 65212 IN  RRSIG AAAA 13 3 86400 20190604233153 20190510120550 30131 switch.ch. B7nqlcPzr7MWsGJvCqDp88QpTgeG8RhB+Hmy0dLBUkxmLGILlaSVJG/G uqIzfTfQgPEXkPUSqVNtL7VazKbzNw==
          ns2.switch.ch.    31488 IN  A 130.59.31.29
          ns2.switch.ch.    31488 IN  RRSIG A 13 3 86400 20190602091521 20190505040528 30131 switch.ch. iSoGsKL6dpS8o44GpXr9T4//NgqEvBWR/8l8gnZJYDApOxfN16DnUa1Z SU/Xm35OchR2sU4FPqYVgjJI7tB+kQ==
          ns2.switch.ch.    46582 IN  AAAA  2001:620:0:ff::2f
          ns2.switch.ch.    46582 IN  RRSIG AAAA 13 3 86400 20190605041302 20190508040551 30131 switch.ch. 1rVU+wrrb3HNz4NiuquBI8k07Bbb+aDmCBN7XXs4oN/2QyWfGoihHiXB V5Nwnd2x9+3/9fUdx/e1XCT4SsM0JA==

          ;; Query time: 15 msec
          ;; SERVER: 192.168.23.1#53(192.168.23.1)
          ;; WHEN: Mon May 13 22:50:41 CEST 2019
          ;; MSG SIZE  rcvd: 708

          Bzg. den NSEC/NSEC3 Records:

          Genau, eine Zone hat in der Regel ein Zonenfile. NXDOMAIN heisst aber nicht “ich weiss nichts über diese Zone”, sondern “den angefragten DNS Record gibt es nicht”.

          Es gibt z.B. keinen A Record für foobar.switch.ch (→ NXDOMAIN):

          $ dig foobar.switch.ch

          ; <<>> DiG 9.14.1 <<>> foobar.switch.ch
          ;; global options: +cmd
          ;; Got answer:
          ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 64659
          ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

          ;; OPT PSEUDOSECTION:
          ; EDNS: version: 0, flags:; udp: 512
          ;; QUESTION SECTION:
          ;foobar.switch.ch.    IN  A

          ;; AUTHORITY SECTION:
          switch.ch.    180 IN  SOA scsnms.switch.ch. dns-operation.switch.ch. 2019051307 900 600 604800 180

          ;; Query time: 17 msec
          ;; SERVER: 192.168.23.1#53(192.168.23.1)
          ;; WHEN: Mon May 13 22:54:02 CEST 2019
          ;; MSG SIZE  rcvd: 102

          Gäbe es eine generische “NXDOMAIN” Antwort, könnte man diese als Angreifer replayen, sprich für jede Anfrage dem Opfer diese Antwort zurücksenden und er würde glabuen, dass es diesen Host nicht gibt. Deshalb wird diese NSEC oder NSEC3 Kette erstellt, welche sagt, welche Hosts existieren. Da diese Kette signiert ist, kann man also beweisen, dass ein Host nicht existiert, wenn man den Host in alphabetischer Reihenfolge vorher und nachher kennt.

          Bei Switch sieht man so z.B. dass der Host foobar.switch.ch nicht existiert (immer noch NXDOMAIN), aber es gibt einen NSEC Record der besagt, dass zwischen dem Host fogo.switch.ch und forano.switch.ch keinen weiteren Host existiert:

          $ dig foobar.switch.ch +dnssec +multiline

          ; <<>> DiG 9.14.1 <<>> foobar.switch.ch +dnssec +multiline
          ;; global options: +cmd
          ;; Got answer:
          ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 24338
          ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 6, ADDITIONAL: 1

          ;; OPT PSEUDOSECTION:
          ; EDNS: version: 0, flags: do; udp: 512
          ;; QUESTION SECTION:
          ;foobar.switch.ch.  IN A

          ;; AUTHORITY SECTION:
          fogo.switch.ch.   180 IN NSEC forano.switch.ch. A AAAA RRSIG NSEC
          fogo.switch.ch.   180 IN RRSIG NSEC 13 3 180 (
                  20190531220120 20190508040551 30131 switch.ch.
                  1HRkyRuANAaCf7Vgzvu8t8FxeEphbEL3N3R//ZL+r4/c
                  3HHnKBhfVqdCKX1vy0aWqaCVVUssDuTf5nspFJnBMw== )
          switch.ch.    180 IN SOA scsnms.switch.ch. dns-operation.switch.ch. (
                  2019051307 ; serial
                  900        ; refresh (15 minutes)
                  600        ; retry (10 minutes)
                  604800     ; expire (1 week)
                  180        ; minimum (3 minutes)
                  )
          switch.ch.    180 IN RRSIG SOA 13 2 86400 (
                  20190530030708 20190513194839 30131 switch.ch.
                  WnD3mQGodR5witedIZ6rCJ+0NQkj33QOvD6Ml4MvOkK9
                  E+5DpepLBmPZxcxyMB2Uoac0xftLDi/zlEqyULNDPQ== )
          switch.ch.    180 IN NSEC 6TO4-RELAY.switch.ch. A NS SOA PTR MX TXT AAAA NAPTR RRSIG NSEC DNSKEY CAA
          switch.ch.    180 IN RRSIG NSEC 13 2 180 (
                  20190531011621 20190513040553 30131 switch.ch.
                  VTthYrx1AsK6ntms+yZ+7jTLl+RSzffBI1s4bCVfVjRn
                  clJ96nR8TVsXOUYo9f6UkuRRjB6nJMTBQ1jVJU0Rzw== )

          ;; Query time: 15 msec
          ;; SERVER: 192.168.23.1#53(192.168.23.1)
          ;; WHEN: Mon May 13 22:55:50 CEST 2019
          ;; MSG SIZE  rcvd: 506

          Dieser NSEC RR ist signiert, damit dieser verifiziert werden kann.

          Diese Verkenntung findet also nicht nur bei NSEC3 sondern auch beim normalen NSEC statt. Ein Angreifer kann dadurch nichts manipulieren.

          Es muss nicht die ganze Liste übermittelt werden, weil es genügt wenn ich den namen vor und nach dem angefragen Host kenne (in alphabetischer Reihenfolge).

          Nochmals. Wenn ich nach dem Host foobar.switch.ch frage, der nicht existiert, kann mir der DNS Server als signierte Antwort sagen: “Es gibt keinen Host zwischen fogo.switch.ch und forano.switch.ch!”. Somit kann der DNS Resolver mit Garantie sagen, dass der Host foobar.switch.ch nicht existiert.

          Da bei NSEC diese Hostnamen aber in Klartext sind, kann man einfach eine Zone enummerieren:

          [...]
          fleves.switch.ch. A AAAA LOC SSHFP RRSIG NSEC·
          floo.switch.ch. A AAAA LOC SSHFP RRSIG NSEC·
          flora.switch.ch. SSHFP RRSIG NSEC·
          fogo.switch.ch. A AAAA RRSIG NSEC·
          forano.switch.ch. SSHFP RRSIG NSEC·
          foreman-eth2.switch.ch. A AAAA LOC RRSIG NSEC·
          foreman-proxy-eth0.switch.ch. A AAAA LOC RRSIG NSEC·
          [...]

          Da dies einem Angreifer je nach dem unnötig viele Informationen preis gibt, wurde mit NSEC3 eine Methode geschaffen, um dies zu erschweren. Dabei werden nur noch Hashes zurückgegeben, die nicht auf gültige DNS Einträge rückschliessen lassen:

          $ dig foobar.nic.ch +dnssec

          ; <<>> DiG 9.14.1 <<>> foobar.nic.ch +dnssec
          ;; global options: +cmd
          ;; Got answer:
          ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 17167
          ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 8, ADDITIONAL: 1

          ;; OPT PSEUDOSECTION:
          ; EDNS: version: 0, flags: do; udp: 512
          ;; QUESTION SECTION:
          ;foobar.nic.ch.     IN  A

          ;; AUTHORITY SECTION:
          ch.     900 IN  SOA a.nic.ch. dns-operation.switch.ch. 2019051323 900 600 1123200 900
          ch.     900 IN  RRSIG SOA 13 1 900 20190612205457 20190513200149 2668 ch. Dj0THjv7ZXzIK474y4VOAxsbGs/19QWNmQASU2sVJsuF6m66ca8mIq/Z Vltxsdyw7VlpGvx3RLMnvFCajGOfBw==
          ui1m64qfm968njapla3sd1i702jl444c.ch. 900 IN NSEC3 1 1 2 96A895CD UI1UTRA7V0CN5H0O5BJ0C822FOI3KKQF A MX TXT AAAA RRSIG CAA
          ui1m64qfm968njapla3sd1i702jl444c.ch. 900 IN RRSIG NSEC3 13 2 900 20190530083232 20190430080146 2668 ch. lskwcvcHAzz7CR4ofo+Pko6y422/3wmPA8CraiDESR6quwjCm82iIEau kKYVfGyQEN0JZVRH7Nf1HpvNjqjrwA==
          fkcm3evmgalkvc47spmf9d111fgunade.ch. 900 IN NSEC3 1 1 2 96A895CD FKD5FJN5GUF0UF83SU215I9RQHUOJD2D NS DS RRSIG
          fkcm3evmgalkvc47spmf9d111fgunade.ch. 900 IN RRSIG NSEC3 13 2 900 20190530230246 20190430230146 2668 ch. KXxEOPwxxLAnmvANN0+etjfg7zXxuUaEY7hcA8JzgFIH6n/KRhQ+smAm l2hwxFQs3aZ3RvIAsW5t1M14O3NSKw==
          1kuo2tq4nik4c4e32laibgaredef2m6s.ch. 900 IN NSEC3 1 1 2 96A895CD 1KVL1O5V5VMTENKS4D5EGJVEMJPR3AJ5 NS DS RRSIG
          1kuo2tq4nik4c4e32laibgaredef2m6s.ch. 900 IN RRSIG NSEC3 13 2 900 20190610213355 20190511210146 2668 ch. xQecC0P+nQb4mIUYhdGPbzbWau0WjM+uuxnuGrgz3mPdkLHIizIpVQX3 byfOohYJKOMWxw5T7NQRILdjPVoxxQ==

          ;; Query time: 14 msec
          ;; SERVER: 192.168.23.1#53(192.168.23.1)
          ;; WHEN: Mon May 13 23:06:56 CEST 2019
          ;; MSG SIZE  rcvd: 745

          Um dort an die Hostnamen zu kommen, müsste man diese cracken. Hashcat bietet beispielsweise auch NSEC3 als Algorithmus an: https://hashcat.net/wiki/doku.php?id=example_hashes → NSEC3.

          Hier findest du übrigens ein super Tool um DNSSEC zu visualisieren: http://dnsviz.net/d/icann.org/dnssec/

Leave a Comment