DNS ID PREDICTION AND EXPLOITATION ================================== By Gamma August 1998 Introduction ============ In April 1997 advisories were released by SNI (www.secnet.com) and Johannes Erdfelt (johan@borg.sventech.com) detailing a vulnerability in BIND and Microsoft Windows NT name servers. The problem lies in the usage of predictable IDs in queries and recursed queries, allowing attackers to poison domain name server caches with false hostname and address information. Details ======= Since communications between name servers are FROM port 53 TO port 53, and there's a good chance of them having to deal with more than one request at a time, the ID in the DNS packet is the only way to tell each request from one another. Without patching, BIND and MS Windows NT name servers use predictable ID's. They start at a certain number and increment from that value for each request made. In the following example we ask ns1.target.com to resolve random.attacker.org 5 times, while sniffing on attacker.org's NS. When we see the questions come through the query ID's are grabbed. This clearly shows ns1.target.com is using predictable ID's. dns# ./qidsample eth0 ns1.target.com attacker.org dns.attacker.org QID-Sample v0.1 public by Gamma '98. Questions sent... Waiting for them to come through. ns1.target.com Query ID: 32332 ns1.target.com Query ID: 32333 ns1.target.com Query ID: 32334 ns1.target.com Query ID: 32335 ns1.target.com Query ID: 32336 dns# So, if we can sniff a network then make the target NS send out a request to the NS of the domain we're sniffing then we can grab the ID from the DNS packet and then be able to predict what the next ID's are likely to be. Bad luck for them. Theoretical Attack ================== The following is an example for spoofing A records. Example Hosts ------------- MALICIOUS.ATTACKER.ORG Attacking host. Can be *.ATTACKER.ORG, it's only requirment is that it can sniff the NS of ATTACKER.ORG. A good choice of host to launch the attack from would be DNS.ATTACKER.ORG to guarantee you can sniff the traffic. DNS.ATTACKER.ORG ATTACKER.ORG's primary name server. DNS.TARGET.COM Target name server that we wish to poison. SUN2.ELITE.GOV The domain to give an A record of our choice to when DNS.TARGET.COM resolves it. DNS.ELITE.GOV Name server with auth over the domain we wish to spoof. In this case the name server controls *.ELITE.GOV. 31.3.3.7 IP we want SUN2.ELITE.GOV to resolve to. The Attack ---------- 1. First of all we must check that SUN2.ELITE.GOV is not already cached on DNS.TARGET.COM. malicious# dig @dns.target.com sun2.elite.gov +norecurse ; <<>> DiG 8.1 <<>> @dns.target.com sun2.elite.gov +norecurse ; (1 server found) ;; res options: init defnam dnsrch ;; got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10 ;; flags: qr ra; QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 2 ;; QUERY SECTION: ;; sun2.elite.gov, type = A, class = IN ;; AUTHORITY SECTION: elite.gov. 12h7m37s IN NS DNS.ELITE.GOV. elite.gov. 12h7m37s IN NS DNS2.ELITE.GOV. ;; ADDITIONAL SECTION: DNS.ELITE.GOV. 12h7m37s IN A xxx.xxx.xxx.x DNS2.ELITE.GOV. 12h7m37s IN A xxx.xxx.xxx.x ;; Total query time: 1190 msec ;; FROM: malicious to SERVER: dns.target.com xxx.xxx.xxx.xxx ;; WHEN: Mon Aug 10 07:34:29 1998 ;; MSG SIZE sent: 29 rcvd: 106 malicious# Nope, it's not already cached. Good. We use the '+norecurse' query option on 'dig' to prevent DNS.TARGET.COM querying any other name servers (ie DNS.ELITE.GOV) for the address of SUN2.ELITE.GOV. Therefore we only get SUN2.ELITE.GOV's address if it is ALREADY cached on DNS.TARGET.COM, and dont risk it being cached by doing a recursive query. 2. We start sniffing DNS.ATTACKER.ORG. 3. We send a query to DNS.TARGET.COM asking for the address of NONEXISTANT.ATTACKER.ORG. Our query has the recursion desired bit set, meaning that if the nameserver we are querying has recursion enabled, it will query another nameserver with our query (assuming the information isn't already cached). By default, nslookup, host, dig etc do recursive queries. malicious# nslookup nonexistant.attacker.org dns.target.com DNS.TARGET.COM will now find out who serves *.ATTACKER.ORG and then build a query packet and send it to that server (DNS.ATTACKER.ORG). dns.target.com:53 ---> [nonexistant.attacker.org] ---> dns.attacker.org:53 4. Our sniffer waits for the query packet from DNS.TARGET.COM and when it sees it, grabs the query ID. Chances are that the next query ID's generated by DNS.TARGET.COM will fall somewhere between 0 -> 10 bigger than the query ID we just sniffed. However, this will depend on how busy the name server is at the time of the attack. The less DNS traffic there is, the more likely our attack will succeed first time. 5. Now we have a good idea what the next query ID generated by DNS.TARGET.COM will be, we send a query to DNS.TARGET.COM asking it for the address of SUN2.ELITE.GOV. dns.target.com:53 ---> [sun2.elite.gov] ---> dns.elite.gov:53 6. The second that query is sent we start sending spoofed DNS replies from DNS.ELITE.GOV to DNS.TARGET.COM telling it that SUN2.ELITE.GOV's address is 31.3.3.7. On each reply we send, the query ID is incremented by 1 so we should hit the correct query ID. dns.target.com:53 <--- . . . . . . . . . . dns.elite.gov:53 | ------- [sun2.elite.gov == 31.3.3.7] ^ dns.attacker.org spoofing dns.elite.gov:53 ---' 7. If we guessed the query ID, and our response is recieved before DNS.ELITE.GOV's reply, our response will be taken as valid and cached on DNS.TARGET.COM. Subsequent responses (ie. from DNS.ELITE.GOV) will be discarded. Now if we query DNS.TARGET.COM for the address of SUN2.ELITE.GOV it will reply with 31.3.3.7. malicious# nslookup sun2.elite.gov dns.target.com Server: dns.target.com Address: xxx.xxx.xxx.xxx Non-authoritative answer: Name: sun2.elite.gov Address: 31.3.3.7 malicious# 8. The attack succeeded. Now any query sent to DNS.TARGET.COM asking for SUN2.ELITE.GOV's address will get 31.3.3.7 as a response. Therefore, anyone using DNS.TARGET.COM as their resolver will connect to 31.3.3.7 if they try to contact SUN2.ELITE.GOV. Our entry in the cache will remain there until the TTL runs out. The same applies for spoofing PTR records; except we change the IP (31.3.3.7) to the IP we wish to be pointed to by our choosen domain. DNS.ELITE.GOV also needs replacing with the name server that has authority over our specified IP. Poison the target's cache with both PTR and A records that correspond to each other and you can bypass any tcp wrapper configuration that is using hostnames and not IP addresses. TCP wrappers are only as good as the information their name server passes them. "tcpd verifies the client host name that is returned by the address->name DNS server by looking at the host name and address that are returned by the name->address DNS server. If any discrepancy is detected, tcpd concludes that it is dealing with a host that pretends to have someone elses host name." -- 'tcpd' man page. Real-Life Attacks ================= There are several possibilities for practical use. Each will be covered below. 1. If the target host you want access to is running systat, netstat, finger, snmp, rusers services it is possible to obtain hostnames/IP addresses of users currently logged on to that host. There will be a high chance that those users are using the name servers that serve their domain, and not a random NS. The attacker poisons those name servers with A records saying that the target host has the attackers IP address. All popular ports on the attacking host are forwarded to the target host, and a sniffer is started. The attacker then denial of services the selected victim user and sits and waits for them to re-login to the target host. The unaware victim's connection will then pass through the attackers box to the target host and everything will appear to be fine to them. The attacker then obtains the users login from their sniffer logs and target's security has been compromised. 2. If the attacker can make an educated guess to what host/hosts are trusted by a target host, then they can poison the target's name servers with PTR and A records which correspond to each other and obtain access via r*-services. NB: The trusted host needs to be controlled by different name servers to target's name servers as you can't poison a name server with a domain which it controls. 3. Denial of service. The attacker doesn't like www.warez.com so he mass poisons internet name servers with an A record for www.warez.com that does not exist (eg. 0.0.0.1). 4. Theft of services. www.company.com and www.competitor.com are rival companies. The attacker poisons name servers with A or CNAME records pointing www.company.com to www.competitor.com. They may also poison NS's with MX records so all mail for company.com gets sent to competitor.com. (This was covered in Johannes Erdfelt's paper). 5. IRC channel takeovers. The attacker sits in the target channel and watches which people get auto-opped by any bots in the channel. The attacker then poisons an IRC server's name servers with PTR and A records for the auto-opped domain so they can join the channel and get opped. You cannot replace DNS information that is already in a server's cache but you can add to several records. By adding records which have a higher TTL value than records already in the cache you may outlive the original records so that your information starts to get used after the orignal records have died out. A can add NS can add MX can add PTR cannot add CNAME cannot add Summary ======= This is a protocol attack, not an error in BIND/MS NT name servers. SNI released a patch for BIND in April '97 to make it use random query ID's. I've not managed to find one name server using it. Microsoft have also release a similar fix for NT name servers. Random ID's do not 100% fix the problem as all the attacker needs to do then is denial of service the name server which they need to reply before and answer with whatever range of query ID's it takes until the correct one is found. Please send any comments and questions to Gamma , email can be encrypted with the following PGP key: Type Bits/KeyID Date User ID pub 2048/54E22A49 1998/03/08 Gamma -----BEGIN PGP PUBLIC KEY BLOCK----- Version: 2.6.3i mQENAzUChPAAAAEIALiqSL4X1hn3UYtEk8uc97AfxjqXS7zhYvLrEnOWqxEST0pw rJ8QFlN+VW2fPlWef03s2T3hYx2rSidNnK4y/TrVY8oEFd/jhnpOHym4NhbsYtZ7 3Un+68JEJKhlO5j9iYSCRJU14R5k2IO9nH+I8PBf1qcspe7G5kvAqDO9rmVioqMU ytkf7MWCcB/Bg+k3myISdmeHCKfkmlSEaKvKjBC8UQ0jy60VwtyM+wdG2A1SBwyJ bB5DLHE/8duziefasit8Q0snXb9yFcS9cNqRoqED3VfrA3IFbkqNncL1gqLhWV0Q fQZMhihSmeI2VAUtAwlPofRgdyi8rqc+LlTiKkkABRG0FUdhbW1hIDxnYW1tYUBk YWMub3JnPokBFQMFEDUChPCupz4uVOIqSQEBodMH/2KrAsL8vrZosDkCxEmANYOM lLGlz/dm93Tt0mNeAxCF92sMrGZTO+A/GGT6YL+ZeLzBezk0dVAbyOBrm7/XPmOx vpS+pNsiV9rGLaOm4gy9AiFRQtjvnI7NrTqG8LJXWezlk/6ykQeaGPz+nzGJRTrc 3hXB5S/MIxGSvJWtYm4h+lC7qWr7AnRxnuIVvFpZf7/TRc73G+XdBDMCw9ogLrKJ QBOedF+NMS/Lx7ua0aqq6Okx3SYkCu/kvCKbu+jEYP2NDRDPpR2vtvIp5EG9wQ8D 6X9j29Te0/mmsgiaJMOqqVlGwHJh4FEmMf0aOoT0DSgWKA9Jbmsu/B534XmC13Y= =lkRe -----END PGP PUBLIC KEY BLOCK-----