
每個(gè) Java 軟件架構(gòu)師都應(yīng)該知道的 20 件事
How much do you want to send?
<input name="amount" />
To whom do you want to send it?
<input name="receiver" />
<input type="submit" value="Send" />
</form>
攻擊者在 BankApp 網(wǎng)站上以用戶名 @evil 開設(shè)賬戶。攻擊者撰寫了兩封單獨(dú)的釣魚郵件。第一封郵件假裝來自 BankApp,內(nèi)容是“警告!您的 BankApp 賬戶中檢測(cè)到潛在欺詐行為。”第二封郵件內(nèi)容是“您可能贏了 1,000 美元。”第一封郵件的目的是鼓勵(lì)用戶登錄 BankApp。第二封郵件包含以下標(biāo)記:HTML
<form method="post" action="https://bankapp.com/transfer">
<input name="amount" type="hidden" value="1000" />
<input name="recipient" type="hidden" value="@evil" />
</form>
<script>document.forms[0].submit();</script>
用戶甚至無需點(diǎn)擊任何內(nèi)容。第二封電子郵件提交表單并在用戶瀏覽器中呈現(xiàn)后立即執(zhí)行攻擊。攻擊者使用這兩封電子郵件向 100,000 名用戶發(fā)送垃圾郵件。其中一些用戶可能擁有 BankApp 帳戶。其中一些用戶會(huì)打開電子郵件,攻擊者從每封電子郵件中獲得 1000 美元。
服務(wù)器通過 HTTP 公開的任何狀態(tài)更改都可能受到偽造請(qǐng)求的影響。CSRF 攻擊可以更改密碼、發(fā)布社交媒體帖子、刪除帳戶、配置路由器以及許多其他危險(xiǎn)或破壞性的操作。
BankApp 示例假設(shè)您必須通過 POST 表單來轉(zhuǎn)賬。并非所有 Web 端點(diǎn)都以這種方式編寫。如果 BankApp 網(wǎng)站允許使用 GET 請(qǐng)求轉(zhuǎn)賬,那么攻擊者的電子郵件可能只會(huì)這樣做:HTML
<IMG src="http://bankapp.com/transfer?amount=1000&recipient=@evil">
當(dāng)用戶在釣魚郵件中看到損壞的圖像標(biāo)簽時(shí),1000 美元就已經(jīng)沒了。
其他可改變狀態(tài)的 HTTP 動(dòng)詞也可能被利用。只有 PATCH、POST、PUT 和 DELETE應(yīng)允許更改狀態(tài),但如果 GET、HEAD 和 OPTIONS 也能進(jìn)行更改,則可能存在漏洞。
不要忽略登錄頁面上的 CSRF 警告。在登錄時(shí),即使用戶尚未通過身份驗(yàn)證,CSRF 攻擊仍然可能是一種威脅,盡管方法和風(fēng)險(xiǎn)與經(jīng)過身份驗(yàn)證的 CSRF 不同。在登錄 CSRF 攻擊中,攻擊者偽造請(qǐng)求,使用攻擊者的登錄憑據(jù)將用戶登錄到站點(diǎn)。受害者可能會(huì)認(rèn)為自己已經(jīng)登錄了自己的帳戶,從而留下攻擊者可以使用的信息。針對(duì) Google 和 Yahoo 的登錄 CSRF 攻擊可能會(huì)將受害者的搜索歷史記錄暴露給攻擊者。針對(duì) PayPal 等網(wǎng)站的登錄攻擊可能會(huì)誘使用戶提供信用卡信息,然后攻擊者可以登錄并使用這些信息。
CSRF 攻擊依賴于能夠預(yù)測(cè)瀏覽器請(qǐng)求的內(nèi)容,從而偽造瀏覽器請(qǐng)求。針對(duì) CSRF 的最強(qiáng)大防御方法是使每個(gè)請(qǐng)求的內(nèi)容不可預(yù)測(cè)。基于令牌的防御依賴于隨機(jī)生成的值來做到這一點(diǎn)。
為了保護(hù)自己,服務(wù)器會(huì)向每個(gè)表單添加一個(gè)隱藏字段,為每個(gè)會(huì)話(或每個(gè)請(qǐng)求)分配一個(gè)不同的隨機(jī)值。服務(wù)器會(huì)確認(rèn)每個(gè)后續(xù)請(qǐng)求都具有此字段,并且其值與為會(huì)話分配的值相匹配。這稱為同步器令牌模式。
同步器令牌要求服務(wù)器在服務(wù)器端存儲(chǔ)隨機(jī)會(huì)話值。如果您不想在服務(wù)器上保留狀態(tài),則可以使用只有服務(wù)器上才知道的私鑰加密令牌值。加密值應(yīng)該是時(shí)間戳。通過確認(rèn)每個(gè)請(qǐng)求都包含隱藏字段、您可以解密字段值、解密值是時(shí)間戳以及時(shí)間戳是最近的(令牌未過期)來驗(yàn)證后續(xù)請(qǐng)求。
加密令牌是一種無狀態(tài)的 CSRF 防御措施,而雙重提交的 cookie 是另一種。在這種防御措施中,隨機(jī)令牌值保存在客戶端的 cookie 中。每個(gè)后續(xù)請(qǐng)求都必須在隱藏字段中包含相同的值。在每次請(qǐng)求中,服務(wù)器都會(huì)確認(rèn)隱藏字段是否存在,并且其值與 cookie 中的值匹配。
為了確保這種防御的可靠性,您必須使用 HTTPS(無論如何都推薦使用)并確保您的子域也是安全的。
AJAX 調(diào)用發(fā)生在基于 Cookie 的瀏覽器會(huì)話上下文中,也容易受到 CSRF 攻擊。AJAX 調(diào)用通常不會(huì)發(fā)布可以放置隱藏字段的表單。相反,它會(huì)在自定義 AJAX 標(biāo)頭中將 CSRF 令牌返回給服務(wù)器。JavaScript
var xhr = new XMLHttpRequest();
xhr.setRequestHeader(tokenname, tokenvalue);
將tokenname
和替換tokenvalue
為生成 AJAX 請(qǐng)求的頁面中隱藏的隨機(jī)令牌字段的名稱和值。
使用自定義 HTTP 標(biāo)頭是一種防御措施,因?yàn)橹挥?JavaScript 可以創(chuàng)建自定義標(biāo)頭,并且瀏覽器的單源策略 (SOP) 會(huì)阻止跨站點(diǎn) JavaScript 調(diào)用。
許多編程框架(例如Spring、Django、.NET和AngularJS )都帶有基于令牌的 CSRF 防御的內(nèi)置實(shí)現(xiàn),這些實(shí)現(xiàn)可以生成加密性強(qiáng)的隨機(jī)令牌值并在每次請(qǐng)求時(shí)對(duì)其進(jìn)行驗(yàn)證。其他一些框架也有可用的附加組件:例如,適用于 Java 的OWASP CSRFGuard和適用于 PHP 的CSRFProtector 項(xiàng)目。正確實(shí)施基于令牌的防御可能很棘手,因此如果有人已經(jīng)為您制定了可靠的實(shí)現(xiàn),請(qǐng)不要自行構(gòu)建。
基于令牌的防御效果最好,但縱深防御方法需要考慮額外措施來阻止可能的 CSRF 攻擊。
SameSite是一種 Cookie 屬性,類似于Secure、HTTPOnly和Expires。SameSite 屬性讓網(wǎng)站設(shè)計(jì)者決定瀏覽器何時(shí)應(yīng)在跨站點(diǎn)請(qǐng)求中包含 Cookie。SameSite 的值可能是Strict或Lax,任何一個(gè)值都會(huì)阻止至少一些 CSRF 請(qǐng)求。這是一種有用的防御措施,但僅靠它還不夠,因?yàn)椴⒎撬袨g覽器都支持它(大多數(shù)瀏覽器都支持),而且它可以被繞過。
要確認(rèn)請(qǐng)求是否有效,請(qǐng)檢查 HTTP 標(biāo)頭以確認(rèn)來源和目標(biāo)值是否匹配。要確定請(qǐng)求的來源,請(qǐng)檢查 Origin 或 Referer 標(biāo)頭。將其與請(qǐng)求的目的地進(jìn)行比較:目標(biāo)來源。這些值無法偽造。只有瀏覽器才允許設(shè)置它們。
這種防御措施的優(yōu)點(diǎn)是,甚至在身份驗(yàn)證之前就可以識(shí)別跨站點(diǎn)請(qǐng)求。但是,一小部分網(wǎng)絡(luò)流量可能會(huì)出于正當(dāng)理由忽略請(qǐng)求來源,并且如果您的應(yīng)用程序位于代理后面,則確定目標(biāo)來源并非易事。
有時(shí)(尤其是對(duì)于高風(fēng)險(xiǎn)交易)直接讓用戶參與是緩解 CSRF 和其他偽造請(qǐng)求的有效方法。要求用戶提供密碼或一次性令牌,或者通過 CAPTCHA,可以提供有效的保護(hù)。
這些提示將幫助您避免防御 CSRF 時(shí)常見的問題。
如果未正確實(shí)施,基于令牌的防御措施可能會(huì)被攻破。為了確保隨機(jī)令牌值無法預(yù)測(cè),應(yīng)使用加密性強(qiáng)的隨機(jī)數(shù)生成器來創(chuàng)建令牌值。此外,請(qǐng)謹(jǐn)慎使用將生成的值與請(qǐng)求中收到的值進(jìn)行匹配的邏輯。驗(yàn)證邏輯中的錯(cuò)誤導(dǎo)致GlassDoor 遭受 CSRF 攻擊。在 GlassDoor 實(shí)施的某些情況下,檢查失敗會(huì)引發(fā)異常,但該異常僅被記錄下來,代碼會(huì)繼續(xù)執(zhí)行,就像驗(yàn)證成功一樣。
此外,跨站點(diǎn)腳本漏洞 (XSS)可以擊敗任何 CSRF 保護(hù)。如果攻擊者可以從用戶的瀏覽器中檢索令牌,即使是完美實(shí)施的基于令牌的 CSRF 防御也幾乎無法提供保護(hù)。可靠的 XSS 防御是 CSRF 防御的先決條件。
這些措施有時(shí)被視為緩解措施,但卻不起作用:
多步驟交易
如果攻擊者仍然可以預(yù)測(cè)事務(wù)的每個(gè)步驟,那么將改變服務(wù)器狀態(tài)的操作分成多個(gè) HTTP 請(qǐng)求是沒有幫助的。
秘密cookie
創(chuàng)建攻擊者無法預(yù)測(cè)的秘密 cookie 毫無用處,因?yàn)闉g覽器總是在每次請(qǐng)求時(shí)發(fā)回所有相關(guān) cookie。攻擊者無需猜測(cè)秘密 cookie。
HTTPS
單純加密網(wǎng)絡(luò)流量并不能阻止 CSRF 攻擊。然而,對(duì)于其他一些緩解措施(例如雙重提交的 cookie)而言,這是必要的步驟,并且在所有情況下都可取,以使其他措施更加可靠。
URL 重寫
您可以在頁面加載時(shí)修改 URL,從而消除會(huì)話 cookie,但這樣做會(huì)在 URL 上暴露會(huì)話 ID,從而增加攻擊者捕獲會(huì)話 ID 的風(fēng)險(xiǎn)。
跨站點(diǎn)腳本 (XSS) 漏洞與跨站點(diǎn)請(qǐng)求偽造 (CSRF) 漏洞具有一些共同的特征。兩者都旨在在受害者的合法網(wǎng)絡(luò)會(huì)話環(huán)境中運(yùn)行惡意代碼。然而,XSS 旨在將惡意代碼直接注入易受攻擊的頁面,而 CSRF 通常依賴于社交工程(例如網(wǎng)絡(luò)釣魚電子郵件)將惡意代碼放入受害者瀏覽器中的不相關(guān)頁面。XSS 依賴于目標(biāo)網(wǎng)站中的缺陷,這些缺陷允許注入惡意代碼,服務(wù)器將把這些惡意代碼作為其自身網(wǎng)頁的一部分傳遞給受害者。
差異很大。惡意 XSS 腳本可以直接訪問目標(biāo)站點(diǎn)中的頁面。事實(shí)上,XSS 漏洞可以向攻擊者暴露頁面上的所有內(nèi)容,包括任何反 CSRF 令牌值。即使是完美的防御措施也幾乎無法為易受 XSS 攻擊的站點(diǎn)提供 CSRF 保護(hù)。
漏洞測(cè)試是任何安全程序的基本組成部分。掃描工具能夠發(fā)現(xiàn)許多 CSRF(和 XSS)漏洞。鑒于此類漏洞的潛在嚴(yán)重性,任何擁有 Web 應(yīng)用程序的人都應(yīng)系統(tǒng)地測(cè)試它們 – 最好將自動(dòng)掃描作為 CI/CD 管道的一部分。漏洞測(cè)試需要遵守最佳實(shí)踐和標(biāo)準(zhǔn),例如 NIST SP 800-53 和 ISO 27001。高風(fēng)險(xiǎn)應(yīng)用程序還應(yīng)在其安全程序中包括手動(dòng)滲透測(cè)試。
文章來源:What is Cross-Site Request Forgery (CSRF)?
每個(gè) Java 軟件架構(gòu)師都應(yīng)該知道的 20 件事
2024年國(guó)外熱門天氣環(huán)境API
如何在 Python 和 Flask 中使用 IP API 查找地理位置?
2024年免費(fèi)日歷假期API
REST API 安全最佳實(shí)踐與常見漏洞解析
如何免費(fèi)調(diào)用有道翻譯API實(shí)現(xiàn)多語言翻譯
Python 實(shí)現(xiàn)自動(dòng)化寫作助手:零一萬物api輕松上手
使用Python調(diào)用免費(fèi)歸屬地查詢API
最佳經(jīng)緯度查詢API免費(fèi)版推薦與使用指南
對(duì)比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力
一鍵對(duì)比試用API 限時(shí)免費(fèi)