Implementing DNSSEC Using Black-lies

Introduction

DNSSEC adds a signature record for every record type in the response, guaranteeing the integrity of the response and preventing man-in-the-middle attacks.

but what if the response is empty?

The way negative answers are handled in DNSSEC is not straightforward. originally a new record type called NSEC was introduced. NSEC returns the previous and next name in zone which proves that the name in requested query cannot exist. there are two main problems with this solution:

1- zone walking: you can start from root and ask for next location using NSEC

2- response size: additional NSEC and RRSIG record required for authentication can cause the response size to get too big, making dns server vulnerable to amplification attacks.

NSEC3, an update to NSEC made zone walking harder but not completely impossible.

another solution was proposed in RFC-4470 aka while-lies. it proposes to create dummy locations slightly before and after the requested name for NXDOMAIN responses.

Black-lies goes even further by changing NXDOMAIN responses to NODATA.

a detailed explanation of this technique can be found here: Economical With The Truth: Making DNSSEC Answers Cheap

here I will show the result of our implementation in different scenarios.

Cases

we used the sample zone from RFC-4035 to discuss different cases, (RRSIG and DNSKEY values are omitted):

example.       3600 IN SOA ns1.example. bugs.x.w.example. (
1081539377 3600 300 3600000 3600)
3600 NS ns1.example.
3600 NS ns2.example.
3600 MX 1 xx.example.
3600 NSEC a.example. NS SOA MX RRSIG NSEC DNSKEY
a.example. 3600 IN NS ns1.a.example.
3600 IN NS ns2.a.example.
3600 DS 57855 5 1 (
B6DCD485719ADCA18E5F3D48A2331627FDD3
636B )
3600 NSEC ai.example. NS DS RRSIG NSEC
ns1.a.example. 3600 IN A 192.0.2.5
ns2.a.example. 3600 IN A 192.0.2.6
ai.example. 3600 IN A 192.0.2.9
3600 HINFO "KLH-10" "ITS"
3600 AAAA 2001:db8::f00:baa9
3600 NSEC b.example. A HINFO AAAA RRSIG NSEC
b.example. 3600 IN NS ns1.b.example.
3600 IN NS ns2.b.example.
3600 NSEC ns1.example. NS RRSIG NSEC
ns1.b.example. 3600 IN A 192.0.2.7
ns2.b.example. 3600 IN A 192.0.2.8
ns1.example. 3600 IN A 192.0.2.1
3600 NSEC ns2.example. A RRSIG NSEC
ns2.example. 3600 IN A 192.0.2.2
3600 NSEC *.w.example. A RRSIG NSEC
*.w.example. 3600 IN MX 1 ai.example.
3600 NSEC x.w.example. MX RRSIG NSEC
x.w.example. 3600 IN MX 1 xx.example.
3600 NSEC x.y.w.example. MX RRSIG NSEC
x.y.w.example. 3600 IN MX 1 xx.example.
3600 NSEC xx.example. MX RRSIG NSEC
xx.example. 3600 IN A 192.0.2.10
3600 HINFO "KLH-10" "TOPS-20"
3600 AAAA 2001:db8::f00:baaa

1 —Answer

A successful query to an authoritative server.

;; QUESTION SECTION:
;x.w.example. IN MX

here we return the same answer:

;; ANSWER SECTION:
x.w.example. 3600 IN MX 1 xx.example.
x.w.example. 3600 IN RRSIG MX 8 3 3600 20200715093313 20200707063313 28743 example. ...

2 — Name Error

An authoritative name error.

;; Question
ml.example. IN A

Normal Answer:

;; Header: QR AA DO RCODE=3;; Answer
;; (empty)

;; Authority
example. 3600 IN SOA ns1.example. bugs.x.w.example. (
1081539377
3600
300
3600000
3600
)
example. 3600 RRSIG SOA 5 1 3600 20040509183619 (
20040409183619 38519 example.
...
b.example. 3600 NSEC ns1.example. NS RRSIG NSEC
b.example. 3600 RRSIG NSEC 5 2 3600 20040509183619 (
20040409183619 38519 example.
...
example. 3600 NSEC a.example. NS SOA MX RRSIG NSEC DNSKEY
example. 3600 RRSIG NSEC 5 1 3600 20040509183619 (
20040409183619 38519 example.
...

The NSEC RRs prove that the name does not exist and that no covering wildcard exists.

Black-lies answer:

;; Header: QR AA DO RCODE=0;; Answer
;; (empty)

;; Authority
example. 3600 IN SOA ns1.example. bugs.x.w.example. (
1081539377 3600 300 3600000 3600)
example. 3600 IN RRSIG SOA 8 1 3600 20200715094623 (
20200707064623 28743 example.
...
ml.example. 3600 IN NSEC \000.ml.example. RRSIG NSEC
ml.example. 3600 IN RRSIG NSEC 8 2 3600 20200715094623 (
20200707064623 28743 example.
...

here we respond with RCODE=0 (SUCCESS, NODATA). there is one RRSIG for SOA and one black-lies RRSIG for ml.example., claiming that ml.example. exists but only contains RRSIG and NSEC records.

3 — No Data Error

A "no data" response.

;; Question
ns1.example. IN MX

Normal answer:

;; Answer
;; (empty)

;; Authority
example. 3600 IN SOA ns1.example. bugs.x.w.example. (
1081539377 3600 300 3600000 3600)
example. 3600 RRSIG SOA 5 1 3600 20040509183619 (
20040409183619 38519 example.
...
ns1.example. 3600 NSEC ns2.example. A RRSIG NSEC
ns1.example. 3600 RRSIG NSEC 5 2 3600 20040509183619 (
20040409183619 38519 example.
...

The NSEC RR proves that the name exists and that the requested RR type does not.

Black-lies answer:

;; AUTHORITY SECTION:
example. 3600 IN SOA ns1.example. bugs.x.w.example. (
1081539377 3600 300 3600000 3600)
example. 3600 RRSIG SOA 8 1 3600 20200715100708
20200707070708 28743 example.
...
ns1.example. 3600 NSEC \000.ns1.example. A
CNAME PTR TXT AAAA SRV RRSIG NSEC TLSA CAA
ns1.example. 3600 RRSIG NSEC 8 2 3600 20200715100708
20200707070708 28743 example.
...

our answer here is similar to the normal except that in NSEC record for ns1.example. we add all supported RR types except for the one requested.

4 — Referral to Signed Zone

;; Question
mc.a.example. IN MX

The DS RR contains the data which the resolver will need to validate the corresponding DNSKEY RR in the child zone’s apex.

answers are the same here:

;; Answer
;; (empty)

;; Authority
a.example. 3600 IN NS ns1.a.example.
a.example. 3600 IN NS ns2.a.example.
a.example. 3600 DS 57855 5 1 (
B6DCD485719ADCA18E5F3D48A2331627FDD3
636B )
a.example. 3600 RRSIG DS 5 2 3600 20040509183619 (
20040409183619 38519 example.
...
;; Additional
ns1.a.example. 3600 IN A 192.0.2.5
ns2.a.example. 3600 IN A 192.0.2.6

5 — Referral to Unsigned Zone

;; Question
mc.b.example. IN MX

Normal answer:

;; Answer
;; (empty)

;; Authority
b.example. 3600 IN NS ns1.b.example.
b.example. 3600 IN NS ns2.b.example.
b.example. 3600 NSEC ns1.example. NS RRSIG NSEC
b.example. 3600 RRSIG NSEC 5 2 3600 20040509183619 (
20040409183619 38519 example.
...

The NSEC RR proves that no DS RR for this delegation exists in the parent zone.

Black-lies answer:

;; Answer
;; (empty)

;; Authority
b.example. 3600 IN NS ns1.b.example.
b.example. 3600 IN NS ns2.b.example.
b.example. 3600 IN NSEC \000.b.example. NS RRSIG NSEC
b.example. 3600 IN RRSIG NSEC 8 2 3600 20200715102857 (
20200707072857 28743 example.
...

there’s a problem with NSEC’s next label; we can’t use \000.b.example. because it’s outside our authority, and we can’t/don’t want to return the next label inside authority (ns.example. in this case). using root or any other default label can also cause trouble, recursors may mark anything in between as NXDOMIAN and negative-cache them. as of now I dont have a better soolution for this problem.

6 — Wildcard Expansion

A successful query that was answered via wildcard expansion.

;; Question
a.z.w.example. IN MX

Normal answer:

;; Answer
a.z.w.example. 3600 IN MX 1 ai.example.
a.z.w.example. 3600 RRSIG MX 5 2 3600 20040509183619 (
20040409183619 38519 example.
...
;; Authority
example. 3600 NS ns1.example.
example. 3600 NS ns2.example.
example. 3600 RRSIG NS 5 1 3600 20040509183619 (
20040409183619 38519 example.
...
x.y.w.example. 3600 NSEC xx.example. MX RRSIG NSEC
x.y.w.example. 3600 RRSIG NSEC 5 4 3600 20040509183619 (
20040409183619 38519 example.
...

The label count in the answer’s RRSIG RR indicated that a wildcard RRset was expanded to produce this response, and the NSEC RR proves that no closer match exists in the zone.

Black-lies answer:

;; Answer
a.z.w.example. 3600 IN MX 1 ai.example.
a.z.w.example. 3600 IN RRSIG MX 8 4 3600 20200715104329 (
20200707074329 28743 example.
...

here we claim that there was no wildcard expansion and return a normal answer.

7 — Wildcard No Data Error

A "no data" response for a name covered by a wildcard.

;; Question
a.z.w.example. IN AAAA

Normal answer:

;; Answer
;; (empty)

;; Authority
example. 3600 IN SOA ns1.example. bugs.x.w.example. (
1081539377 3600 300 3600000 3600)
example. 3600 RRSIG SOA 5 1 3600 20040509183619 (
20040409183619 38519 example.
...
x.y.w.example. 3600 NSEC xx.example. MX RRSIG NSEC
x.y.w.example. 3600 RRSIG NSEC 5 4 3600 20040509183619 (
20040409183619 38519 example.
...
*.w.example. 3600 NSEC x.w.example. MX RRSIG NSEC
*.w.example. 3600 RRSIG NSEC 5 2 3600 20040509183619 (
20040409183619 38519 example.
...

The NSEC RRs proce that the matching wildcard name does not have any RRs of the requested type and that no closer match exists in the zone.

Black-lies answer:

;; Answer
;; (empty)

;; Authority
a.z.w.example. 3600 NSEC \000.a.z.w.example.
A CNAME PTR MX TXT SRV RRSIG NSEC TLSA CAA
a.z.w.example. 3600 RRSIG NSEC 8 4 3600 20200715105328
20200707075328 28743 example.
...
example. 3600 SOA ns1.example. bugs.x.w.example. (
1081539377 3600 300 3600000 3600)
example. 3600 RRSIG SOA 8 1 3600 20200715105328
20200707075328 28743 example.
...

here again we ignore wildcard expansion and return a normal NODATA response.

8 — DS Child Zone No Data Error

A "no data" response for a QTYPE=DS query that was mistakenly sent to
a name server for the child zone.

;; Question
example. IN DS

Normal answer:

;; Answer
;; (empty)

;; Authority
example. 3600 IN SOA ns1.example. bugs.x.w.example. (
1081539377 3600 300 3600000 3600)
example. 3600 RRSIG SOA 5 1 3600 20040509183619 (
20040409183619 38519 example.
...
example. 3600 NSEC a.example. NS SOA MX RRSIG NSEC DNSKEY
example. 3600 RRSIG NSEC 5 1 3600 20040509183619 (
20040409183619 38519 example.
...

Black-lies answer:

;; Answer
;; (empty)

;; Authority
example. 3600 IN SOA ns1.example. bugs.x.w.example. (
1081539377 3600 300 3600000 3600)
example. 3600 RRSIG SOA 8 1 3600 20200715110009
20200707080009 28743 example.
...
example. 3600 NSEC \000.example.
A NS SOA PTR MX TXT AAAA
SRV RRSIG NSEC TLSA CAA
example. 3600 RRSIG NSEC 8 1 3600 20200715110009
20200707080009 28743 example.
...

Conclusion

our implementation seems to work fine. although there are still some flaws. you can check out our code here.

--

--

--

DNS specialist, Golang enthusiast

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Common Web Hack Attacks

Common web hack attacks

Another Great News!!

{UPDATE} Word Break - Crossword Puzzles Hack Free Resources Generator

How to unlock your Android phone without flashing it when you forget your password.

Now on Poloniex: Measurable Data Token

Chains on Chains!! Chaining several IDOR’s into Account Takeover(PART ONE)

GDPR The Basic Facts — Enhanced Rights

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Arash Cordi

Arash Cordi

DNS specialist, Golang enthusiast

More from Medium

Blockchain in Fintech: A Catalyst for Disruption in Finance World

Automating Active Directory lab deployment (And focusing on Juicy stuff) — The Auror project…

Add proxy support for WSO2 default stripe extension implementation - Monetizing an API

CS371p Spring 2022: Justin Milushev