返回文章列表

Bash 工具實作高效網域名稱列舉技術與應用

本文介紹如何使用 Bash 指令碼結合 dig、whois、grep、awk 等指令,實作 DNS 網域名稱列舉,並利用 ProjectDiscovery Chaos API 擴充套件子網域名稱搜尋範圍。文章同時講解如何解析 IP 地址、識別網路應用、並利用 Nuclei 掃描 TLS 證書中的 SAN

資安 Web 開發

在網路安全測試中,DNS 網域名稱列舉是不可或缺的環節,能幫助我們深入瞭解目標網路架構,發現潛在的攻擊面。本文將會介紹如何利用 Bash 指令碼,結合 dig、whois 等指令,開發一個功能強大的網域名稱列舉工具。我們會探討如何解析 IP 地址、識別網路應用,並結合 ProjectDiscovery Chaos API 擴充套件子網域名稱搜尋範圍。此外,還會介紹如何使用 Nuclei 掃描 TLS 證書中的 SAN 資訊,從而發現更多隱藏的網域名稱和子網域名稱,更全面地掌握目標系統的資訊。最後,我們將會示範如何透過修改 hosts 檔案,覆寫 DNS 解析結果,直接存取目標應用程式,以提升滲透測試效率。這些技術的結合,能有效提升資訊收集的效率和準確性,為後續的安全測試奠定堅實基礎。

網域名稱列舉的 Bash 工具

在進行網路安全測試或資訊收集時,DNS(網域名稱系統)列舉是一項重要的技術。這項技術可以幫助我們發現目標網域的子網域名稱、根網域名稱以及相關的IP地址和組織資訊。以下是如何使用Bash來進行DNS列舉的詳細說明。

DNS 列舉的基本概念

DNS 列舉的目的是透過分析網域名稱來取得更多關於目標網路的資訊。這些資訊可能包括子網域名稱、IP地址以及持有該網路的組織資訊。這些資訊對於進一步的測試和分析非常有價值。

基本工具與指令

在Bash中,我們可以使用一些常見的指令來進行DNS查詢和資訊提取。以下是一些常用的指令:

  1. dig:DNS查詢工具,用於取得網域名稱的IP地址或CNAME記錄。
  2. whois:用於查詢網域名稱或IP地址的持有人資訊。
  3. grep:文字搜尋工具,用於從輸出中提取特定資訊。
  4. awk:文書處理工具,用於對文字進行複雜的操作和分析。

使用 Bash 進行 DNS 列舉

以下是一個完整的 Bash 指令碼範例,展示如何進行DNS列舉。這個指令碼包括三個主要功能:resolveorgdnsrecon

基本函式

首先,我們定義了一些基本函式來處理DNS查詢和資訊提取。

resolve() {
    while IFS= read -r line; do
        dig +short "$line" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | head -n 1
    done
}

內容解密:

這個 resolve 函式接受一個網域名稱作為輸入,並傳回對應的IP地址。它使用 dig 指令進行DNS查詢,並使用 grephead 指令來提取和篩選結果。IFS= 設定內部欄位分隔符為空白,以防止前導或尾隨空白被修剪。read -r 讀取標準輸入到變數 line 中。

org() {
    while IFS= read -r line; do
        whois "$line" | grep OrgName | tr -s ' ' | cut -d ' ' -f 2-
    done
}

內容解密:

這個 org 函式接受一個IP地址作為輸入,並傳回Whois資料中的 OrgName 值。這些資訊可以告訴我們誰擁有該網路區塊。它使用 whois 指令查詢IP地址,並使用 greptrcut 指令來提取和處理結果。

DNS 列舉指令碼

接下來是主函式 dnsrecon,它結合了前面的基本函式,進行網域名稱和子網域名稱的列舉。

dnsrecon() {
    if [[ $# -ne 1 ]]; then
        echo "You didn't provide a domain as input."
        echo "Usage: $0 [domain]"
        exit 1
    fi

    if [[ -z "$CHAOS_KEY" ]]; then
        echo "No chaos API key found. Set env CHAOS_KEY."
        exit 1
    fi

    local domain=$1
    local domains=''
    local roots=''

    # 網域名稱處理邏輯

}

內容解密:

這個 dnsrecon 函式接受一個網域名稱作為輸入,並進行子網域名稱和相關根網域名稱的列舉。它首先檢查是否提供了正確的命令列引數和API金鑰。然後,它定義了一些區域性變數來儲存處理過程中的中間結果。

# 網域名稱處理邏輯

# 使用ProjectDiscovery Chaos API進行子網域名稱列舉

# 提取根網域名稱並進行進一步的列舉

# 輸出結果

內容解密:

在這部分中,我們可以新增更多的邏輯來處理網域名稱和子網域名稱。例如,我們可以使用ProjectDiscovery Chaos API來進行子網域名稱列舉,並提取根網域名稱以進行進一步的列舉。最後,我們將結果輸出到螢幕上。

內容解密:

此圖示展示了整個DNS列舉流程。從開始到結束,每個步驟都有明確的邏輯關係。首先檢查API金鑰是否存在,然後進行子網域名稱解析、根網域名稱提取以及相關根網域名稱的列舉。最後輸出結果並結束流程。

在實際應用中,你可以根據需要進一步擴充套件和最佳化這些指令碼和函式。希望這篇文章能夠為你提供一些靈感和參考。

進行網域列舉與資訊收集

在這個部分,我們將討論如何使用 Bash 進行 DNS 列舉與資訊收集。這是進行安全測試的重要步驟,因為它能幫助我們發現隱藏的網域和子網域,從而更全面地評估目標系統的安全性。

變數宣告與作用域管理

首先,我們來看看如何宣告並管理變數。在 Bash 中,宣告變數為本地變數可以避免與全域變數或其他函式中的變數發生衝突。這在處理 .bashrc 檔案中的函式時特別重要,因為這些函式在 Bash 套件中都是可用的。

local mdi_result=$(mdi <<< "$domain")

在這裡,我們將 domain 變數傳遞給 mdi 函式來取得相關網域的清單。mdi 函式設計上接受來自標準輸入的輸入(例如 echo example.com | mdi),而不是作為函式引數傳遞(例如 mdi example.com)。因此,我們需要使用三個 < 字元來呼叫它。在 Bash 中,<<< 稱為 here-string 運算元,用於直接將字串作為輸入傳遞給命令,而不是從檔案或標準輸入讀取。

內容解密:

  • 變數宣告:宣告變數為本地變數可以限制其作用域,避免與全域變數或其他函式中的變數發生衝突。
  • here-string 運算元<<< 用於直接將字串作為輸入傳遞給命令,適合用於簡單的單行輸入。

使用 Chaos API 取得網域

接下來,我們檢查 mdi_result 是否為空。如果 mdi_result 為空,則將輸入網域直接傳遞給 Chaos API,並將結果指定給 domains 變數。

if [[ -z "$mdi_result" ]]; then
    domains=$(chaos -silent -d "$domain")
else
    echo "$mdi_result" | while IFS= read -r line; do
        root=$(rootdomain <<< "$line")
        chaos_domains=$(chaos -silent -d "$root")
        domains=$(echo -e "$domains\n$chaos_domains")
    done
fi

這段程式碼將 mdi_result 的內容逐行傳遞到 do/done 塊中。每一行的資料(一個網域)會被傳遞給 rootdomain 函式,該函式會傳回根網域(例如 www.example.com 會傳回 example.com)。然後將這個根網域傳遞給 Chaos API 呼叫並將結果指定給 chaos_domains 變數。最後,將 API 呼叫傳回的子網域清單附加到 domains 變數中。

domains=$(echo "$domains" | grep . | grep -v \* | sort -u)

這段程式碼確保刪除空白行(grep .傳回非空白行),移除任何萬用字元網域(grep -v \*),然後移除重複項(sort -u)。

內容解密:

  • Chaos API:用於從根網域取得相關子網域。
  • 管道操作:將 mdi_result 的內容逐行處理。
  • 字元篩選:使用 grep .grep -v \* 分別移除空白行和萬用字元。
  • 排序去重:使用 sort -u 去除重複項。

DNS 列舉與 IP 地址解析

接下來,我們使用 Bash 進行 DNS 列舉並解析 IP 地址。這些步驟有助於更全面地瞭解目標系統的網路結構。

echo "$domains" | while IFS= read -r line; do
    ip=$(resolve <<< "$line")
    if [[ -z "$ip" ]]; then
        continue
    fi
    orgname=$(org <<< "$ip")
    echo "$line;$ip;$orgname"
done

這段程式碼將每一行的資料在 domains 變數中傳遞到 do/done 塊中。其中的 IFS= 段落確保行結尾保持完整。每個網域都會傳遞給 resolve 函式,該函式傳回 IP 地址並儲存在 ip 變數中。如果 IP 地址不能解析(即為空),則繼續下一個迴圈。如果成功解析,則會列印預出「Domain;IP;Org」格式的資料。

內容解密:

  • DNS 列舉:使用 Bash 語法逐行處理每個網域。
  • IP 地址解析:利用管道操作和函式來取得每個網域的 IP 地址。
  • 條件判斷:如果 IP 地址不能解析則繼續下一個迴圈。
  • 輸出格式:以「Domain;IP;Org」格式列印結果。

網路應用識別

在進行安全測試時,常常會收到外部客戶提供的 IP 或網路地址清單。然而,僅僅測試這些定義的 IP 或網路地址而不進行足夠的 OSINT(開源情報收集)來發現所有可能的網域名稱是不夠完整的做法。

網路應用與主機標頭

當使用 IP 地址請求網站時,主機伺服器、負載平衡器或反向代理可能會傳回預設站點。因此如果不進行 DNS 列舉並測試相關網域名稱,可能會錯過其他可能存在漏洞的應用程式。

Figure 8.7 – dnsrecon 函式輸出示例

例如 OWASP Juice Shop 是一個故意存在漏洞的測試站點。如果你僅僅根據 IP 地址進行測試而不進行子網域列舉,你可能會錯過一些潛在的漏洞和應用程式。

網路應用識別例項

假設你收到一個 IP 地址範圍需要測試。如果你只掃描這些 IP 地址而不進行子網域列舉並測試相關網域名稱,你可能會錯過一些重要的漏洞和應用程式。

Figure 8.8 – Pinging OWASP Juice Shop demo

如上圖所示,當你根據 IP 地址存取一個站點時可能只看到「Not Found」,但當你根據正確的網域名稱存取時才能看到正確的站點內容。

執行 DNS 列舉

以下是如何使用 Bash 語法進行 DNS 列舉並找到所有相關子網域:

#!/bin/bash

# 清理先前結果檔案
> discovered_domains.txt

# 輸入範例: domain="example.com"
# 輸入範例: domain_list="domain1 domain2 domain3"
for domain in $domain_list; do
    local mdi_result=$(mdi <<< "$domain")

    if [[ -z "$mdi_result" ]]; then
        domains=$(chaos -silent -d "$domain")
    else
        echo "$mdi_result" | while IFS= read -r line; do
            root=$(rootdomain <<< "$line")
            chaos_domains=$(chaos -silent -d "$root")
            domains=$(echo -e "$domains\n$chaos_domains")
        done
    fi

    domains=$(echo "$domains" | grep . | grep -v \* | sort -u)

    echo "$domains" | while IFS= read -r line; do
        ip=$(resolve <<< "$line")
        if [[ -z "$ip" ]]; then
            continue
        fi

        orgname=$(org <<< "$ip")
        echo "$line;$ip;$orgname" >> discovered_domains.txt
    done

done

# 執行 dnsrecon 命令來進一步分析已發現的網域及其相關資訊:
dnsrecon example.com

此圖示展示瞭如何透過 DNS 列舉技術發現潛在目標及其相關資訊。這些步驟包括從根來源取得相關子網域、解析相關 IP 地址並記錄發現結果到檔案中以供進一步分析和測試。

內容解密:

  • DNS 列舉技術:透過利用工具和技術(如 Chaos API 和 dnsrecon)來發現潛在目標及其相關資訊。
  • IP地址解析 :確保所有已發現的子網域都能正確解析成可用 IP 地址。
  • 結果記錄 :將所有發現結果記錄到檔案以便後續分析和測試。

利用Nuclei發現與DNS快取技術溯源網頁應用程式

在進行網站測試或安全評估時,第一個步驟通常是資訊收集與溯源。這個過程中,我們需要了解目標網站的基礎架構,包括IP位址、子網域名稱及其防禦機制。以下是玄貓如何利用Nuclei來發現與DNS快取技術溝通網頁應用程式的詳細過程。

開始資訊收集

首先,我們需要了解目標網站的IP位址與DNS設定。許多IP位址解析為隨機子網域名稱,通常是代理伺服器放置在伺服器池前方。我們知道客戶使用內容傳遞網路(CDN)在其網站前端,並且流量會被Web應用程式防火牆(WAF)過濾,阻止掃描嘗試。

此外,如果我們透過網域名稱請求網站,網域名稱會解析為CDN上的IP位址,而這些CDN IP位址不在範圍內,因此無法攻擊它們。

攻破CDN防護

幸運的是,客戶並未過濾進入流量以僅允許CDN提供商的來源IP位址。這意味著我們可以直接探索每個IP位址上所託管的網站,並覆寫DNS以手動將網域名稱對應到IP位址。這樣可以讓我們直接存取網頁應用程式。

利用Nuclei發現TLS證書中的SAN

我使用了Nuclei漏洞掃描器來發現DNS名稱與TLS證書相關聯。TLS證書是數位證書,用於驗證網站身份並啟用加密連線。這些證書包含持有者的資訊、證書的公開金鑰以及發行證書授權單位(CA)的數位簽章。

TLS主體替代名稱(SAN)是X.509規範的擴充套件功能,允許使用者為單一SSL/TLS證書指定額外的主機名稱。這意味著單一證書可以保護多個網域名稱和子網域名稱,簡化證書管理並降低成本。

Nuclei具有掃描範本來提取TLS SAN。首先,我使用Nuclei掃描活躍IP位址清單。以下是使用Nuclei ssl-dns-names範本掃描Hyatt Hotels漏洞賞金計畫中的網路地址範例:

nuclei -t ssl-dns-names -l ip_addresses.txt -o nuclei_output.txt

此命令會將輸出結果儲存到nuclei_output.txt中。

內容解密:

這段程式碼使用Nuclei的ssl-dns-names範本來掃描給定的IP位址列表(ip_addresses.txt)。-t選項指定要使用的範本,-l選項指定輸入檔案列表,-o選項指定輸出檔案。

清理與重新格式化輸出

接下來,我們需要清理並重新格式化這些輸出結果以便插入到hosts檔案中。hosts檔案是一個簡單的文字檔案,用來將主機名稱對應到IP位址。它是任何作業系統(包括Linux)網路堆積疊的一部分。你可以透過cat /etc/hosts命令檢視hosts檔案的內容。

理解DNS與hosts檔案

在Linux系統上,當你使用網域名稱進行網路通訊時,電腦必須將網域名稱解析為IP位址。首先是檢查自己的主機名稱是否比對;接著檢查hosts檔案中的條目;最後再與網路介面組態中的DNS伺服器通訊。

簡單來說,在hosts檔案中硬編碼網域名稱到IP位址會覆寫DNS。Windows也使用hosts檔案作為同樣目的,儘管它在不同的位置。

重新格式化Nuclei掃描結果

以下程式碼會讀取一個檔案作為唯一命令列引數並輸出可以複製貼上到hosts檔案中的行:

#!/bin/bash

if [ "$#" -ne 1 ]; then
    echo "Converts Nuclei ssl-dns-names scan output to hosts file format"
    echo "Usage: $0 /path/to/file"
    exit 1
fi

cat "$1" | cut -d ' ' -f 4- | \
while read -r line; do
    ip=$(echo "$line" | awk '{print $1}')
    domains=$(echo "$line" | cut -d ' ' -f 2-)
    echo "$ip $domains" >> hosts_file.txt
done

內容解密:

此程式碼首先檢查是否有正確的命令列引數(即要處理的檔案路徑)。如果沒有提供正確的引數,則會顯示使用方法並離開。

然後,它讀取輸入檔案並使用cut命令提取第四欄開始的所有欄位(即TLS SAN和相關網域名稱)。接著使用while迴圈逐行處理輸出結果:

  • ip=$(echo "$line" | awk '{print $1}'):提取每行的第一個欄位(即IP位址)。
  • domains=$(echo "$line" | cut -d ' ' -f 2-):提取剩餘欄位(即TLS SAN和相關網域名稱)。
  • echo "$ip $domains" >> hosts_file.txt:將重新格式化後的結果寫入hosts_file.txt

應用於實務中的重寫hosts檔案

將上述生成的hosts_file.txt內容複製貼上到你的hosts檔案中:

sudo cp hosts_file.txt /etc/hosts

這樣就完成了將DNS解析覆寫為特定IP對應特定網域名稱的設定。

整合概念圖示

此圖示展示了DNS解析及如何透過修改hosts檔案覆寫原本DNS解析結果:

@startuml
skinparam backgroundColor #FEFEFE
skinparam sequenceArrowThickness 2

title Bash 工具實作高效網域名稱列舉技術與應用

actor "客戶端" as client
participant "API Gateway" as gateway
participant "認證服務" as auth
participant "業務服務" as service
database "資料庫" as db
queue "訊息佇列" as mq

client -> gateway : HTTP 請求
gateway -> auth : 驗證 Token
auth --> gateway : 認證結果

alt 認證成功
    gateway -> service : 轉發請求
    service -> db : 查詢/更新資料
    db --> service : 回傳結果
    service -> mq : 發送事件
    service --> gateway : 回應資料
    gateway --> client : HTTP 200 OK
else 認證失敗
    gateway --> client : HTTP 401 Unauthorized
end

@enduml

內容解密:

  • A:代表你所需存取之Domain Name。
  • B:代表作業系統中的Host File。
  • C:代表Host File中指定之Local IP Address。
  • D:代表系統預設DNS Server。
  • E:代表經由預設DNS Server解析得到之Remote IP Address。
  • 點選A時:
    • 如果Host File存在對應之條目則會回傳C(Local IP Address)。
    • 若Host File不存在條目則會向D(預設DNS Server)請求最終傳回E(Remote IP Address)。