DNSSEC is a secure implementation of the ubiquitous DNS system that ensures integrity and trust by signing all DNS records with security keys to create cryptographic signatures. These signatures are stored along with traditional DNS records (MX, A, AAAA, CNAME, etc.) and by checking the signature, this ensures the records returned by the DNS server come from the name server authorized for the given zone. Traditional DNS systems are vulnerable to both man-in-the middle attacks, where the DNS records are altered in route to the user, and DNS poising attacks, where the local DNS resolver (most likely your computer) receives a flood of bad DNS resolutions that tell the local resolver to resolve a given domain to the attacker’s site, rather than the legitimate one. This article is not intended to review possible DNS attacks, but to provide a better understanding of DNSSEC and how it operates.
The first and immediate change that DNSSEC has is the introduction of a host of new DNS record types that facilitate the cryptographic trust the system relies upon. We will name all the records here for reference, and proceed to explain how they function and what role they play later in the article.
- RRSIG — contains the cryptographic signature for an associated record set
- DNSKEY — contains the public signing key
- DS — contains the hash of DNSKEY
- NSEC(3) — contains a denial-of-existence record
The first step in setting up a DNSSEC system is to group all resource records (RR) into a set or RRset. The RRset bundles all records of the same type and label into a single bundle that can later be signed. Rather than signing each record individually, all AAAA records can be signed together as well as any other type of record used in the DNS Zone. This grouping greatly reduces the traffic required to verify and trust each record, as the cryptographic data only needs to be pulled once for all records of the same type.
Once the RRsets have been established, the DNS servers authoritative over the zone, will sign each RRset with the a zone-signing key (ZSK) pair. The structure of this key is asymmetrical in a similar fashion to SSL communications, where there is a private and public key pair. In this case, the RRsets are signed with the private portion of the zone-signing key, while the public portion is later used to verify the signature. As part of DNSSEC, when each RRset is signed with the public key, the resulting signature is stored in a separate resource record called the RRSIG record. Of course the signature is useless without the public portion of the zone-signing key to verify that the signature matched the RRset. To allow the DNS resolver to validate the signature, another record containing the public portion of the zone-singing key is made available in the DNSKEY record. Now, when a DNS resolver requests a type of record (ex. A), the name server authoritative over the zone will return both the A record and the RRSIG record. The resolver then queries the DNS server again for the DNSKEY record containing the public ZSK and can then validate that the requested record is valid and coming from a trusted source.
One glaring issue in this setup is that if an attacker was performing a man-in-the-middle attack, all the attacker would need to do is to replace the DNSKEY record with his own, and the attacker could spoof the entire process and the DNS resolver would not know the difference. Thus there needs to be a way to validate the authenticity of the public ZSK first, before we can use it to verify the record. This is where the key-singing key comes into play.
The role of the key-signing key (KSK) is to validate the ZSK and provide a means of ensuring trust through the entire DNSSEC system. The KSK validates the ZSK in much the same way as the ZSK validates the RRsets. That is, the KSK signs the public portion of the ZSK (which as previously discussed is stored as a DNSKEY record) and in doing so creates an additional RRSIG record used to validate the ZSK’s DNSKEY record. The public portion of the key-signing key is itself stored in another DNSKEY record, which together with the DNSKEY record for the ZSK form an RRset of DNSKEY records. To help simply, here is the step process of validating a record from the perspective of a DNS resolver.
- The resolver queries the DNS server for a record (ex. A)
- The DNS server returns the RRset containing the record as well as the RRSIG record containing the signature of RRset signed by the ZSK
- The resolver then queries the DNS server for the DNSKEY record to retrieve the public ZSK to validate the signature.
- The DNS server returns the RRset containing both the ZSK and the KSK as well as the RRSIG record containing the signature for the RRset of both ZSK and KSK.
- The resolver now has all it need to validate the query. It verifies the RRSIG for the request RRset (the A records) with the public ZSK
- If that passes, then it validates the ZSK by comparing the RRSIG of the DNSKEY RRset with the public KSK.
With this process complete, we can be sure that entire zone is secure and trust has been established. This would be fine, if DNS existed as only one zone, but this is of course not the case. DNS is hierarchical, and trust in one zone is to say nothing of its child or parents zones. Furthermore, although we have been able to establish trust within the zone, we have not established trust of the zone. You can think of it as though you are trying to read a book on elephants. So far we have verified that everything written in the book is true and factual, but we have not yet established if the book itself is about elephants or rhinos, or particle physics.
Delegation Signer Records
Now that we have ensured the records returned by a zone can be valid, we need a way of validating the zone itself. To do so DNSSEC simply works up the chain of DNS’ hierarchical structure and passes the trust up via the parent. In other words, if you can trust the parent zone, then you can trust the child zones as well. To do this, whenever a child zone is setup, a hashed copy of the zone’s Public key-signing key (KSK) is given to the parent zone to publish as a new type of record called the Delegation Signer (DS) record. How this works is that each time a resolver is told to contact a child zone, the parent zone provides the resolver with a DS record. Not only does this tell the resolver that the child zone supports DNSSEC (DNSSEC is far from ubiquitous), but it also provides a way of validating and trusting the child zone. All the DNS resolver needs to do, is hash the public KSK of the child zone and compare it to the DS record provided by the parent. If the records match up, then the resolver can be assured that it is talking to the child-zone’s authorized DNS server. This also tells the resolver that the child’s KSK has not been tampered with, and that all records in the child zone can be trusted.
This process can be repeated at infinitude through the entire structure of DNS and ensures a chain of trust extending through the entire resolution process.
The next obvious question is okay so now we can trust the child zone, but how do we establish trust of the parent zone and its DS record. This is where the chain of Trust and Private root-signing key come into play.
Chain of Trust
Just as any other record in the DNSSEC system, the DS record is part of a RRset that has a signed RRSIG in the parent. The whole process of validation of the RRset is repeated like before, until we get to the parent’s public KSK. To verify that, we need to look at the parent’s parent (grandparent?) DS record, and to verify that we simply keep moving up the chain finding and validating the parent of the parent of the parent, until we reach root DNS zone where there are no more parents to provide a DS record for verification. (The root DNS zone is a managed cluster of servers operated by 13 named authorities by the IANA). Although this may seem very official, any some may argue the need to verify trust with the root, without a proper means of verification, there is no way to know for sure that the DNS resolved is actually talking with the root DNS zone’s servers. Thus since there are no more zones to verify the root, the duty of trust is passed from machine to human.
In a verify public and highly audited ceremony performed every quarter, the Root Signing Ceremony has several selected individuals from the international community agree and sign the root DNS zone’s RRset for the DNSKEY records. The result is a RRSIG record that can be used to verify the root DNS server’s public KSK and ZSK. This is notable, because rather than trusting the public KSK because of the parent’s DS record, the DNS resolver must ASSUME that the KSK is valid because we as humans trust the process in which the Root Signing Ceremony was performed.
The ability to build trust between parent and child zones is the backbone of DNSSEC. If any part of the chain is broken, then all records supposedly secured by the chain can be altered and changed by attackers thus defeating the entire purpose of the DNSSEC system.
Explicit Denial of Existence
There is an additional piece of DNSSEC that bares some explanation. Under a traditional DNS setup, when you ask a name server for the IP address of a domain that does not exist it returns an empty answer. That is, there is no message returned, meaning that there is nothing for DNSSEC to sign. The fix for this issue was to add NSEC and NSEC3 record types that in essence explicitly tell a DNS resolver that a given zone does not exist. It is implemented so that every record in a zone is linked to a neighbor essentially forming a ring of records that can be cycled through. If a record does not exist on the ring, then it has no possibility of existing in the zone, thus we know explicitly the requested record cannot exist
NSEC records work by returning the “Next Secure” record stored alphabetically in the Zone. For example assuming a DNS server authoritative over example.com has AAAA records for api.example.com and www.example.com. If a user attempted to navigate to blog.example.com, the DNS server would return a NSEC record containing www.example.com, indicating that not only does blog.example.com not exist, but there are also no domains between blog and www.example.com.
The astute observer may realize that the use of the NSEC record is an effective way of domain enumeration and may reveal domains a zone administrator was counting on being private.
A few solutions were proposed to close this issue, the first being NSEC3 which rather than returning the signed gap between alphabetical domains, the record that is returned is a signed gap between the alphabetical salted hash of the domains (that is to say the hashes are sorted alphabetically, and not the original domain names). This not only obfuscates the domains in the zone, but through salting, prevents rainbow table look ups and relies on an attackers ability to brute-force the hash. The attacker would likely have more success with a dictionary enumeration tool like DirBuster than they would breaking the hash. However this is still a vulnerability that could be exploited and should be understood by zone managers.
DNSSEC is an awesome tool for securing and modernizing the aging infrastructure of DNS. Unfortunately because DNS infrastructure is so entrenched as a backbone of the internet DNSSEC adoption has been slow with many many TLDs lacking support for DNSSEC. Additionally due to some misunderstandings and bad configurations of early DNSSEC it was used for DDOS amplification attacks