One (Hypothetical) Concrete Example of a Practical DNS Validation Attack:
(Author's note: I've chosen for this example to utilize the Let's Encrypt CA as the Certificate Authority involved and I have chosen as a target for improper validation the domain
eff.org. Neither of these is in any way endorsing what I have documented here. Neither is aware of the scenario I am painting here. I have NOT actually carried out a route hijack attack in order to get a certificate for
eff.org. I DO NOT intend to do so. I have laid out the research methodology and data points of interest that one who would seek to get a certificate for
eff.org illegitimately would need.)
The target:
eff.org
In order to validate as
eff.org, one needs to -- at a minimum -- be positioned to temporarily answer DNS queries on behalf of
eff.org. Assuming that the DNS root servers, the .org TLD servers and the registrar for
eff.org are not to be compromised, the best mechanism to accomplish answering for
eff.org in the DNS will be to hijack the IP space for the authoritative name servers for the
eff.org zone.
First, we must find them.
appleprov1:~ mhardeman$ dig +trace -t NS
eff.org
; <<>> DiG 9.8.3-P1 <<>> +trace -t NS
eff.org
;; global options: +cmd
. 161925 IN NS
a.root-servers.net.
. 161925 IN NS
b.root-servers.net.
. 161925 IN NS
c.root-servers.net.
. 161925 IN NS
d.root-servers.net.
. 161925 IN NS
e.root-servers.net.
. 161925 IN NS
f.root-servers.net.
. 161925 IN NS
g.root-servers.net.
. 161925 IN NS
h.root-servers.net.
. 161925 IN NS
i.root-servers.net.
. 161925 IN NS
j.root-servers.net.
. 161925 IN NS
k.root-servers.net.
. 161925 IN NS
l.root-servers.net.
. 161925 IN NS
m.root-servers.net.
;; Received 228 bytes from 10.47.52.1#53(10.47.52.1) in 330 ms
org. 172800 IN NS
a0.org.afilias-nst.info.
org. 172800 IN NS
a2.org.afilias-nst.info.
org. 172800 IN NS
b0.org.afilias-nst.org.
org. 172800 IN NS
b2.org.afilias-nst.org.
org. 172800 IN NS
c0.org.afilias-nst.info.
org. 172800 IN NS
d0.org.afilias-nst.org.
;; Received 427 bytes from 198.97.190.53#53(198.97.190.53) in 154 ms
eff.org. 86400 IN NS
ns1.eff.org.
eff.org. 86400 IN NS
ns2.eff.org.
;; Received 93 bytes from 2001:500:b::1#53(2001:500:b::1) in 205 ms
eff.org. 7200 IN NS
ns1.eff.org.
eff.org. 7200 IN NS
ns6.eff.org.
eff.org. 7200 IN NS
ns2.eff.org.
;; Received 127 bytes from 69.50.225.156#53(69.50.225.156) in 79 ms
(Further research suggests
ns6.eff.org is presently non-responsive or is in some special role - I would guess a hidden master, considering that the .org delegation servers only refer out to
ns1.eff.org and
ns2.eff.org.)
Is
eff.org DNSSEC protected? Asking "dig +trace -t DNSKEY
eff.org" will reveal no DNSKEY records returned. No DNSSEC for this zone. See also
dnsviz.net for such lookups.
So, all I need to do is hijack the IP space for
ns1.eff.org and
ns2.eff.org -- and very temporarily -- to get a certificate issued for
eff.org.
(Author's further note: I'll grant that
eff.org is probably on various peoples' high value domain list and thus would likely get policy blocked for other reasons regardless of successful domain validation. This is, after all, only an example. I also wish to set out that I give IPv4 examples below, knowing one would also need to work on the IPv6 angle as well. I do not explore this here, the principles are the same.)
Now, we need to know what IP space to hijack:
dig -t A
ns1.eff.org yields:
;; ANSWER SECTION:
ns1.eff.org. 3269 IN A 173.239.79.201
dig -t A
ns2.eff.org yields:
;; ANSWER SECTION:
ns2.eff.org. 6385 IN A 69.50.225.156
Ultimately, to succeed in getting a DNS TXT record domain validation from Let's Encrypt for
eff.org, we will need to _very briefly_ take over the IP space and be able to receive and answer DNS queries for 173.239.79.201 and 69.50.225.156. This is probably far easier for a great number of people than many would believe.
Let's understand more about those two IP addresses and how the network space containing those two IP addresses is advertised to the broader internet. I will utilize the University of Oregon's Route Views project for this:
route-views>show ip bgp 173.239.79.201
BGP routing table entry for
173.239.64.0/20, version 196945145
Paths: (41 available, best #18, table default)
Not advertised to any peer
Refresh Epoch 1
3277 3267 174 32354
195.208.112.161 from 195.208.112.161 (194.85.4.13)
Origin IGP, localpref 100, valid, external
Community: 3277:3267 3277:65321 3277:65323 3277:65331
route-views>show ip bgp 69.50.225.156
BGP routing table entry for
69.50.224.0/19, version 103657500
Paths: (40 available, best #33, table default)
Not advertised to any peer
Refresh Epoch 1
58511 6939 13332
103.247.3.45 from 103.247.3.45 (103.247.3.45)
Origin IGP, localpref 100, valid, external
The key facts we are most interested in is who is advertising this IP space (what ASN ultimately advertises the space) and what is the scope of the advertisement - what network block size. We have the following:
173.239.64.0/20 advertised by AS32354 (Unwired) - and -
69.50.224.0/19 advertised by AS13332 (NephoScale Inc.)
Of particular importance, our work is made easier by the fact that the IPs we wish to hijack are advertised as part of larger aggregated blocks. The global BGP network broadly accepts advertisements as small as a /24. If a couple of /24s which are subsets of the above listed /19 and /20 are suddenly apparent in the global routing table (or, in fact, visible within a chosen subset of the global routing tables) then the routes for just that single /24 within the larger blocks will be hijacked, leaving the rest of the IP space in the /19 and /20 unharmed. This greatly reduces the odds that a hijack will be detected. It also greatly improves the odds that the hijack will propagate sufficiently to get the needed effect. Remember that in routing table lookups, the most specific match will win (specialized policy routing excepted). A /24 is smaller than a /19 or /20.
The following advertisements would beat out the legitimate advertisements for just the individual /24 segments that we need to perform our hijack of the DNS servers' IPs:
173.239.79.0/24
69.50.224.0/24
If we only need to convince a relatively small part of the world, versus the whole world, that we are the path to those two /24 network blocks, and if we only need to do so for a brief time, we will massively reduce the odds that our BGP routing hijack for these two blocks will be caught as fraudulent or even casually observed.
But how can we tell who must be convinced? By definition, we must convince the software/hardware/infrastructure at our target CA (Let's Encrypt) which performs the domain validation DNS queries.
Today and yesterday, I ran a total of 4 DNS validation queries (2 on each day) to domains I legitimately own and control. In all instances, the IPv4 IP address making these DNS validation queries was:
64.78.149.164
While Let's Encrypt doesn't advertise that IP address to the world, there's no real way for them to hide the source of a validation either. I would presume that they roll to different IPs fairly frequently, but it doesn't seem to happen super often.
What can we learn about this IP?
>show ip bgp 64.78.149.164
BGP routing table entry for
64.78.144.0/20, version 150101167
Paths: (41 available, best #34, table default)
Not advertised to any peer
Refresh Epoch 1
58511 6939 13649
103.247.3.45 from 103.247.3.45 (103.247.3.45)
Origin IGP, localpref 100, valid, external
The IP address is part of an advertisement (
64.78.144.0/20) originated by AS13649 (ViaWest) in Colorado. This is the ISP providing service to Let's Encrypt's DNS validation point at the moment.
In order to successfully get a certificate from
eff.org from Let's Encrypt, we need to persuade ViaWest that there's a better than presently reflected route to
173.239.79.0/24 and
69.50.224.0/24 and that some piece of infrastructure we control is that better route. Ultimately, we likely don't even have to persuade ViaWest directly. We could, instead, merely persuade one of ViaWest's upstream transit suppliers.
Knowing where to make what advertisement to get ViaWest to see those two /24s is a skillset which is effectively only built in actual industry experience. The specifics of how one would most easily place this attack and constrain the scope to a point that it would impact little overall internet traffic and would limit visibility of the hijack to the larger internet vary with every target. From a glance, I can tell you that ViaWest purchases IPv4 transit from at least Level3 (AS3356) and QWest/CenturyLink (AS209). More than that though, ViaWest is a fairly aggressive IXP peering participant with a stated "Open" peering policy. They are present on several exchanges, including CoreSite's Any2 Denver Internet Exchange. See their entry at the PeeringDB database:
https://www.peeringdb.com/net/388 The majority of peering relationships across IXPs don't validate ownership of the advertisements other than a visual check at the initial peering establishment and a rule in the routers to auto-shut the peering if a peering which historically shared 200 routes tries to send 300+ routes. Things like that. Why that is the general case is a long, complicated and nuanced topic. Anyone with money -- and not even all that much of that -- could colocate at CoreSite Any2 Denver, join the exchange, and probably get a peering relationship with ViaWest easily. Two weeks later, in the middle of the nite, ViaWest for a period of 5 minutes sees new advertisements for the /24s containing the two IP addresses we need to hijack.
At that time, we would run the certificate validation requests and the certificate issuance requests, get the certificate and disappear the advertisements. If we were so lucky as to have secured a direct peering relationship with ViaWest, then only we and ViaWest will have ever seen the route. Let's Encrypt's infrastructure will have known nothing. In the worst case, ViaWest's subscribers may be unable to access things running on the (at most) ~500ish IPs we just hijacked for a period that definitely wouldn't need to exceed 5 minutes. In the middle of the night.
As easily as that, one could definitely get a certificate issued without breaking most of the internet, without leaving much of a trace, and without failing domain validation.
That certificate could later be utilized in a targeted MITM attack.
My purpose in writing this was to illustrate just how easily someone with quite modest resources and the right skill set can presently overcome the technical checks of DNS based domain validation (which includes things such as HTTP validation).
I'll write separately in a less sensationalized post to describe each risk factor and appropriate mitigations.
In closing I wish to emphasize that Let's Encrypt was only chosen for this example because it was convenient as I already had a client installed and also literally free for me to perform multiple validations and certificate issuances. (Though I could do that with Comodo's domain validation 3 month trial product too, couldn't I?) A couple of extra checks strongly suggest that quite several other CAs which issue domain validation products could be just as easily subverted. As yet, I have not identified a CA which I believe is well prepared for this level of network manipulation. To their credit, it is clear to me that the people behind Let's Encrypt actual recognize this risk (on the basis of comments I've seen in their discussion forums as well as commentary in some of their recent GitHub commits.) Furthermore, there is evidence that they are working toward a plan which would help mitigate the risks of this kind of attack. I reiterate again that nothing in this article highlights a risk surfaced by Let's Encrypt that isn't also exposed by every other DV issuing CA I've scrutinized.
Thanks,
Matt Hardeman