NSEC3-beveiligingstechnologie voor DNSSEC uitgekleed
Nieuwe inzichten in de 'iteraties'- en 'salt'-parameters
Nieuwe inzichten in de 'iteraties'- en 'salt'-parameters
NSEC3 is aan DNSSEC toegevoegd om ondertekende zones tegen inventarisatie door kwaadwillenden (via 'zone walking') te beschermen. Deze beveiliging lijkt inmiddels echter achterhaald: het mechanisme kan goeddeels gekraakt worden en de cryptografie is niet goed doordacht. Daarom wordt inmiddels gewerkt aan een aanbeveling om de geavanceerde mogelijkheden van NSEC3 (een aantal extra iteraties op de hash en de toepassing van salt) niet meer te gebruiken.
Update: Naar aanleiding van de publicatie van RFC 9276 (BCP 236), waarin de hier beschreven aanbevelingen inmiddels zijn vastgelegd, hebben we eind 2022 de NSEC3-instellingen van de .nl-zone aangepast: het aantal extra iteraties voor NSEC3 is op nul ('0') gezet en de salt is nu leeg ('-').
NSEC, kort voor Next Secure, is onderdeel van DNSSEC (gespecificeerd in RFC 4034, sectie 4). Het is een methode om ook DNS-antwoorden voor niet-bestaande records van een digitale handtekening te voorzien: een zogenaamde 'authenticated denial of existence'. Het gaat dan om zogenaamde NXDOMAIN-responses (voor niet-bestaande domeinnamen) en NODATA-responses (voor niet-bestaande recordtypen van wel bestaande domeinnamen). Omdat je onmogelijk alle niet-bestaande domeinnamen kunt ondertekenen, specificeert elk NSEC-record de ruimte die tussen twee wel bestaande domeinnamen in zit. Vraag je bijvoorbeeld om een A-record voor de niet-bestaande naam gopher.example.nl, dan krijg je een NSEC-record terug dat aangeeft dat er geen domeinnamen zitten tussen de namen ftp.example.nl en mail.example.nl.
Deze NSEC-records worden aangemaakt en ondertekend bij het ondertekenen van je zone (waarmee de grootte daarvan grofweg verdubbelt). Een validerende resolver die een niet-bestaande hostnaam opvraagt, krijgt dus een ondertekend NSEC-record terug voor het interval waarin ook de door hem opgevraagde naam zich bevindt. En daarmee weet de resolver zeker dat de betreffende naam niet bestaat.
Hierbij moeten we gelijk aantekenen dat het zojuist beschreven mechanisme het uitgangspunt is. In dit artikel kun je bijvoorbeeld lezen hoe Cloudflare verschillende slimmigheidjes heeft bedacht om NSEC3-records te generen voor hun dynamische zones (waarbij DNS-antwoorden on-the-fly worden gegenereerd uit een database). Het probleem van NSEC is dat het heel eenvoudig wordt om alle hostnamen in een zone te achterhalen. Door het slim opvragen van niet-bestaande domeinnamen kun je immers alle NSEC-records verzamelen – deze vormen een gelinkte lijst – waarmee je ook alle intervalgrenzen (dat wil zeggen: de wel bestaande domeinnamen) op een rijtje hebt. Dit is in veel gevallen om veiligheidsredenen ongewenst.
NSEC3, gedefinieerd in RFC 5155, is onder andere bedacht om deze 'zone walking' of 'zone enumeration' tegen te gaan. Daarbij worden niet de domeinnamen zelf gebruikt maar alleen hun hashes (in dit geval: een digitale verhaspeling). Een client die een niet-bestaande hostnaam opvraagt, krijgt nu een ondertekend NSEC3-record terug voor het interval van hashes waarin ook de hash van de betreffende hostnaam valt. De manier waarop dit werkt is dat de NSEC-intervalgrenzen in de zone eerst gehasht worden en pas daarna in volgorde gezet voor ondertekening. Een client die een NSEC3-record valideert doet dat dus door niet de domeinnaam zelf te controleren maar door de hash daarvan te genereren en te controleren dat die hash binnen de grenzen van het NSEC3-record valt. Door het gebruik van hashes kan niet zomaar meer een lijst met bestaande domeinnamen worden gemaakt. Om te voorkomen dat iemand alsnog alle domeinnamen in je zone achterhaalt met behulp van een dictionary-tabel (waarin de hashes van alle veelgebruikte labels eerder al uitgerekend zijn), wordt nog een salt aan elke domeinnaam toegevoegd en een extra aantal slagen (iteraties) voor het uitvoeren van de hash-functie. Die instellingen zijn hetzelfde voor de hele zone en worden in het nieuwe NSEC3PARAM-record opgenomen. Door de salt (niet meer dan een random string) regelmatig te veranderen voorkom je dat iemand een herbruikbare dictionary-tabel voor je zone kan opbouwen. Achtergrondinformatie over de werking (en historie) van NSEC en NSEC3 vind je in RFC 7129.
Er is wel wat af te dingen op het ontwerp en de inzet van NSEC3. Zo zijn om te beginnen veel hostnamen (www, mx1, api, etc.) niet geheim. Bovendien maakt een aantal extra iteraties op de hash het mechanisme niet fundamenteel sterker. Voor de additionele hash-berekeningen zullen zowel krakers als validerende resolvers met grote aantallen gebruikers als ondertekenaars van grote zones ‘gelijkopgaande’ extra rekenkracht moeten inzetten. Ook het gebruik van de salt lijkt in de meeste gevallen overbodig: de hashes worden berekend over de volledige domeinnaam (FQDN), wat betekent dat een dictionary-tabel sowieso al uniek zou zijn voor een specifieke zone. Het snel doorrollen van het gebruikte salt levert daarbij maar een beperkte extra hindernis op; uitgaande van een relatief stabiele zone blijven de meeste al gevonden labels gewoon geldig. Deze inzichten hebben geleid tot de totstandkoming van een Best Current Practice (BCP) 'Guidance for NSEC3 parameter settings'. Op dit moment wordt de laatste hand gelegd aan dit document, waarin wordt aangeraden om zowel de extra iteraties als de salt niet meer te gebruiken.
Miek Gieben is DNSSEC-expert, auteur, ontwikkelaar van allerlei DNS-software, en was eerder technisch adviseur bij SIDN. Hij heeft zich in die tijd uitgebreid verdiept in NSEC3 (onder ander als medeauteur van bovengenoemde RFC 7129) en is het eens met de adviezen in het nieuwe BCP-document. Zelf is Miek überhaupt geen fan van NSEC3 en hij heeft er dan ook voor gekozen om NSEC3 helemaal niet meer in zijn CoreDNS-software te implementeren.
Belangrijkste reden is dat NSEC3 complex is en niet langer afdoende bescherming biedt tegen het originele probleem. Zo slaagden onderzoekers er al in 2014 in om tweederde van de NSEC3-beveiligde domeinen binnen de .com-zone te achterhalen. Op een enkele grafische processor (GPU) duurde dat slechts 4,5 dag.
Als je als domeinnaamhouder of operator NSEC3 wilt gebruiken, dan raden wij je aan om overeenkomstig de nieuwe BCP zowel de extra iteraties als de salt op nul te zetten. Het zou zelfs kunnen dat deze instellingen in de toekomst onderdeel worden van onze incentive-regeling voor DNSSEC. TransIP heeft hier inmiddels een voorschot op genomen en onlangs zijn iteraties-parameter op nul gezet. En ook de Internet.nl-portal heeft zijn testalgoritmen al op de nieuwe aanbeveling aangepast.