稽核 TLS 憑證透明度記錄檔
使用時機
- 監控所擁有的網域,以偵測由未知憑證授權單位所進行的未授權或非預期憑證簽發
- 透過公開 CT 記錄檔中的憑證記錄,探索子網域及隱藏服務
- 偵測使用近似網域憑證(網域仿冒、同形異義字攻擊)的釣魚基礎設施
- 透過驗證所有已簽發憑證皆依照瀏覽器政策出現在 CT 記錄檔中,來稽核憑證授權單位的合規性
- 將持續性憑證監控建置到安全營運流程中,並在新簽發事件發生時發出警報
請勿 將其用於攻擊或中斷憑證授權單位、違反速率限制或服務條款來爬取 CT 記錄檔,或將其作為子網域列舉的唯一方法而未透過 DNS 驗證來佐證結果。
先決條件
- Python 3.10+ 並安裝
requests、cryptography及pyOpenSSL函式庫 - 可存取 crt.sh (HTTPS) 及公開 CT 記錄伺服器
- 要監控的網域清單(擁有的網域、品牌變體、仿冒網域候選)
- 用於新憑證發現警報的 SMTP 憑證或 Webhook URL
- 對 X.509 憑證結構及 TLS 憑證鏈驗證有基本了解
工作流程
步驟 1:網域盤點與基準
為受監控的網域建立初始憑證庫存:
- 定義監控範圍:列出所有擁有的根網域、已註冊的品牌名稱及已知子公司。包含萬用字元模式(
%.example.com)以涵蓋全面的子網域。 - 查詢 crt.sh 取得歷史憑證:使用 crt.sh JSON API 擷取每個網域的所有已知憑證。API 端點
https://crt.sh/?q=%.example.com&output=json會傳回符合萬用字元模式的憑證,其欄位包含issuer_ca_id、issuer_name、common_name、name_value、not_before、not_after及serial_number。 - 建立基準資料庫:將初始憑證集合儲存在本機 SQLite 資料庫中,資料表包含憑證 ID、網域、簽發者、有效日期、SAN(主體替代名稱)及首次出現時間戳記。此基準可避免對已已知的憑證發出警報。
- 識別授權的 CA:從基準中,擷取一組已合法為您的網域簽發憑證的憑證授權單位。任何未來來自非此集合中 CA 的簽發,都將觸發高優先級警報。
- 映射子網域:從所有憑證的
name_value欄位中擷取所有唯一的子網域,以建立初步的子網域庫存。
步驟 2:持續性 CT 記錄監控
設定持續監控以偵測新的憑證簽發:
- 定期輪詢 crt.sh:以固定間隔(每 15-60 分鐘)查詢 crt.sh API 以獲取新憑證。使用
exclude=expired參數聚焦於目前有效的憑證。將結果與基準資料庫比對,以識別新的條目。 - 解析憑證詳細資料:針對每個新憑證,擷取完整的 SAN 清單、簽發者鏈、有效期間、金鑰類型與大小、CT 記錄 SCT(已簽署憑證時間戳記)詳細資料,以及憑證指紋(SHA-256)。
- 偵測預憑證:CT 記錄包含預憑證(在最終簽發前提交的已毒化憑證)。追蹤這些預憑證作為早期預警,因為它們表示即將簽發憑證,但可能尚未啟用。
- 監控 CT 記錄的簽署樹根雜湊 (STH):對於進階監控,直接查詢 CT 記錄伺服器以取得最新的 STH,並驗證連續樹根雜湊之間的一致性證明。不一致表示記錄行為異常(拆分視圖攻擊)。
- 速率限制意識:透過間隔查詢和快取回應來尊重 crt.sh 的速率限制。在收到 HTTP 429 回應時實施指數退避。對於大量監控,請考慮直接查詢 crt.sh 的 PostgreSQL 介面:
crt.sh:5432。 - Atom/RSS 摘要替代方案:訂閱 crt.sh 的 Atom 摘要以進行較輕量的監控:
https://crt.sh/atom?q=%25.example.com提供新記錄條目的即時通知。
步驟 3:透過 CT 資料進行子網域探索
擷取並驗證在憑證透明度資料中發現的子網域:
- 萬用字元擴充:具有萬用字元 SAN(
*.dev.example.com)的憑證會揭示可能存在於 DNS 區域檔案中的子網域。將父網域記錄為進一步列舉的目標。 - 歷史憑證挖掘:不使用
exclude=expired參數查詢 crt.sh,以從可能仍在 DNS 中解析的過期憑證中尋找子網域。這些代表了可能容易受到子網域接管攻擊的歷史基礎設施。 - DNS 驗證:針對每個發現的子網域,執行 DNS 解析(A、AAAA、CNAME 記錄),以判斷該子網域目前是否活躍。與已知 IP 範圍交叉比對,以識別影子 IT 或未經授權的服務。
- 仿冒網域偵測:產生受監控網域的排列組合(位元入侵、同形異義字、插入、省略、調換、鍵盤鄰近替代),並查詢 CT 記錄以取得針對這些變體簽發的憑證。針對仿冒網域的憑證強烈表示存在釣魚基礎設施。
- 去重複與豐富化:標準化發現的子網域(小寫、移除尾端點)、去重複,並使用 WHOIS 資料、IP 地理位置及 HTTP 回應標頭來豐富化,以優先進行調查。
步驟 4:憑證簽發警報
為安全相關的憑證事件設定警報規則:
- 未授權 CA 警報:當憑證由非授權 CA 清單中的 CA 簽發時觸發。這是最高優先級的警報,因為它可能表示網域劫持、用於網域驗證的 BGP 劫持,或 CA 被入侵。
- 新子網域警報:當憑證包含先前未見過的子網域的 SAN 時觸發。這會捕捉到影子 IT 部署和未經授權的服務。
- 萬用字元憑證警報:針對任何新的萬用字元憑證簽發觸發警報,因為萬用字元憑證在被入侵時影響範圍更廣,且其簽發應受到嚴格控制。
- 短效期憑證異常:當憑證的有效期異常短(低於 24 小時),偏離組織正常的憑證生命週期時發出警報,因為這可能表示 Let's Encrypt 被濫用或自動化的釣魚基礎設施。
- 過期警告:當關鍵服務的憑證接近到期日(30、14、7 天)時,根據 CT 記錄資料中的
not_after欄位發出警報。 - 警報傳送:透過電子郵件 (SMTP)、Slack webhook、PagerDuty 傳送警報,或寫入與 SIEM 相容的 JSON 日誌格式,以便與現有的安全監控系統整合。
步驟 5:CT 記錄完整性驗證與報告
驗證記錄完整性並產出合規證據:
- 簽署樹根雜湊 (STH) 監控:透過
get-sthAPI 端點從每個受監控的 CT 記錄中取得最新的 STH。STH 包含樹大小和已簽署的時間戳記。使用記錄的公開金鑰驗證簽章。 - 一致性證明驗證:在連續兩次 STH 擷取之間,透過
get-sth-consistency請求一致性證明,以驗證記錄保持僅附加狀態,且沒有條目被修改或移除。 - 憑證庫存報告:產出所有為受監控網域簽發的憑證完整庫存,按簽發者分組,並包含有效狀態和金鑰強度指標。
- CA 多樣性分析:報告有多少不同的 CA 為組織簽發憑證,識別整合機會和單點故障。
- 合規證據:對於需遵守 PCI-DSS、SOC 2 或類似框架的組織,CT 監控記錄提供了憑證生命週期管理和未授權簽發偵測能力的證據。
關鍵概念
| 術語 | 定義 |
|---|---|
| 憑證透明度 (CT) | 一個開放框架 (RFC 6962),要求憑證授權單位將所有已簽發的憑證記錄在公開可稽核的僅附加記錄中,使網域擁有者能夠偵測未授權的簽發 |
| 已簽署憑證時間戳記 (SCT) | CT 記錄承諾在最大合併延遲(通常為 24 小時)內將憑證納入其 Merkle 樹;瀏覽器在信任憑證前,會要求來自多個記錄的 SCT |
| Merkle 樹 | CT 記錄使用的加密資料結構,其中葉節點是憑證雜湊值,父節點是其子節點的雜湊值,可實現有效的一致性證明和包含證明 |
| 預憑證 | 在最終簽發前提交給 CT 記錄的憑證,包含一個毒化擴充功能 (OID 1.3.6.1.4.1.11129.2.4.3),可防止其用於 TLS,但保留其在記錄中的位置 |
| crt.sh | 由 Sectigo 操作的免費網頁服務,將所有主要 CT 記錄的憑證彙總到一個可搜尋的 PostgreSQL 資料庫中,提供網頁和 API 存取 |
| 子網域接管 | 一種弱點,當子網域的 DNS 記錄指向已停用的服務(雲端供應商、CDN)且攻擊者可重新取得該服務時發生,可透過過期的 CT 憑證發現 |
| 最大合併延遲 (MMD) | CT 記錄在回傳 SCT 後,將已提交的憑證納入其 Merkle 樹的最大時間(通常為 24 小時) |
| CAA 記錄 | DNS 認證授權機構授權記錄,指定允許哪些 CA 為網域簽發憑證;CT 監控可偵測違反 CAA 政策的行為 |
工具與系統
- crt.sh:主要的 CT 記錄彙總器,提供 JSON API 存取(
https://crt.sh/?q=<查詢>&output=json),支援萬用字元查詢、身分過濾和憑證詳細資料擷取 - ct-woodpecker:來自 Let's Encrypt 的開源 CT 記錄監控工具,可與 Prometheus 和 Grafana 整合,用於記錄健康狀況和一致性的營運監控
- certspotter:SSLMate 的 CT 記錄監控工具,監控新簽發的憑證並發送通知;可作為託管服務或自行託管工具使用
- Google Argon / Xenon / Icarus:Google 營運的 CT 記錄,是使用最廣泛的記錄之一,可透過 RFC 6962 API 在其各自的記錄 URL 查詢
- OpenSSL:命令列工具,用於解析憑證詳細資料、驗證鏈,以及從透過 CT 監控擷取的憑證中擷取 SAN 清單
常見情境
情境:偵測金融服務公司的未授權憑證簽發
背景:一家銀行監控其主網域 (bank.example.com),並透過 CT 記錄發現一個從未使用過的 CA 簽發了一張憑證,涵蓋 secure-login.bank.example.com——一個不存在於其 DNS 中的子網域。
方法:
- CT 監控代理程式在 crt.sh 結果中偵測到來自「FreeSSL CA」、用於
secure-login.bank.example.com的新憑證,該 CA 不在授權 CA 清單(DigiCert、Sectigo)中 - 警報因「未授權 CA + 新子網域」而觸發,在 CT 記錄條目出現後 15 分鐘內上報給安全團隊
- 調查該憑證:擷取公開金鑰,檢查網域是否透過 HTTP-01 或 DNS-01 挑戰驗證,查詢 WHOIS 以找出簽發組織
- DNS 查詢
secure-login.bank.example.com發現它解析到一個銀行未使用的主機供應商 IP 位址——確認這是攻擊者的基礎設施 - 啟動事件回應:向 FreeSSL CA 請求撤銷憑證、提交網域濫用報告、將 IP 加入封鎖清單,並通知反釣魚團隊
- 實施 CAA DNS 記錄(
bank.example.com. CAA 0 issue "digicert.com"),以防止未授權 CA 在未來簽發憑證
陷阱:
- 未監控萬用字元模式(
%.bank.example.com),而遺漏了子網域的憑證 - 忽略在實際憑證之前出現在 CT 記錄中的預憑證,失去了早期預警優勢
- 事件發生後,未驗證 CAA 記錄是否在所有網域上正確配置
- 因為在授權變更後未更新基準資料庫,而對合法的憑證續約過度警報
情境:透過 CT 記錄子網域發現進行攻擊面映射
背景:一位滲透測試人員將 CT 記錄用作外部偵察的第一階段,以在被動掃描前映射目標組織的網際網路面對服務。
方法:
- 查詢 crt.sh 以取得
%.target.com及所有已知子公司的網域,收集橫跨 8 年的 2,400 張唯一憑證 - 從所有憑證(包括已過期的)的 SAN 欄位中,擷取 347 個唯一的子網域
- 對所有 347 個子網域進行 DNS 解析,發現其中 189 個目前活躍並具有 A/AAAA 記錄
- 識別出 12 個指向已停用雲端服務(CNAME 指向 S3 儲存貯體、Azure 端點)的子網域,這些是子網域接管的潛在目標
- 發現
staging-api.target.com和dev-portal.target.com,它們不在目標的記錄範圍內,但可連線且執行較舊版本的軟體 - 向目標組織展示調查結果,顯示其已知資產庫存與 CT 得出的攻擊面之間的差距
陷阱:
- 假設所有 CT 發現的子網域都在範圍內,而未與資產擁有者確認
- 未檢查萬用字元 DNS 回應,這些回應可能使子網域看似存在,但實際解析到一個捕獲所有流量的目標
- 僅依賴 CT 資料,而未與被動 DNS 資料庫交叉比對以獲得全面覆蓋
輸出格式
## CT 記錄監控報告
**網域**:example.com
**監控期間**:2026-03-01 至 2026-03-19
**追蹤的憑證總數**:142
**偵測到的新憑證**:7
**產生的警報數**:2
### 警報:未授權 CA 簽發
- **嚴重性**:嚴重
- **憑證 CN**:secure-login.example.com
- **SAN**:secure-login.example.com、
…```
(…為簡潔起見截斷)