
Dieses Projekt generiert DNS-Zonendateien mit benutzerdefinierten NSEC3-Parametern, um die Angriffe in CVE-2023-50868 zu reproduzieren und zu evaluieren.
Dieses Projekt erzeugt DNS-Zonefiles mit benutzerdefinierten NSEC3-Parametern, um die Angriffe aus CVE-2023-50868 zu reproduzieren und auszuwerten.
Python3 (getestet mit Python3.10)
Installierte Python-Abhängigkeiten:
lib: Python-Hilfsprogramme, einschließlich:
keys.py: Wrapper-Funktionen zum Laden/Speichern von Schlüsseln in Dateiennsec.py: Implementierung der DNSSEC-NSEC-Hashesdnssec.py: Modifizierte/gepatchte dnspython-Funktionen mit NSEC3-Unterstützungconfig.py: Hilfsprogramme zum Laden der Konfigurationkeys: PEM-Dateien mit vorab generierten Schlüsseln (generiert mit gen_keys.py)zones: Zonefiles (generiert mit gen_zones.py)config.json: BeispielkonfigurationKonfigurieren Sie, welche NSEC3-Zonen erstellt werden sollen, indem Sie die config.json ändern (siehe Config).
Schlüssel erzeugen:
$ ./gen_keys.py
Für jede Zone werden ein KSK und ein ZSK erzeugt. Die Schlüssel werden bei einer Änderung der Konfiguration wiederverwendet, solange die Zonennamen in der Konfiguration unverändert bleiben.
Zonefiles erzeugen:
$ ./gen_zones.py -c
Die Option -c aktiviert den Export von Konfigurationsdateien (derzeit nur für BIND9).
Verwenden Sie --help für weitere Optionen.
Die Konfigurationsstruktur enthält zwei Elemente:
default: Standardparameter für die Zonen (bisher werden nicht alle unterstützt).zones: Liste aller zu exportierenden Zonen.Eine Zone enthält:
name (erforderlich): Der Name, der beim Referenzieren der Zone und als Dateiname beim Export verwendet wird.origin (erforderlich): Der kanonische Domainname des Zonen-Origins.parent: Der Name der Parent-Zone (nicht der Origin), zu der die NS-, A-, DS- und NSEC3PARAM-Einträge dieser Zone hinzugefügt werden.keysize (erforderlich): Die RSA-Schlüssellänge (bisher nur RSA).nsec3: Die NSEC3-Parameter:
iterations: Standardwert: 0salt: Standardwert: ''algorithm: Integer-Wert; derzeit wird nur SHA-1 (1) unterstützt.tight: Ein spezieller boolescher Wert, der steuert, ob NSEC3-Einträge unmittelbar nach dem Origin und vor und nach *.origin hinzugefügt werden sollen. Wenn z. B. *.origin einen NSEC3-Eintrag 1d..ua.origin. hat, werden auch die Einträge für 1d..u0.origin. und 1d..ub.origin. zur Zonendatei hinzugefügt. Dadurch wird sichergestellt, dass jeder NXDOMAIN-Beweis für eine Subdomain des Origins (z. B. a.origin.) drei NSEC3-Einträge erfordert, da die NSEC3-Einträge, die den Origin und den Wildcard abdecken, einen sehr kleinen Bereich bis zu next_hash haben.ns: Die Nameserver dieser Zone. Ein einzelner Wert oder eine Liste von:
ns: Der Domainname eines Nameservers; Standardwert ist ns1.origin.ip: Die IPv4-Adresse (IPv6 wird derzeit nicht unterstützt); Standardwert ist 172.0.0.1.soa: Die SOA-RDATA.rrsets: Eine Liste zusätzlicher RRsets, angegeben als 5-Tupel-Liste [Domainname, ttl, class, type, rdata], wobei alle Werte (außer optional der TTL) als Zeichenketten angegeben werden.Um den NSEC3-Angriff zu reproduzieren, wird in diesem Abschnitt ein mögliches individuelles Setup bestehend aus einem DNS-Nameserver und einem Opfer-Resolver veranschaulicht.
Stellen Sie vor dem Fortfahren sicher, dass die Systemumgebung über eine ausreichend konfigurierte Firewall verfügt, um öffentliche Server nicht den Angriffs-Zonefiles auszusetzen.
Installieren Sie den NSD-Nameserver (aktuelle Version).
Besuchen Sie die NLNetlabs-Website (https://nsd.docs.nlnetlabs.nl/en/latest/installation.html) für Installationsanweisungen.
Es wird empfohlen, den Nameserver entweder in einer VM oder in einem Container bereitzustellen. Als Ausgangspunkt gibt es ein kleines Dockerfile in docker/nsd.
Erstellen Sie den Container mit docker build -t <tag> <path_to_dockerfile>, zum Beispiel:
cd docker/nsd && docker build -t nsd .
Starten Sie den Container mit docker run -it --name <name> nsd bash, um eine Konsole im Container zu öffnen.
Als Nächstes muss der Nameserver so konfiguriert werden, dass er die Angreifer-Zonefiles hostet.
Dies erfordert eine korrekte Konfiguration der zu erzeugenden Zonefiles (am wichtigsten ist, dass die in den NS-Einträgen angegebene IP-Adresse mit der IP-Adresse des Containers übereinstimmt).
Wenn kein Netzwerk konfiguriert wurde, kann die IP-Adresse des Containers mit folgendem Befehl angezeigt werden:
docker container inspect <name> | grep IPAddress
Erzeugen Sie die Zonen mit Konfigurationsausgabe (./gen_zones.py -c, siehe oben) und kopieren Sie den Ausgabeordner zones aus dem Repository-Verzeichnis in den Docker-Container:
docker cp ./zones <name>:/etc/nsd
In der Container-Konsole muss die NSD-Konfiguration /etc/nsd/nsd.conf im Container um die folgenden Zeilen ergänzt werden:
verify:
enable: no
remote-control:
control-enable: no
include: "/etc/nsd/zones/nsd.conf"
Führen Sie schließlich NSD aus der Container-Shell mit dem folgenden Befehl aus:
/usr/sbin/nsd -d -c /etc/nsd/nsd.conf
Aktivieren Sie die Protokollausgabe mit der Option -V 4.
Wenn keine Probleme aufgetreten sind, sollte der autoritative Nameserver nun laufen. Sie können dies überprüfen, indem Sie vom Hostsystem aus mit dig eine Abfrage für eine der Zonen-Domains durchführen:
dig @<ip-addr-of-nsd-container> <domain>
Installieren Sie einen Resolver. In dieser Demonstration zeigen wir einen möglichen Ansatz für Unbound 1.17.1.
Ein offizielles Dockerfile finden Sie hier: https://github.com/NLnetLabs/pythonunbound
Wir haben eine modifizierte Version dieses Dockerfiles in docker/unbound beigefügt, mit einer aktualisierten Ubuntu-Version und vorkonfiguriert für Unbound 1.17.1.
Klonen Sie das Repository, wechseln Sie in dessen Verzeichnis und erstellen Sie den Unbound-Container:
docker build -t <tag> .
Starten Sie den Container mit:
docker run --name <name> -it <tag> bash
Als Nächstes muss Unbound so konfiguriert werden, dass es den autoritativen NSD-Nameserver finden kann.
Dies geschieht durch Ändern der Datei unbound.conf im Arbeitsverzeichnis des Containers.
Stellen Sie dazu sicher, dass der Eintrag server.module-config aus der Konfiguration entfernt wird.
Um die DNSSEC-Validierung zu aktivieren, müssen die DNSKEY-Einträge der Angreifer-Parent-Zone manuell konfiguriert werden. Dabei muss es sich um denselben Schlüssel handeln, der zum Erzeugen der Signaturen verwendet wurde, zum Beispiel:
server:
chroot: ""
do-ip6: no
trust-anchor: "attack.er. DNSKEY 257 3 7 AwEAAdqDN3rJYlmGP3jJs5lCZq5NYrCn pCVlV0ko17JnbfYfLCroEF4reO/Xy0MK C9AVvSRTk83MHDuzMYXogm7m/gcn3Mh0 MwB2InP8jkPw5not+TMH/Wrbs31xkT2n RIBJJ+1lPF+e2AvwWvgREcEVTRbdhIqQ iM1StWXoTVudry4V"
Darüber hinaus muss eine Stub-Zone konfiguriert werden, damit der Unbound-Resolver den autoritativen NSD-Nameserver finden kann.
Dies wird erreicht, indem Folgendes zur Datei unbound.conf hinzugefügt wird:
stub-zone:
name: "attack.er."
stub-prime: yes
stub-addr: <ip-addr-of-nsd-container>
Starten Sie Unbound im Container mit:
unbound -vvv (verwenden Sie -dd, um die Daemonisierung zu verhindern).
Sie sollten nun in der Lage sein, Unbound mit dig abzufragen und die Antwortzeit zu beobachten:
dig @127.0.0.1 attack.er
Falls Sie Probleme mit dieser Anleitung haben, können Sie uns gerne für weitere Unterstützung kontaktieren.