HTB - 使用 Python 進行 DNS 枚舉
DNS(Domain Name System)網域名稱系統
它將人們可讀取的網域名稱(例如,www.amazon.com) 轉換為機器可讀取的IP 地址(例如,192.0.2.44)。
傳統DNS作法:主 DNS(Primary/Master)+ 輔助 DNS(Secondary/Slave)
主 DNS:正本(可以編輯區域檔 zone file、改 A/CNAME/MX 等紀錄)輔助 DNS:影印本(通常唯讀,定期從主 DNS 把 zone 複製過來)Zone transfer(AXFR/IXFR):影印機動作(把區域資料從主送到輔)
AXFR:把整本「電話簿」整本影印走(完整區域檔)
IXFR:只影印「最近改過的那幾頁」(增量更新)
在這邊的攻擊面就是使用者可能會錯誤配置
正常情況應該是:
- 只允許「你的輔助 DNS」那些固定 IP/主機名來做 zone transfer,其他來源一律拒絕
錯誤情況: - 沒有限制來源,或 ACL 寫錯、TSIG(簽章驗證)沒用/沒設好導致任何外部 client 都可以要求 AXFR
DNS 記錄和查詢
DNS 記錄是位於權威 DNS 伺服器上的指令,包含有關網域的資訊。
這些條目以 DNS 語法編寫,為 DNS 伺服器提供適當的指令。
以下是我們在滲透測試中遇到的最常見的 DNS 記錄:
| 記錄 | 描述 |
|---|---|
| A | IP 版本 4 位址記錄 |
| AAAA | IP 版本 6 位址記錄 |
| CNAME | 規範名稱記錄 |
| HINFO | 主機資訊記錄 |
| ISDN | 綜合業務數位網路記錄 |
| MX | 郵件交換器記錄 |
| NS | 名稱 伺服器記錄 |
| PTR | 反向查找指標記錄 |
| SOA | 管理局記錄的開始 |
| TXT | 文字記錄 |
我們可以使用許多工具和資源來向 DNS 伺服器發送查詢。例如,我們可以使用以下工具:
dig
使用範例:1
2dig NS inlanefreight.com
dig SOA inlanefreight.comnslookup
使用範例:1
2nslookup -type=SPF inlanefreight.com
nslookup -type=txt _dmarc.inlanefreight.com
範例題目:
Investigate all records for the domain “inlanefreight.com” with the help of dig or nslookup and submit the one unique record in double quotes as the answer.
透過 dig 或 nslookup 指令,尋找網域名稱「inlanefreight.com」的所有記錄,並將唯一記錄以雙引號括起來作為答案提交。
我們兩種工具都可以使用,這邊使用簡單好記的dig
1 | |
Find out the corresponding IPv6 address of the domain “inlanefreight.com” and submit it as the answer.
找出網域名稱「inlanefreight.com」對應的 IPv6 位址,並將其作為答案提交。
一樣使用dig來尋找答案
1 | |
DNS 枚舉
我們可以將這些資訊分為以下幾類:
- DNS Records
- Subdomains/Hosts
- DNS Security
枚舉技術介紹:
- OSINT(上篇IG跟上上篇暗網都有簡單介紹到OSINT,OSINT就是從公開來源去尋找資訊的意思)
VirusTotal
DNSdumpster
Netcraft
Google等搜尋引擎 - Certificate Transparency (CT)
CT日誌中包含所有Certificate Authority(CA)SSL/TLS certificates 來自 Web 伺服器包括 domain names, subdomain names, 和 email addresses。)
CTFR.py - Zone transfer(區域轉移)
這個過程稱為 Asynchronous Full Transfer Zone (AXFR)。Zone transfer僅涉及文件或記錄的傳輸以及檢測所涉及伺服器資料庫中的差異。
執行區域轉移:
1
dig axfr inlanefreight.com @10.129.2.67
範例題目:
Perform a zone transfer for the “inlanefreight.htb” domain against your target and determine how many nameservers the company has. Submit the total number of nameservers as the answer.
對「inlanefreight.htb」網域名稱執行區域轉移,並確定目標公司擁有多少台網域名稱伺服器。將網域名稱伺服器總數作為答案提交。
尋找AXFR我們可以使用dig,使用方法同樣是簡單的dig加上要檢查的參數以及標的:
1 | |
Determine the IPv4 address of “ns1.inlanefreight.htb” from your target and submit it as the answer.
從目標中確定「ns1.inlanefreight.htb」的 IPv4 位址,並將其作為答案提交。
從上一題的輸出中我們就看到答案了,這邊不贅述。
Perform a zone transfer against the target “inlanefreight.htb” domain and determine the IPv4 address of ns2.inlanefreight.htb and submit it as the answer.
對目標「inlanefreight.htb」網域執行區域轉移,確定ns2.inlanefreight.htb的IPv4位址,並將其作為答案提交。
如上題。
Check if a zone transfer against the target “inlanefreight.htb” domain because we could hear from the conversations with the administrators that they are not very familiar with DNS. As a proof of concept, a TXT record was left there to serve as evidence. Submit this TXT record as the answer.
請檢查是否存在針對目標網域「inlanefreight.htb」的區域轉移,因為我們從與管理員的溝通中了解到他們對DNS不太熟悉。為了驗證概念,我們在該網域下保留了一條TXT記錄作為證據。請將此TXT記錄作為答案提交。
如上題。
終於到正題了
我們使用dnspython 這個模組來進行DNS枚舉。
以下進行逐行講解
基本用法:
1 | |
若是有多台需要解析的話,為了方便出錯比較好除錯,同時讓main更乾淨,所以函數參數能越少越好(最好不要超過三個)。
再來是加上Try-Except,讓程式在失敗的時候不會直接結束,而是會繼續運行(並輸出錯誤)。
If-Else:最好只檢查少量條件,像是判斷是否真的有拿到資料。
For-Loop:for 迴圈越簡單越好,否則迭代次數錯了很難 debug。
1 | |
使用For-Loop進行AXFR:
1 | |
範例題目:
Perform a zone transfer using the DNS-AXFR.py script against your target for the “inlanefreight.htb” domain and submit the total number of unique subdomains found.
使用 DNS-AXFR.py 腳本對目標「inlanefreight.htb」執行DNS-AXFR,並提交找到的唯一子網域總數。
1 | |
argparse
若是已經有固定功能的話可以使用ArgParser ,就不用一直更改程式碼,類似建立一個標準模組(最近終末地玩多了覺得這東西應該要叫藍圖w)。
這邊附上可調用的參數:
name or flag:參數名稱或旗標(可以是一個名稱,或一組可用的選項字串,例如 -d、–domain)。
action:當命令列遇到這個參數時要執行的基本動作類型(例如存值、計數、設為 True/False 等)。
nargs:這個參數要從命令列「吃掉」幾個值(例如 1 個、可選、或多個)。
const:某些 action 與 nargs 組合會需要的固定常數值。
default:如果命令列沒有提供這個參數,解析後使用的預設值。
type:把命令列字串轉換成的型別(例如 int、float、str)。
choices:允許的值範圍/集合(輸入必須是其中之一)。
required:是否必填(通常用在「可選參數」上,表示能不能省略)。
help:這個參數的簡短說明(會出現在 -h/–help 的幫助訊息)。
metavar:在用法訊息(usage)中顯示的「參數值名稱」占位符(例如顯示成 DOMAIN、IP)。
dest:parse_args() 回傳物件中,這個參數存放的屬性名稱(例如變成 args.domain 的 domain 就是 dest)。
1 | |