Server-Side Request Forgery(SSRF,伺服器端請求偽造)發生在應用程式接受 URL、Host 或其他目的地資訊後,代表使用者向該位置發出請求,卻沒有充分確認最後連線的目的地是否符合業務預期。攻擊者因此可能借用伺服器可見的網路、服務帳號與信任關係,接觸外部使用者原本無法到達的內部服務、雲端 Metadata 或本機資源。

先講結論:不要讓使用者決定伺服器最後連到哪裡
MITRE CWE-918 將 SSRF 描述為:Web Server 接收上游提供的 URL 或類似請求並抓取內容,卻沒有充分確保請求送往預期目的地。風險不只是『後端幫忙開網址』,而是攻擊者能把應用程式變成位於信任網路內的 Request Proxy。
安全設計應先問:產品是否真的需要接受完整 URL?若目的地固定,Client 只應提交物件 ID、檔案 Key、合作服務代碼或其他非網路資料,由伺服器在設定中組出固定目的地。只有在 URL 預覽、Webhook、圖片匯入、文件轉換等確實需要任意外部網址時,才承擔更高複雜度的驗證與網路隔離。
真正有效的控制要覆蓋整個連線生命週期:使用單一標準 URL Parser、限制 Scheme 與 Port、處理 Userinfo 與正規化、解析全部 A/AAAA 位址、拒絕非公開與特殊用途位址、固定實際連線位址、每一跳 Redirect 重新驗證,並由 Egress Firewall/Proxy 限制應用程式可到達的網路。
- 能不接受完整 URL 就不接受,改用伺服器端固定目的地與結構化參數
- 已知合作服務使用嚴格 Allowlist;任意外部網址採公共目的地驗證與隔離 Fetcher
- 驗證 URL 的解析結果與 DNS 的全部 A/AAAA 位址,不以字串包含或 Regex 黑名單判斷
- 預設關閉自動 Redirect;若業務需要,對每一跳重跑完整驗證且限制跳數
- 限制 Protocol、Method、Header、Body、回應大小、Timeout 與可存取 Port
- 使用 Egress Firewall、Network Policy、出站代理與最小權限工作負載身分縮小失守影響
一次 SSRF 請求如何形成?
第一個請求由使用者送往應用程式,例如要求從 URL 匯入圖片、測試 Webhook、產生網頁預覽或把遠端文件轉成 PDF。第二個請求則由伺服器端 HTTP Client、Headless Browser、圖片處理器、PDF Renderer、XML Parser 或背景 Worker 發出。SSRF 發生在外部輸入能控制第二個請求的目的地或關鍵連線資訊。
第二個請求擁有與瀏覽器不同的視野。它可能能解析內部 DNS、連上 Loopback、Private Network、Link-local 位址、管理 API、Service Mesh、資料庫代理或雲端 Metadata;也可能自動帶上服務帳號、Client Certificate、Proxy Credential、預設 Header 或可信來源 IP。
判定是否成立不能只看畫面有沒有顯示回應。若伺服器真的向測試者控制的安全端點發出 DNS 或 HTTP Request,即使回應未回傳給前端,也可能是 Blind SSRF;後續能否接觸敏感目的地與造成何種影響,仍要在授權範圍內分層驗證。
| 必要條件 | 應確認的問題 | 證據示例 |
|---|---|---|
| 伺服器發出第二次請求 | 哪個元件實際解析並連線?同步還是背景執行? | 專用測試端點日誌、Request ID、背景 Job 與應用程式出站紀錄 |
| 外部輸入影響目的地 | 能控制 Scheme、Host、Port、Path、Redirect 或 DNS 名稱嗎? | 正常基線與單一變因修改後的 Request 差異 |
| 目的地驗證不足 | 是否解析最終目的地、全部 A/AAAA 與每次 Redirect? | 驗證日誌、DNS 結果、連線 IP 與拒絕原因 |
| 伺服器具額外網路能力 | 能否到達 Client 無法接觸的內部、Link-local 或管理服務? | 網路拓撲、Egress Policy 與隔離測試服務 |
| 存在可觀察影響 | 回應、時間、DNS/HTTP Callback、狀態變更或日誌是否證明請求發生? | 最小無害回呼、狀態前後差異與完整清理紀錄 |
哪些功能最容易出現 SSRF?
最直接的入口包括 URL 預覽、Open Graph 抓取、Avatar/圖片匯入、遠端檔案下載、Webhook/Callback 測試、RSS/Feed、網站截圖、PDF 產生、連結檢查、代理轉送與第三方整合。任何讓使用者提交 URL 且由伺服器取得內容的功能都應列入清單。
間接入口同樣重要。SVG、HTML、CSS、Office 文件、XML、影音 Playlist 或圖片格式可能引用外部資源,解析器在轉檔或預覽時會自動抓取;Headless Browser 可能載入主頁之外的 Script、Font、Iframe、圖片與 Redirect;Webhook Endpoint 也可能在事件發生數小時後才被背景 Worker 呼叫。
另外要找 Host、Base URL、Proxy、Import Source、Storage Endpoint、Registry、Git Remote、SSO Metadata URL、Package Repository、健康檢查與管理員可設定的整合欄位。『只有管理員能設定』會降低可利用者範圍,但管理帳號遭濫用、低權限能影響資料流或跨租戶共用 Worker 時,仍可能形成重要風險。
| 功能 | 伺服器端元件 | 容易遺漏的第二請求 |
|---|---|---|
| URL/社群預覽 | HTTP Client 或 Headless Browser | Redirect、頁內圖片、Script、Font、Iframe 與 Favicon |
| 圖片/文件匯入 | Downloader、Image Library、Converter | SVG/CSS 外部資源、縮圖、OCR 與轉檔流程 |
| Webhook/Callback | API Service 或背景 Worker | 測試按鈕、事件重送、Retry、DNS 變更與長效設定 |
| PDF/網站截圖 | Browser/Renderer | HTML、CSS url()、Iframe、列印樣式與 Browser Redirect |
| 整合與管理設定 | Connector、Agent、Service Account | Base URL、Proxy、Registry、Storage Endpoint 與健康檢查 |
SSRF、Open Redirect、XXE、LFI 與 CSRF 有什麼不同?
SSRF 的核心是伺服器替攻擊者連線到非預期目的地;Open Redirect 是應用程式讓 Client 被導向其他位置,本身不一定有 Server-side Fetch。若後端 Fetcher 自動跟隨 Open Redirect,它則可能成為 SSRF 驗證繞過的一環。
XXE 是 XML Parser 處理外部實體時產生的注入問題,可能讀取本機檔案或發出網路請求,因此能成為 SSRF 的入口;LFI/Path Traversal 著重本機檔案路徑,而 SSRF 可透過 file 等 Scheme 觸碰本機資源,但根因仍是後端處理可控制目的地。
CSRF 借用受害者瀏覽器自動攜帶的登入狀態,讓瀏覽器對受信任網站執行非本人意圖的操作;SSRF 借用的是伺服器的網路位置、服務身分與信任關係。兩者名稱相似,但檢測環境與防護控制完全不同。
| 議題 | 請求或解析發生位置 | 主要風險 | 核心防護 |
|---|---|---|---|
| SSRF | 伺服器、Worker、Renderer 或後端 Parser | 接觸非預期外部、內部、本機與 Metadata 目的地 | 目的地驗證、Redirect 重驗、Egress 隔離 |
| Open Redirect | Client 導覽或應用程式回應 Location | 釣魚、Token 洩漏或成為後端 Redirect 鏈 | 目的地 Allowlist、相對路徑與 Redirect Policy |
| XXE | 伺服器端 XML Parser | 外部實體讀檔、網路請求與資料外洩 | 停用 DTD/External Entity、使用安全 Parser |
| LFI/Path Traversal | 伺服器本機檔案解析 | 讀取或操作非預期檔案 | 固定根目錄、正規化、檔名 Allowlist 與權限 |
| CSRF | 受害者瀏覽器 | 借用使用者 Session 執行非本人意圖操作 | Anti-CSRF Token、SameSite、Origin 與使用者確認 |
回應型、Blind 與 Semi-blind SSRF 怎麼判斷?
回應型 SSRF 會把第二次請求的內容、狀態碼或錯誤資訊直接或間接帶回前端,較容易確認資料是否被讀取。Semi-blind 情境可能只呈現成功/失敗、回應時間、內容長度或不同錯誤;這些差異可反映目的地是否存在,但需要建立可靠控制組,避免把網路抖動誤判為弱點。
Blind SSRF 不把結果回傳給使用者,常出現在 Webhook、PDF、日誌處理、背景匯入與事件 Queue。安全測試應使用由測試團隊控制、可記錄 DNS 與 HTTP 的無害端點,加入唯一不可猜測的關聯值,並等待符合背景 Job 週期的合理時間。
收到外部 Callback 只證明伺服器可被引導連到測試端點,不自動等於能讀取 Metadata、掃描內網或執行程式。風險評估要分開描述已證明的連線能力、可控制的 Method/Header/Body、回應是否可見,以及網路與服務身分可能放大的影響。
URL 驗證為什麼比看字串困難?
URL 同時包含 Scheme、Userinfo、Host、Port、Path、Query 與 Fragment,不同 Parser、HTTP Client、Proxy 與 DNS Library 可能對編碼、反斜線、尾點、IDN、IPv6 括號、重複分隔符或 Userinfo 的理解不同。若驗證器與實際連線元件解析結果不一致,攻擊者可能讓檢查看到允許的 Host,連線卻前往另一個位置。
安全做法是以與實際 Client 相容的成熟 URL Library 解析一次,拒絕 Parser Error 與模糊格式,明確取得結構化 Scheme、Host、Port 與 Credential 欄位。通常應拒絕 URL Userinfo、未知 Scheme、非預期 Port、Fragment 與不必要的自訂 Header;比較 Host 前先做一致且可測試的 IDN/大小寫/尾點正規化。
不要用 `startsWith`、`contains`、後綴字串或單一 Regex 判斷信任網域。例如 Hostname 的邊界、子網域委派、註冊網域與國際化名稱需要明確規則;若只允許少數合作服務,直接比較解析後的精確 Host 與固定 Port 最可靠。
| 元件 | 安全決策 | 常見錯誤 |
|---|---|---|
| Scheme | 只允許業務必要的 http/https,預設拒絕其他協定 | 只封鎖 file,遺漏 Client 支援的其他 Scheme |
| Userinfo | 一般 Fetch 功能直接拒絕帳密型 URL | 把 @ 前的信任網域誤認為真正 Host |
| Host | 解析、正規化後做精確 Allowlist 或公共位址驗證 | 使用 contains/字串後綴,或驗證與連線用不同 Parser |
| Port | 只開業務必要 Port,未指定時依 Scheme 使用明確預設 | 允許任意 Port,讓伺服器探測內部管理服務 |
| Path/Query | 限制長度、編碼與可傳資料,不注入服務秘密 | 把 Server Credential、內部 Header 或使用者秘密轉送到外部 |
| Fragment | Server Fetch 不需要時拒絕或移除 | 驗證器與 Client 對 Fragment/編碼的處理不一致 |
DNS Rebinding/Pinning 與 TOCTOU 風險是什麼?
只驗證 Domain 字串仍不夠,因為 DNS 決定實際連線 IP。攻擊者控制的網域可能在不同查詢或 TTL 期間回傳不同答案:驗證階段解析到公開 IP,真正連線時改成 Loopback、Private、Link-local 或其他特殊用途位址。這是典型的檢查與使用時間差。
防護流程要取得全部 A 與 AAAA 結果,逐一分類並拒絕任何非允許位址;連線時使用已驗證且固定的 IP,而 HTTP Host/TLS SNI 保持為已核准網域,避免 HTTP Client 再次獨立解析。若架構無法 Pin IP,至少透過受控 DNS Resolver、Egress Proxy 與 Network Policy 保證連線目的地仍受限制。
Keep-alive、Connection Pool、DNS Cache 與 Proxy 也會影響行為。Policy 必須明確定義解析時間、Cache TTL、連線重用與失效條件,並監控 Allowlist 網域是否解析到未預期的內部或特殊位址。
Redirect 為什麼必須關閉或逐跳重新驗證?
初始 URL 可能是允許的公開目的地,回應卻以 30x 導向內部、Link-local、不同 Port、不同 Scheme 或另一個攻擊者控制網域。若 HTTP Client 在驗證後自動跟隨 Redirect,第一跳的檢查就失去意義。OWASP 因此建議停用 Web Client 的自動 Redirect。
若產品確實需要 Redirect,應由應用程式手動處理:限制最大跳數,解析相對位置,對新的完整 URL 重跑 Scheme、Host、Port、DNS 與 IP 分類,拒絕 Credential 與不允許的 Method 轉換,也不能把 Authorization、Cookie、Client Certificate 或內部 Header 帶到不同 Origin。
最後要記錄完整 Redirect Chain 與每一跳的解析 IP,並限制迴圈、總時間與總下載量。只驗證最終 URL 也不足,因為中間每一跳都可能已經對敏感目的地發出 Request。
SSRF 的安全連線流程應該長什麼樣子?
下圖呈現完整路徑:外部 URL 先由單一 Parser 拆解與正規化,再檢查允許的 Scheme/Port,解析全部 IPv4/IPv6,拒絕非公開與特殊用途位址,最後經受控 Egress Proxy 連到目的地。任何 Redirect 都不能直接前往下一站,而要回到相同驗證流程。
應用層控制負責理解業務允許的目的地;網路層控制則確保即使 Parser、Library 或程式分支失守,工作負載仍無法直接連到內部管理網段與 Metadata。兩層缺一不可。

Allowlist 與任意外部網址應採兩種不同設計
若系統只需呼叫已知 HR、Payment、Storage 或合作 API,採嚴格 Allowlist:Client 不直接提交完整 URL,而是選擇固定 Integration ID;伺服器端保存 Scheme、Host、Port、Base Path 與認證,並只讓特定工作負載透過網路政策連到這些目的地。
若業務需要抓取任意公開網址,例如 Link Preview 或圖片匯入,無法只靠固定網域。此時應把 Fetcher 隔離成無雲端權限、無內網路由、無共享 Cookie/Credential 的低權限服務,限制只用 HTTP/HTTPS,解析並拒絕所有非公開 IPv4/IPv6 結果,逐跳驗證 Redirect,並限制回應。
Denylist 是最後手段而不是完整安全模型。除了 RFC1918,還有 Loopback、Link-local、Shared Address、Benchmark、Multicast、Reserved、IPv4-mapped IPv6、IPv6 ULA 與平台特定 Metadata 位址;單純維護幾個字串很容易漏掉編碼與新範圍。應使用成熟 IP Library 依『是否全球可達』分類,再由網路層拒絕內部與特殊網段。
| 設計面向 | 已知可信服務 | 任意公開網址 |
|---|---|---|
| Client 輸入 | 提交 Integration ID 與結構化資料,不提交完整 URL | 可提交 URL,但欄位與長度受到嚴格限制 |
| 目的地 Policy | 精確 Scheme、Host、Port、Path Allowlist | 只允許 HTTP/HTTPS 且所有解析位址必須全球可達 |
| DNS/連線 | 監控 Allowlist DNS,Pin 已驗證位址或使用固定服務探索 | 檢查全部 A/AAAA、Pin IP、逐跳重驗 Redirect |
| 工作負載 | 只具呼叫指定合作服務所需權限 | 獨立低權限 Fetcher,無內網、Metadata 與服務秘密 |
| 網路控制 | Egress 只允許固定 IP/Proxy/Service Endpoint | 強制出站 Proxy,拒絕內部與特殊用途位址 |
Protocol、Method、Header 與 Body 也要限制
SSRF 不一定只使用 HTTP。實際可用 Scheme 取決於 Runtime、Library、Wrapper 與 Parser;若功能只需 Web 內容,就明確只允許 http 與 https,拒絕 file、gopher、ftp、smb、data、dict 與任何自訂 Handler,並停用不需要的 Proxy Environment 與 URL Wrapper。
大多數 Preview/Import 功能只需要 GET 或 HEAD。不要讓 Client 自行選擇 Method、任意 Header 或 Body,否則伺服器可能對內部 API 發出具狀態變更能力的 Request。固定安全 Header,移除 Authorization、Cookie、Proxy-Authorization、Host Override、Forwarded/X-Forwarded-* 與雲端 Metadata 特定 Header。
即使目的地是公開網站,也要防止資料外洩。不要把目前使用者的 Session、內部 API Key、Trace Baggage、Client Certificate 或完整原始 Header 轉送到外部;Request Body 只包含業務必要且經驗證的資料。
回應限制如何降低 DoS、資料外洩與 Parser 風險?
Fetcher 應設定連線、TLS、首 Byte、讀取與總時間 Timeout,限制 Redirect 次數、最大 Response Bytes、解壓縮後大小、Content-Type 與下載速率。不要只相信 Content-Length;Chunked、壓縮炸彈、無限串流與慢速回應都可能耗盡 Worker、Socket、Memory 或 Queue。
如果功能只需確認 Webhook 可達,不必把完整回應保存或回傳;若只需圖片,先限制 MIME 與大小,再由隔離的 Decoder 處理,不能因副檔名看似圖片就交給高權限 Parser。HTML Preview 應限制子資源或使用無內網能力的瀏覽器沙箱。
錯誤訊息不應回傳內部 IP、DNS 名稱、Service Banner、TLS Certificate 或完整連線例外。對外只提供穩定錯誤類別,詳細診斷寫入受保護日誌並與 Request ID 關聯。
雲端 Metadata 為什麼是高價值目標?
雲端 Metadata 位於工作負載本機可達的 Link-local 或專用名稱,提供執行個體資訊,也可能提供附加服務身分的短效存取憑證。若 SSRF 能取得這些 Credential,實際影響由該身分的 IAM 權限、Token 有效期、資源政策與網路條件決定,不能只看到 Metadata IP 就自動評為最高風險。
AWS IMDSv2 使用先以 PUT 取得 Session Token、再以 Token Header 讀取 Metadata 的方式,且可設定 Token Required 與 Response Hop Limit;Azure IMDS 要求 `Metadata: true` 且拒絕含 X-Forwarded-For 的 Request;Google Cloud Metadata 要求 `Metadata-Flavor: Google`。這些設計能阻止部分無法控制 Method/Header 的 SSRF。
但 Metadata Header/Token 只是縱深防禦。能控制 Method 與 Header 的 SSRF、同機不受信任程序、錯誤 Proxy 或其他平台服務仍可能形成風險。應要求 AWS IMDSv2、依環境限制 Metadata、讓 Fetcher 沒有 Metadata 路由,並對 VM/Pod 身分套用最小 IAM 權限與短效憑證。
| 平台 | 官方請求意圖機制 | SSRF 防護仍需補足 |
|---|---|---|
| AWS EC2 | IMDSv2 先以 PUT 取得 Session Token,後續 Request 帶 Token;可要求 V2 與設定 Hop Limit | 停用 IMDSv1、最小 IAM、限制 Fetcher 路由並依容器拓撲設定 Hop Limit |
| Azure VM | 要求 Metadata: true,且拒絕含 X-Forwarded-For 的 Request | 本機 Firewall/Network 控制、最小 Managed Identity 與禁止轉送任意 Header |
| Google Compute Engine | 要求 Metadata-Flavor: Google,並拒絕不符合要求的 Request | 隔離無需 Metadata 的程序、最小服務帳號權限與限制敏感自訂 Metadata |
Kubernetes、Service Mesh 與微服務環境要注意什麼?
在 Kubernetes 中,SSRF 可能接觸 Cluster DNS、Service IP、Pod IP、Kubelet、Metrics、管理介面或雲端 Metadata。NetworkPolicy 若未設定 Egress,Pod 通常可能廣泛出站;Service Account Token 自動掛載、Node 權限與 Workload Identity 設定也會決定影響。
將任意 URL Fetcher 放在獨立 Namespace/工作負載,停用不需要的 Service Account Token,自身不持有業務 Secret,只允許經受控 DNS 與 Egress Proxy 前往公開目的地。對 Metadata 使用平台支援的 Workload Identity、網路限制與最小權限,而不是讓所有 Pod 共用 Node 身分。
Service Mesh Sidecar 與 Egress Gateway 可以集中觀察與限制流量,但要確認直連 IP、Original Destination、DNS Capture、TLS Passthrough 與 Sidecar Bypass 都受控。應用層仍需辨識業務目的地,不能假設有 Mesh 就自動安全。
如何安全檢測 SSRF?
測試前先取得明確授權,列出允許測試的功能、環境、出站 Protocol、Callback Domain、停止條件與禁止目的地。優先在隔離測試環境建立模擬的公開服務、內部服務與 Metadata Stub,不直接探測真實內網、雲端 Metadata、第三方系統或未授權 Port。
先記錄正常基線:輸入欄位、解析後 URL、發出 Request 的元件、Method、Header、DNS、Redirect、Timeout、回應處理與背景排程。接著以測試團隊控制的安全 Domain 驗證 DNS/HTTP Callback,再使用本機建立的隔離 Private Target 確認 Network Policy 是否阻擋。一次只改一個變因,才能辨識實際控制。
針對 Parser、IPv4/IPv6、Redirect 與 DNS 行為做單元與整合測試,但不在生產環境大量嘗試編碼變體或 Port 掃描。若意外收到敏感資料或服務 Credential,立即停止、不繼續使用,依事件流程保全最小證據並撤銷受影響秘密。
- 盤點所有 URL、Host、Endpoint、Proxy 與遠端資源欄位,包括背景 Worker 與 Parser 子資源
- 使用專屬 Callback Domain 與不可猜測關聯值,分辨 DNS、HTTP 與不同測試案例
- 以隔離 Stub 驗證 Public、Private、Loopback、Link-local、IPv6 與 Metadata Policy
- 測試 Redirect 每一跳、DNS 變更、不同 Port 與 Header 是否重新驗證
- 確認同步回應、背景 Job、Queue Retry、Audit Log 與 Egress Log 都能關聯
- 測試後撤銷暫時 Credential、清理 Callback 紀錄並確認沒有殘留 Job 或檔案
一筆可信的 SSRF 發現需要哪些證據?
報告至少要說明入口、觸發角色、原始輸入、解析後 URL、實際 DNS 結果、實際連線 IP/Port、Method、Redirect Chain、執行元件與時間。對 Blind SSRF,要提供專用 Callback 端點收到的 DNS/HTTP 紀錄、唯一關聯值,以及能對上應用程式 Request/Job 的時間與 ID。
影響必須分層。能連到測試者公開端點、能連到隔離內網 Stub、能控制 Header/Method、能讀取 Response、能造成狀態變更是不同能力;沒有在授權範圍內驗證的 Metadata 或內部服務影響應清楚標示為推論,不能以假設當成既成事實。
證據要遮罩 Session、服務 Token、內部 DNS、客戶資料與雲端帳號資訊。若回應只呈現時間差,需有多次基線、正負控制與誤差範圍,排除 Timeout、Cache、Queue 與網路抖動。
| 證據 | 應記錄內容 | 判讀與保護要求 |
|---|---|---|
| 入口與身分 | 功能、路由、欄位、角色、租戶、同步/背景流程 | 使用專用帳號,不暴露真實 Session 或客戶資料 |
| 解析與連線 | 原始 URL、正規化結果、A/AAAA、實際 IP/Port、Method | 證明最後目的地,不只截取輸入欄位 |
| Redirect Chain | 每一跳 Location、DNS、IP、Origin 與 Header 處理 | 任何一跳都需在發送前重新驗證 |
| Callback/回應 | 唯一關聯值、DNS/HTTP 時間、Request Header 或回應片段 | 只使用授權的安全測試端點與最小資料 |
| 網路能力 | 公開、隔離 Private Stub、Metadata Stub 的允許/拒絕結果 | 不掃描真實內網或雲端 Metadata |
| 修復複驗 | 修復版本、拒絕原因、Egress Log、合法目的地回歸 | 確認拒絕發生在 DNS/連線或副作用之前 |
日誌、監控與告警要看哪些訊號?
安全日誌應記錄已驗證的主體、租戶、功能、原始 Host 的安全摘要、解析後 Scheme/Host/Port、DNS 結果分類、最終連線 IP、Redirect 次數、Policy 結果、下載量、時間與 Request/Job ID。完整 Query、Credential、Signed URL 與敏感 Response 不應直接寫入日誌。
高價值訊號包括:嘗試連到 Loopback、Private、Link-local、IPv6 ULA、Metadata、非預期 Port 或 Scheme;短時間大量 Host/Port 變動;DNS 在公開與非公開位址間改變;多次 Redirect;異常 Timeout、Response Size 或壓縮比例;Fetcher 對內網的任何成功連線。
Egress Proxy、DNS Log、Cloud Flow Log、Application Log 與 WAF/API Gateway 應能用 Request ID 串聯。告警後要保留 Policy 決策與 DNS 結果,但控制資料量與個資;不能因為有監控就允許寬鬆出站。
如何把 SSRF 防護做成可重用平台能力?
不要讓每個團隊各寫一套 `isSafeUrl`。建立中央 Safe Fetch Service/Library,輸入為業務目的地類型與受限參數,統一處理 Parser、Scheme、Port、DNS、IP 分類、Redirect、Header、Timeout、Response Limit、日誌與錯誤。高風險任意網址功能則走隔離 Fetcher。
在 CI 建立固定測試向量,覆蓋解析歧義、Userinfo、大小寫與尾點、IPv4/IPv6、IPv4-mapped IPv6、全部特殊用途範圍、多 A/AAAA、DNS 改變、相對與跨 Origin Redirect、不同 Port、巨大與慢速 Response。測試應檢查『沒有建立連線』,不只檢查 API 回傳 400。
SAST 可找出外部輸入流向 HTTP Client、Renderer、XML/Image Parser 的路徑;DAST 與互動測試能驗證實際 DNS、Redirect 與網路行為;IaC/Cloud Policy 檢查則確認 Egress、Metadata 與 IAM。三者結合才能覆蓋程式與環境。
| 測試層 | 主要目的 | 代表性案例 |
|---|---|---|
| URL Policy Unit Test | 驗證 Parser、正規化、Scheme、Port 與 Host 規則 | Userinfo、IDN、尾點、非預期 Scheme/Port 全部拒絕 |
| DNS/IP Unit Test | 驗證全部 IPv4/IPv6 與特殊用途分類 | 多 A/AAAA 任一非公開即拒絕,IPv4-mapped IPv6 正確分類 |
| HTTP Integration Test | 驗證 IP Pin、Redirect、Header 與 Response Limit | 每跳重驗、跨 Origin 不轉送 Credential、超限立即中止 |
| Network Policy Test | 證明工作負載無法接觸內網與 Metadata | 即使應用層測試控制失效,隔離 Target 仍連線失敗 |
| End-to-End Regression | 確認 Preview、Import、Webhook 與背景流程 | 合法公開目的地可用,所有 Queue/Retry 均套用相同 Policy |
發現 SSRF 後的修復與事件處理順序
先限制正在暴露的能力:停用脆弱 URL Fetch、關閉自動 Redirect、移除任意 Header/Method、透過 Egress Firewall 阻擋內部與 Metadata,並暫時將高風險功能移至無權限的隔離工作負載。不要只在 WAF 封鎖已知 Payload。
若 SSRF 可能接觸雲端 Credential、API Key 或內部 Session,應立即依身分與秘密類型撤銷/輪替,檢視 IAM 使用、Cloud Audit Log、內部服務存取與異常出站。範圍要包含背景 Worker、相同 Library、所有租戶與部署版本。
根因修復後補上中央 Safe Fetch Policy、網路隔離與回歸測試,盤點所有相同資料流。事件是否需通知客戶或主管機關,應由事件應變、法務與隱私團隊依已證明的資料存取、契約與法規共同判斷。
- 立即停用或限制高風險 Fetch,從網路層封鎖內部、特殊位址與 Metadata
- 保全 Application、DNS、Proxy、Flow、Cloud Audit 與背景 Job 日誌
- 撤銷可能暴露的短效與長效 Credential,檢查後續使用軌跡
- 以中央目的地 Policy、隔離 Fetcher、最小 IAM 與 Egress Control 修復根因
- 盤點所有 URL 消費者、Parser、Renderer、Worker、Redirect 與平行端點
- 完成合法功能、負向目的地、網路隔離與監控的全範圍複驗
修復後如何複驗,才不會留下旁路?
先重跑原始案例,確認非允許目的地在建立 DNS/TCP/TLS/HTTP 連線前被拒絕;再用等價輸入位置、背景 Worker、舊版 API、Renderer 子資源與 Webhook Retry 驗證相同 Policy。HTTP 400 不是唯一證據,隔離目的地與 Egress Log 都不應看到 Request。
接著測試 URL 正規化、全部 IPv4/IPv6 特殊範圍、多 A/AAAA、DNS 答案改變、相對與絕對 Redirect、跨 Origin Header、不同 Port、Timeout、壓縮與回應上限。對雲端環境確認 Metadata 機制與最小 IAM 已生效,但不直接讀取真實 Credential 作為驗證。
最後確認合法目的地、Redirect 與整合仍能正常運作,錯誤不暴露內部資訊,Policy 拒絕能被日誌與告警捕捉。報告應列出修復版本、網路政策、測試矩陣、已覆蓋資料流與仍需追蹤的第三方元件。
| 複驗面向 | 應通過的結果 | 常見殘留風險 |
|---|---|---|
| 原始入口 | 不對未授權目的地建立任何連線 | 只改畫面或回應碼,背景 Request 仍送出 |
| 解析與 DNS | 所有 A/AAAA 皆公開且連線固定到已驗證 IP | 驗證與 Client 不同 Parser,或連線時重新解析 |
| Redirect | 每一跳完整重驗並限制跳數與 Credential | 只驗第一跳或最終 URL,中間已接觸敏感目的地 |
| 平行資料流 | API、Worker、Renderer、Parser 與 Retry 共用 Policy | 同步路由已修,非同步或舊版入口遺漏 |
| 網路與雲端 | Fetcher 無內網/Metadata 路由且服務身分最小化 | 只依賴 Header/Token,工作負載仍可廣泛出站 |
| 合法功能 | 核准服務與公開資源在限制內正常完成 | 過度封鎖造成整合失敗,團隊另開不受控旁路 |
給產品、開發、雲端與資安團隊的檢查表
SSRF 防護不是在 Controller 加一條 URL Regex,而是對『應用程式代表誰、從哪個網路、帶著什麼身分、能連到哪裡』建立完整邊界。產品限制輸入能力、開發維護 Safe Fetch Policy、平台限制 Egress 與 Metadata、雲端治理最小化 IAM,資安才能用證據持續驗證。
- 能用 ID 或固定 Integration 代替完整 URL 時,不讓 Client 控制 Scheme、Host 與 Port
- 所有 Fetch、Parser、Renderer 與 Worker 使用同一套成熟 URL/DNS/IP Policy
- 只允許必要 Scheme、Method、Port、Header、Body、Redirect、大小與 Timeout
- 檢查全部 A/AAAA 與特殊用途位址,避免驗證後再次 DNS 解析
- 每一跳 Redirect 重驗,跨 Origin 不轉送 Cookie、Authorization 與內部 Header
- 任意網址 Fetcher 獨立部署、沒有內網/Metadata 路由、業務秘密與高權限 IAM
- Egress Proxy/Firewall、DNS、Application 與 Cloud Audit Log 可用 Request ID 關聯
- CI 同時驗證 Policy、實際連線阻擋、合法流程與所有非同步資料流
資料來源
- OWASP Cheat Sheet — Server-Side Request Forgery Prevention↗
- OWASP Web Security Testing Guide — Testing for Server-Side Request Forgery↗
- MITRE CWE-918 — Server-Side Request Forgery↗
- IANA — IPv4 Special-Purpose Address Space↗
- IANA — IPv6 Special-Purpose Address Space↗
- AWS EC2 — Use the Instance Metadata Service↗
- Microsoft Azure — Instance Metadata Service↗
- Google Cloud — View and query VM metadata↗


