:原理對比、通解套路與防御修復(fù)清單)
把CSRF和SSRF放在同一個靶場里連著刷完我最大的感受是這兩個漏洞名字看著像親戚原理卻剛好站在“請求信任”的兩端。這個好靶場的CSRF與SSRF模塊題目數(shù)量不算多但每一關(guān)都還原了真實業(yè)務(wù)里最容易忽略的接口很適合已經(jīng)從“聽過漏洞名”走到“能看懂?dāng)?shù)據(jù)包”這一步的人。這篇文章我會先說明為什么這兩個漏洞值得對著練再分別拆開CSRF和SSRF的本質(zhì)、題型和通用解法最后補一節(jié)“兩者怎么串起來利用”和一份能直接拿去自查的修復(fù)清單?;A(chǔ)要求不高只要你會看HTTP請求、知道Cookie是怎么帶上的就能跟上等刷到JSON型CSRF和內(nèi)網(wǎng)繞過那幾關(guān)你會發(fā)現(xiàn)前面的判斷流程全都還能復(fù)用。1. 為什么CSRF和SSRF適合放在一起練1.1 兩個漏洞的“信任方向”正好相反CSRF跨站請求偽造的核心是瀏覽器會把你的身份憑證Cookie自動貼到每一次請求上不管這次請求是你主動發(fā)起的還是某個惡意頁面悄悄發(fā)起的。服務(wù)器看到“帶著有效Cookie的修改請求”就默認(rèn)是本人操作。這里的信任對象是“會話身份”。SSRF服務(wù)端請求偽造的核心是服務(wù)器因為業(yè)務(wù)需要去訪問用戶提供的某個地址相當(dāng)于把客戶端的手搭在服務(wù)端的手上讓服務(wù)器替你向外發(fā)請求。大多數(shù)應(yīng)用對“從服務(wù)器出發(fā)的請求”天然放松警惕因為默認(rèn)來源可信。這里的信任對象是“請求的發(fā)起方”。打個比方CSRF像有人趁你走神拿你的門禁卡去刷了公司大門SSRF則像你通過前臺轉(zhuǎn)接電話讓前臺幫你撥一個內(nèi)部分機號。前者騙的是“你帶著卡”后者騙的是“你是內(nèi)部電話”。把這兩個場景放進(jìn)同一張對比表區(qū)別就很直觀了對比項CSRFSSRF請求發(fā)起方受害者的瀏覽器存在漏洞的服務(wù)器攻擊者控制位置跨站頁面里拼出來的請求服務(wù)端某個“URL參數(shù)”核心信任點“帶Cookie本人本意”“服務(wù)器發(fā)出的請求內(nèi)部可信”能影響的范圍受害者已登錄的業(yè)務(wù)操作內(nèi)網(wǎng)服務(wù)、本機接口、文件系統(tǒng)典型關(guān)鍵詞改資料、改密、轉(zhuǎn)賬、綁定圖片下載、URL預(yù)覽、導(dǎo)入、回調(diào)1.2 靶場題目的兩條線索好的靶場不會把漏洞出成腦筋急轉(zhuǎn)彎它會按真實業(yè)務(wù)埋點。CSRF的關(guān)卡基本都長在“改資料、改密碼、綁定手機號、支付接口”這些狀態(tài)變更操作上防護(hù)要么完全沒有要么故意留了一個看似嚴(yán)密但能被繞過的Token機制SSRF的關(guān)卡則圍繞“遠(yuǎn)程圖片加載、URL轉(zhuǎn)PDF、RSS導(dǎo)入、Webhook回調(diào)”這類需要服務(wù)器主動訪問外網(wǎng)的接口讓你從“參數(shù)到底是不是一個URL”這類蛛絲馬跡里定位觸發(fā)點。我刷題時腦子里一直掛著兩句話CSRF問的是“這個請求是不是本人本意”SSRF問的是“這個地址是不是允許訪問”。帶著這兩個問題去讀代碼和數(shù)據(jù)包比死記題型管用得多。靶場把這兩個漏洞放在一起本身就是想讓你對比這種“信任錯位”——一個信錯了身份一個信錯了來源。1.3 練習(xí)環(huán)境怎么搭最順手開始刷題之前把環(huán)境準(zhǔn)備好能省下一半的排查時間。我的習(xí)慣是這么幾件事一臺本地虛擬機跑靶場最常見的組合是PHPMySQL那套經(jīng)典架構(gòu)。裝好以后做一次干凈的系統(tǒng)快照往后每個關(guān)卡反復(fù)復(fù)位、反復(fù)重刷很省心。一個抓包改包工具沒有的話用瀏覽器開發(fā)者工具也行。網(wǎng)絡(luò)面板看請求、復(fù)制為curl、改Cookie重放這幾件事在驗證CSRF時幾乎天天用。兩個隔離的瀏覽器環(huán)境一個當(dāng)受害者始終保持“已登錄”狀態(tài)另一個當(dāng)攻擊者專門打開你構(gòu)造的惡意頁面。兩個環(huán)境必須隔離Cookie最簡單的方式是不同瀏覽器或者不同用戶配置文件。再準(zhǔn)備一個HTTP監(jiān)聽服務(wù)用來做SSRF的帶外觀測。最簡單的寫法是起一個Python腳本把請求路徑追加到日志文件import http.server class H(http.server.BaseHTTPRequestHandler): def do_GET(self): open(ssrf.log, a).write(self.path \n) self.send_response(200) self.end_headers() http.server.HTTPServer((0.0.0.0, 8000), H).serve_forever()把所有攻擊驗證都限制在這臺本地靶場虛擬機里不要拿這套思路去沒有授權(quán)的系統(tǒng)上試這是底線。2. CSRF的本質(zhì)別把“帶著憑證”當(dāng)成“本人確認(rèn)”2.1 一句話解釋CSRF跨站請求偽造的意思是攻擊者利用你在正常站點上的登錄狀態(tài)讓瀏覽器替你發(fā)出某些指令?!皞卧臁边@個詞有點誤導(dǎo)人——攻擊者并沒有偽造你的身份憑證你的Cookie真實有效他只是偽造了一個“請求場景”你明明只是在看一個網(wǎng)頁就已經(jīng)順手提交了轉(zhuǎn)賬、改密或發(fā)布操作。理解這個點很重要因為它決定了CSRF和XSS的邊界。XSS是在目標(biāo)站頁面里執(zhí)行腳本等于搶到了鑰匙CSRF是在你自己的頁面里遙控瀏覽器屬于“借”鑰匙不是“搶”鑰匙。靶場里很多題區(qū)分兩者看的是腳本能否在目標(biāo)域下執(zhí)行還是單純只需要瀏覽器發(fā)起一個跨站請求。2.2 三個先決條件少一個都不成立第一目標(biāo)操作必須是會改變狀態(tài)的請求。查詢數(shù)據(jù)、讀取頁面的GET請求即使被跨站觸發(fā)通常也只是信息泄露談不上“偽造”真正危險的是改密碼、改綁定、發(fā)帖、轉(zhuǎn)賬這類有副作用的請求。第二這個請求的憑證由瀏覽器自動攜帶。Cookie是最常見的也包括某些自動附加的Authorization頭。正因為瀏覽器自動帶上憑證攻擊者才能隔空借你的身份。如果憑證是攻擊者拿不到的、并且請求必須手動附加的CSRF自然就不成立。第三服務(wù)端沒有校驗“請求意圖”。缺少Token、對Origin不檢查、Cookie沒配SameSite都是典型的缺口。靶場題目千變?nèi)f化本質(zhì)上都是在找這個“三缺一”的缺口位置。2.3 四種最常見的出題款式GET型狀態(tài)修改參數(shù)直接放在URL里常見于改昵稱、退訂、標(biāo)記已讀這種開發(fā)圖省事的接口。跨站觸發(fā)最簡單一個img、一個誘導(dǎo)點擊的鏈接就夠。有些靶場把它包裝成“下載報告”或“切換語言”但只要判斷依據(jù)是“GET且修改了數(shù)據(jù)”就直接進(jìn)入CSRF考慮范圍。POST型正常表單請求Content-Type是application/x-www-form-urlencoded。跨站頁面可以用一個自動提交的form完整模擬出同樣的請求行為上沒有任何差別。這是最經(jīng)典的題型也是我建議所有刷題者必須先打通的關(guān)卡。JSON型接口接收application/json前端用AJAX提交??缯酒胀ū韱文M不了JSON的Content-Type但有個老技巧能用enctypetext/plain的表單拼出合法JSON。靶場出到這一關(guān)基本就是讓你理解“表單編碼和JSON解析之間的縫隙”form actionhttps://target.lab/api/change_profile methodPOST enctypetext/plain textarea name{email:attackertest.lab,csrf:}/textarea /form scriptdocument.forms[0].submit();/script這段代碼的重點在textarea的name值name是左半個JSONtextarea內(nèi)容是右半個JSON表單編碼時中間恰好補了一個“”于是提交出去的body就是{email:attackertest.lab,csrf:}一個合法的JSON對象。服務(wù)端只要沒在拿到JSON后重新校驗token來源就會把它當(dāng)成正常請求處理。Token形同虛設(shè)型接口里確實有CSRF Token但它是寫死的、復(fù)用的、放在URL里的、校驗時允許為空或者Token不跟會話綁定。靶場里最典型的一種是“攻擊者自己注冊一個賬號拿到合法Token同樣能在受害者請求里通過校驗”因為Token沒有綁定到具體會話。遇到這類題先驗證Token是不是每個會話唯一再驗證它是不是真的被服務(wù)端校驗了。2.4 SameSite出現(xiàn)后這些題要重新看一遍現(xiàn)代瀏覽器的SameSite屬性已經(jīng)把一部分CSRF天然擋掉了。SameSiteLax時img、fetch這類子資源跨站請求不會帶Cookie但用戶通過點擊鏈接觸發(fā)的頂層GET導(dǎo)航仍會帶CookieSameSiteStrict時更苛刻跨站場景基本不帶。這個屬性對靶場的影響是明顯的以前靠img秒殺的GET型CSRF在Lax下可能翻車但POST型CSRF本來就不是頂層導(dǎo)航Lax下基本帶不了Cookie所以防護(hù)效果更明顯。刷題時要在抓包里確認(rèn)Cookie的SameSite值別憑經(jīng)驗?zāi)X補。還有一類服務(wù)端會用Referer或Origin做校驗常見坑是只查“字符串里是否包含目標(biāo)域名”。攻擊者可以用http://evil.com/?target.lab這種URL讓Referer里包含目標(biāo)域名或者通過meta namereferrer contentno-referrer讓Referer整個為空而部分實現(xiàn)又會對空Referer放行。靶場關(guān)卡往往故意留這種縫正好說明“單點防護(hù)為什么不可靠”。3. CSRF關(guān)卡的通解套路從看請求到驗證觸發(fā)3.1 先把操作翻譯成請求拿到題先別急著找漏洞用抓包工具把目標(biāo)操作完整錄一遍。記錄四件事請求方法、請求路徑、提交的參數(shù)、請求攜帶憑證的方式。如果你發(fā)現(xiàn)某個“敏感操作”用的是GET直接把這條記進(jìn)可疑名單。參數(shù)里有沒有Token、Cookie里的會話結(jié)構(gòu)是什么這些信息后面會反復(fù)用到。這一步最容易忽略的是“并發(fā)請求”。有些靶場會把Token的校驗設(shè)計成“一次性使用”但業(yè)務(wù)接口會同時發(fā)出兩個請求比如先保存草稿再提交此時只要提前把一個請求里的Token重放到另一個請求里就有可能在邊角料里找到繞過窗口。先記錄完整的請求順序再談構(gòu)造。3.2 按防護(hù)逐項打勾接下來依次確認(rèn)幾件事請求里有沒有一個像隨機字符串的Token字段它的值是不是和當(dāng)前會話對應(yīng)服務(wù)端有沒有校驗Origin或Referer校驗規(guī)則是嚴(yán)格比對域名還是只查字符串包含Cookie的SameSite屬性是什么接口是否要求自定義請求頭。把這四項的狀態(tài)寫在紙上漏洞成不成立基本就清楚了。服務(wù)端防護(hù)做得越“雜”越容易在某個實現(xiàn)細(xì)節(jié)上出錯——比如Origin校驗只查了http://開頭或者只查了端口之前的部分這些都會在后續(xù)驗證時成為突破口。3.3 根據(jù)請求類型選擇PoC模板判斷完防護(hù)之后按照請求長相套模板請求長得像PoC方案GET且能改狀態(tài)img觸發(fā)或誘導(dǎo)點擊POST表單自動提交的form接收J(rèn)SONtext/plain拼JSON需要完整交互流程把多個步驟做成連續(xù)頁面腳本依次提交GET型最樸素的寫法img srchttp://target.lab/user/delete?id1024 width0 height0POST型最常用的寫法form actionhttp://target.lab/user/change_email methodPOST input typehidden nameemail valuestealtest.lab /form scriptdocument.forms[0].submit()/script隱藏域和自動提交腳本是為了減少用戶操作。有的靶場故意要求模擬“用戶點擊”因為真實場景中誘導(dǎo)點擊更隱蔽觸發(fā)方式要從“用戶會點什么”來選。比如把PoC放在一個下載按鈕上、一段迷惑性文案后面比頁面加載就彈alert更像真實攻擊鏈。3.4 雙瀏覽器驗證是最后一步準(zhǔn)備兩個隔離的瀏覽器環(huán)境。環(huán)境A登錄目標(biāo)站模擬受害者把會話保持在有效狀態(tài)環(huán)境B不登錄目標(biāo)站只負(fù)責(zé)打開攻擊頁面。受害者環(huán)境打開攻擊頁之后立刻切回環(huán)境A檢查目標(biāo)操作是否已經(jīng)發(fā)生。之所以要隔離是因為同一個瀏覽器里同時存在受害者Cookie和攻擊頁面會出現(xiàn)“SameSite判定正確但Origin是同一站點”的干擾導(dǎo)致判斷錯誤。隔離之后受害者身份、攻擊者頁面、目標(biāo)站點三個角色清清楚楚驗證結(jié)果不會糊。3.5 這類題最容易踩的三個坑一是把CSRF和XSS混為一談。XSS是在目標(biāo)頁面里執(zhí)行腳本CSRF是跨站偽造請求。如果接口同時存在XSS和CSRF往往是XSS能直接模擬請求CSRF反而成了錦上添花修復(fù)時要分開看待。二是驗證時只在攻擊者的未登錄環(huán)境里看結(jié)果。CSRF的前提是受害者已登錄所有測試都要以受害者視角為準(zhǔn)。你很可能在“未登錄環(huán)境測試失敗”之后誤判漏洞不存在而切換受害者視角立刻復(fù)現(xiàn)。三是盯著表單忘記了Cookie。有些操作需要請求里帶上某個獨立的Cookie才生效僅跨站提交表單是不夠的。如果這個Cookie是第三方可設(shè)置的那就是另一個獨立漏洞點不要混進(jìn)CSRF結(jié)論里。4. SSRF的本質(zhì)服務(wù)端的手被借到內(nèi)網(wǎng)去敲門4.1 SSRF到底在放什么進(jìn)來SSRF的經(jīng)典定義是服務(wù)端根據(jù)用戶可控的URL發(fā)起請求。這里的關(guān)鍵詞不是“URL”而是“服務(wù)端發(fā)起”。攻擊者平時只能從外網(wǎng)訪問你的服務(wù)器但服務(wù)器自己是可以訪問內(nèi)網(wǎng)、訪問自己回環(huán)接口的。一旦某個業(yè)務(wù)接口允許用戶指定一個地址并讓服務(wù)器去訪問攻擊者就等于搭上了服務(wù)器的內(nèi)網(wǎng)通道??蛻舳撕头?wù)器之間通常隔著一層安全邊界但服務(wù)器到內(nèi)網(wǎng)往往沒有同等的訪問控制。很多內(nèi)網(wǎng)接口、管理后臺直接綁在非公網(wǎng)地址上外網(wǎng)掃不到卻擋不住來自服務(wù)器自身的連接。這就是SSRF能造成破壞的根本原因。4.2 哪些接口是重災(zāi)區(qū)業(yè)務(wù)場景用戶可控的部分常見參數(shù)名圖片縮放/下載圖片URLurl、img、pic網(wǎng)頁快照/轉(zhuǎn)PDF待轉(zhuǎn)URLlink、target_urlRSS/Feed導(dǎo)入訂閱地址rss、feedWebhook回調(diào)通知回調(diào)地址callback、webhook資產(chǎn)探測/URL健康檢查檢查目標(biāo)host、url遠(yuǎn)程文件導(dǎo)入下載地址file、source識別方法不是看參數(shù)名而是看行為。一個“傳URL自動下載”的頭像功能就是SSRF觸發(fā)點只能傳文件本體的上傳接口則不是。先問自己這個操作會不會讓服務(wù)器額外發(fā)起一次網(wǎng)絡(luò)請求會就進(jìn)入SSRF排查流程。4.3 能打到哪從內(nèi)網(wǎng)探測到元數(shù)據(jù)最基礎(chǔ)的利用是內(nèi)網(wǎng)探測。把URL改成http://內(nèi)網(wǎng)IP/通過返回內(nèi)容、超時、錯誤頁差異判斷端口和服務(wù)再進(jìn)一步是訪問本機和管理接口很多開發(fā)環(huán)境把調(diào)試面板、性能面板、管理后臺綁在127.0.0.1外網(wǎng)打不到但SSRF可以。云上的應(yīng)用還有一個經(jīng)典目標(biāo)——云元數(shù)據(jù)服務(wù)。它通常監(jiān)聽在169.254.169.254這類鏈路本地地址里面放著實例ID、網(wǎng)絡(luò)配置甚至角色憑證等敏感信息。如果應(yīng)用部署在容器或虛擬機里SSRF打通這個地址往往比打內(nèi)網(wǎng)一臺普通機器值錢得多。如果協(xié)議沒限制file://能讀本地文件dict://、gopher://則可以跟內(nèi)網(wǎng)里基于TCP的服務(wù)交互。后面這兩種屬于進(jìn)階玩法靶場里一般出現(xiàn)在最后幾關(guān)原理大于實操。但至少要知道SSRF能影響的絕不是“多訪問一個網(wǎng)頁”那么簡單。5. SSRF的通解步驟與繞過組合拳5.1 第一步確認(rèn)它真的在“替你請求”先把可疑參數(shù)改成指向自己可控地址的URL??煽氐刂吩趺磥肀镜匕袌隼镒钊菀椎氖桥淝懊鎸懙哪莻€HTTP監(jiān)聽器監(jiān)聽一臺你自己能訪問到的機器或虛擬機的8000端口。把參數(shù)改成http://監(jiān)聽機IP:8000/ssrf_test請求一進(jìn)來日志里就有記錄。沒有回顯的接口也能靠這個確認(rèn)觸發(fā)點。這一步要留意“是否帶外驗證失敗就排除了SSRF”。有些應(yīng)用會對URL做一次DNS預(yù)解析或連接復(fù)用第一次請求沒打到監(jiān)聽器可能只是緩存或重試邏輯問題多觸發(fā)幾次、換個URL參數(shù)位置再下結(jié)論。5.2 第二步摸清協(xié)議與過濾規(guī)則先測協(xié)議。http://能通不代表file://能通分別試一下file:///etc/passwd、dict://127.0.0.1:6379/info觀察報錯和響應(yīng)差異就能摸出服務(wù)端到底放行了哪些協(xié)議。再測過濾。把127.0.0.1的各種寫法逐個丟進(jìn)去看哪個被攔、哪個放行。重點觀察過濾代碼是針對“原始字符串”做黑名單還是針對“解析后的主機名/IP”做校驗還是兩層都做。這個判斷決定了后面用哪套繞過組合。5.3 繞過字典一次看明白“為什么攔不住”繞過思路示例說明點分十進(jìn)制http://2130706433/127.0.0.1的十進(jìn)制整數(shù)寫法十六進(jìn)制http://0x7f000001/127.0.0.1的十六進(jìn)制寫法八進(jìn)制http://0177.0.0.1/127.0.0.1的八進(jìn)制寫法IPv6http://[::1]/回環(huán)地址的IPv6表示IPv4映射IPv6http://[::ffff:127.0.0.1]/兼容IPv4的IPv6地址符號混淆http://test.lab127.0.0.1/實際請求目標(biāo)是127.0.0.1#或?干擾http://127.0.0.1#test.lab后面內(nèi)容只是fragment或query自定義域名解析到內(nèi)網(wǎng)自己控制一個域名指向127.0.0.1域名白名單被繞過跳轉(zhuǎn)短鏈或自建跳轉(zhuǎn)頁302到內(nèi)網(wǎng)請求庫跟隨重定向時不重新校驗DNS重綁定第一次解析外網(wǎng)IP通過校驗第二次解析內(nèi)網(wǎng)IP校驗和實際連接不是同一次解析URL編碼對部分字符做URL編碼檢測和解碼順序不一致會被繞過http://evil.com127.0.0.1/這個寫法值得單獨說說URL里真正的主機是127.0.0.1evil.com只是userinfo部分。黑名單如果只檢查“URL里不能出現(xiàn)內(nèi)網(wǎng)IP”卻不解析URL結(jié)構(gòu)就會錯誤放行。#的干擾同理http://127.0.0.1#evil.com的目標(biāo)地址是127.0.0.1evil.com只是fragment字符串檢查卻可能認(rèn)為域名是evil.com。還有一個“雙URL寫法”http://127.0.0.1/http://evil.com在部分實現(xiàn)里解析器和實際請求庫取的是不同一段導(dǎo)致校驗?zāi)繕?biāo)與實際請求目標(biāo)不一致。這種解析差異在靶場里屬于必試項因為每換一種后端語言結(jié)果可能都不一樣。5.4 依賴解析結(jié)果的繞過重定向與DNS重綁定很多防護(hù)只校驗傳入的域名認(rèn)為域名安全就直接發(fā)請求。這時有兩個繞法。一是短鏈或自建跳轉(zhuǎn)頁做302到內(nèi)網(wǎng)地址。如果請求庫跟隨重定向且不重新校驗馬上繞過。二是DNS重綁定讓同一個域名第一次解析給一個外網(wǎng)IP通過校驗發(fā)起實際連接前再解析成內(nèi)網(wǎng)IP。兩者本質(zhì)都一樣“校驗時看到的”和“連接時訪問的”不是同一個目標(biāo)。在靶場里模擬DNS重綁定最簡單的方式是改本地hosts或者用自有域名改DNS記錄把校驗和訪問拆開觸發(fā)。理解這個原理比親手復(fù)現(xiàn)更關(guān)鍵——很多生產(chǎn)環(huán)境的SSRF防護(hù)死就死在“校驗一次就以為天下太平”上。5.5 沒有回顯時怎么判斷連通性看時間請求到開放端口可能立即返回或響應(yīng)偏慢到關(guān)閉端口會快速失敗或超時多組對比能推測端口狀態(tài)。看錯誤很多應(yīng)用會把上游錯誤原樣帶出來“Connection refused”和“Connection timeout”的區(qū)別就是信息??磶庾屇繕?biāo)反過來請求你的監(jiān)聽器或者觸發(fā)一次對自有域名的DNS解析用日志確認(rèn)連通。通解建議是永遠(yuǎn)不要只依賴一種回顯方式。靶場里有些SSRF關(guān)卡設(shè)計成“無回顯”其實就是逼你學(xué)會用時間和帶外交互去推理。這個能力比單純會背繞過寫法值錢。6. CSRF與SSRF的聯(lián)動一個容易被漏掉的真實組合6.1 為什么它們能連起來很多接口是登錄后才能使用的包括SSRF觸發(fā)點。攻擊者沒有受害者會話本來調(diào)不動這個接口。但CSRF恰好不需要攻擊者持有會話——它只需要受害者的瀏覽器帶著受害者自己的會話去訪問這個接口。于是兩條漏洞線接上了攻擊者先在受害者身份下觸發(fā)一次跨站請求讓服務(wù)器去請求攻擊者指定的內(nèi)網(wǎng)地址。這在真實業(yè)務(wù)里的對應(yīng)場景很常見開發(fā)團(tuán)隊給某個“URL下載接口”做了登錄校驗以為外網(wǎng)用戶不能直接用但他們忘了給接口配CSRF Token。做SSRF防御時只加了一層“要登錄”相當(dāng)于給門上了個門把手門還是沒鎖。6.2 組合關(guān)的觀察順序找服務(wù)端會主動發(fā)請求的功能圖片下載、URL預(yù)覽、Webhook回調(diào)確認(rèn)它是否要求登錄如果要求登錄繼續(xù)查有沒有Token、Origin、SameSite防護(hù)如果只有登錄校驗把它當(dāng)成一個CSRF目標(biāo)構(gòu)造跨站頁面觸發(fā)它觸發(fā)成功后再走SSRF的繞過流程去打內(nèi)網(wǎng)目標(biāo)。這種組合題在靶場里通常被放在“進(jìn)階”區(qū)。做出來的瞬間你會覺得CSRF和SSRF不是兩塊獨立知識它們本來就串在一條請求鏈路上CSRF控制“誰發(fā)起”SSRF控制“發(fā)到哪”。兩層都防住鏈子才斷。6.3 倒過來的組合也存在反過來同樣成立SSRF訪問到內(nèi)網(wǎng)某個未授權(quán)接口后如果這個內(nèi)網(wǎng)接口本身也缺少CSRF防護(hù)攻擊者相當(dāng)于借用服務(wù)器在內(nèi)網(wǎng)網(wǎng)絡(luò)里的位置替自己發(fā)了一輪“跨站請求”。理解了“誰借誰的憑證發(fā)起請求”這個本質(zhì)鏈?zhǔn)綀鼍耙谎劬湍芸创┖罄m(xù)刷題遇到SSRF打內(nèi)網(wǎng)Redis、內(nèi)網(wǎng)管理臺這類關(guān)卡思路也會順很多。7. 刷完之后照著改兩份防御清單7.1 CSRF修復(fù)自查[ ] 狀態(tài)變更請求一律限制為POST避免GET改數(shù)據(jù)[ ] 每個會話獨立生成隨機Token提交時與Session校驗使用后失效[ ] Token放在請求體或自定義Header里不放URL[ ] 關(guān)鍵接口要求自定義Header跨站表單發(fā)不了[ ] Cookie配置SameSite根據(jù)業(yè)務(wù)在Lax和Strict之間選擇[ ] 不要只依賴單一校驗Token為主、Origin校驗兜底[ ] 登錄、登出、改密碼這類邊界接口也要覆蓋。登錄接口本身也存在CSRF這一點經(jīng)常被忽略。攻擊者可以誘導(dǎo)受害者登錄攻擊者的賬號受害者后續(xù)做的每一步操作都會被記錄變成另一種隱私泄露。靶場里如果單獨出了一道“登錄CSRF”的題它修起來和普通CSRF沒有本質(zhì)區(qū)別但容易被漏。7.2 SSRF修復(fù)自查[ ] 協(xié)議白名單只放http、https[ ] 目標(biāo)域名白名單不靠IP黑名單[ ] 域名解析后的IP在連接前再次校驗排除回環(huán)、私網(wǎng)、鏈路本地地址127.0.0.0/8、10.0.0.0/8、172.16.0.0/12、192.168.0.0/16、169.254.0.0/16、::1、0.0.0.0都要考慮[ ] 禁止跟隨重定向或每次重定向都重新校驗[ ] 用獨立的DNS解析并單獨校驗解析結(jié)果防DNS重綁定[ ] 出網(wǎng)只開放必要端口響應(yīng)內(nèi)容脫敏錯誤不原樣回顯設(shè)置超時[ ] 在URL解析和HTTP連接這兩個層面都拒絕非http協(xié)議。7.3 三個最常見的防御誤區(qū)一是黑名單思維。禁止127.0.0.1、禁止localhost是典型的黑名單進(jìn)制寫法、IPv6、重定向、DNS重綁定全都能繞。防御只能靠白名單加解析后校驗。二是以為SSRF是輸入過濾問題。SSRF的根子在“出網(wǎng)請求不受控”輸入過濾只是補丁。修復(fù)要落在網(wǎng)絡(luò)出口、協(xié)議白名單、請求庫配置上而不是在參數(shù)層面反復(fù)加規(guī)則。三是“有Token就安全了”的錯覺。Token解決的是“請求是不是用戶本意”解決不了“服務(wù)器訪問了不該訪問的地址”。CSRF和SSRF是兩條信任鏈各修各的不能混用。收尾把“誰替誰發(fā)請求”刻進(jìn)腦子里這套靶場刷完兩輪之后我養(yǎng)成了一個習(xí)慣凡是看到服務(wù)器會主動訪問外部地址的功能先在紙上畫一條請求鏈路標(biāo)出“誰發(fā)起的”“帶誰的身份”“訪問的地址可不可控”。CSRF和SSRF表面上一橫一豎落到這條鏈路上其實就是兩個節(jié)點的事。建議你把每一個關(guān)卡重置之后不看筆記再走一遍再試著把漏洞的修復(fù)代碼寫出來。能動手修才算真正通解。