您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關CSRF攻擊的示例分析的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
什么是CSRF攻擊?
CSRF 全稱
Cross-site request forgery
,中文為跨站請求偽造 ,攻擊者誘導受害者進入第三方網站,在第三方網站中,向被攻擊網站發送跨站請求。利用受害者在被攻擊網站已經獲取的注冊憑證,繞過后臺的用戶驗證,達到冒充用戶對被攻擊的網站執行某項操作的目的。 CSRF攻擊就是黑客利用用戶的登錄狀態,并通過第三方站點來干一些嘿嘿嘿的壞事。
幾種常見的攻擊類型
1.GET類型的CSRF
GET類型的CSRF非常簡單,通常只需要一個HTTP請求:
<img src="http://bank.example/withdraw?amount=10000&for=hacker" >
在受害者訪問含有這個img的頁面后,瀏覽器會自動向http://bank.example/withdraw?account=xiaoming&amount=10000&for=hacker
發出一次HTTP請求。bank.example就會收到包含受害者登錄信息的一次跨域請求。
2.POST類型的CSRF
這種類型的CSRF利用起來通常使用的是一個自動提交的表單,如:
<form action="http://bank.example/withdraw" method=POST> <input type="hidden" name="account" value="xiaoming" /> <input type="hidden" name="amount" value="10000" /> <input type="hidden" name="for" value="hacker" /> </form> <script> document.forms[0].submit(); </script>
訪問該頁面后,表單會自動提交,相當于模擬用戶完成了一次POST操作。
3.鏈接類型的CSRF
鏈接類型的CSRF并不常見,比起其他兩種用戶打開頁面就中招的情況,這種需要用戶點擊鏈接才會觸發。這種類型通常是在論壇中發布的圖片中嵌入惡意鏈接,或者以廣告的形式誘導用戶中招,攻擊者通常會以比較夸張的詞語誘騙用戶點擊,例如:
<a href="http://test.com/csrf/withdraw.php?amount=1000&for=hacker" taget="_blank"> 重磅消息!! <a/>
由于之前用戶登錄了信任的網站A,并且保存登錄狀態,只要用戶主動訪問上面的這個PHP頁面,則表示攻擊成功。
CSRF的特點
攻擊一般發起在第三方網站,而不是被攻擊的網站。被攻擊的網站無法防止攻擊發生。
攻擊利用受害者在被攻擊網站的登錄憑證,冒充受害者提交操作;而不是直接竊取數據。
整個過程攻擊者并不能獲取到受害者的登錄憑證,僅僅是“冒用”。
跨站請求可以用各種方式:圖片URL、超鏈接、CORS、Form提交等等。部分請求方式可以直接嵌入在第三方論壇、文章中,難以進行追蹤。
CSRF通常是跨域的,因為外域通常更容易被攻擊者掌控。但是如果本域下有容易被利用的功能,比如可以發圖和鏈接的論壇和評論區,攻擊可以直接在本域下進行,而且這種攻擊更加危險。
防護策略
黑客只能借助受害者的cookie
騙取服務器的信任,但是黑客并不能憑借拿到**「cookie」**,也看不到 **「cookie」的內容。另外,對于服務器返回的結果,由于瀏覽器「同源策略」**的限制,黑客也無法進行解析。
這就告訴我們,我們要保護的對象是那些可以直接產生數據改變的服務,而對于讀取數據的服務,則不需要進行
CSRF
的保護。而保護的關鍵,是 「在請求中放入黑客所不能偽造的信息」
同源檢測
既然CSRF大多來自第三方網站,那么我們就直接禁止外域(或者不受信任的域名)對我們發起請求。
那么問題來了,我們如何判斷請求是否來自外域呢?
在HTTP協議中,每一個異步請求都會攜帶兩個Header,用于標記來源域名:
Origin Header
Referer Header
這兩個Header在瀏覽器發起請求時,大多數情況會自動帶上,并且不能由前端自定義內容。 服務器可以通過解析這兩個Header中的域名,確定請求的來源域。
使用Origin Header確定來源域名
在部分與CSRF有關的請求中,請求的Header中會攜帶Origin字段。字段內包含請求的域名(不包含path及query)。
如果Origin存在,那么直接使用Origin中的字段確認來源域名就可以。
但是Origin在以下兩種情況下并不存在:
IE11同源策略: IE 11 不會在跨站CORS請求上添加Origin標頭,Referer頭將仍然是唯一的標識。最根本原因是因為IE 11對同源的定義和其他瀏覽器有不同,有兩個主要的區別,可以參考MDN Same-origin_policy#IE_Exceptions
302重定向: 在302重定向之后Origin不包含在重定向的請求中,因為Origin可能會被認為是其他來源的敏感信息。對于302重定向的情況來說都是定向到新的服務器上的URL,因此瀏覽器不想將Origin泄漏到新的服務器上。
使用Referer Header確定來源域名
根據HTTP協議,在HTTP頭中有一個字段叫Referer,記錄了該HTTP請求的來源地址。 對于Ajax請求,圖片和script等資源請求,Referer為發起請求的頁面地址。對于頁面跳轉,Referer為打開頁面歷史記錄的前一個頁面地址。因此我們使用Referer中鏈接的Origin部分可以得知請求的來源域名。
這種方法并非萬無一失,Referer的值是由瀏覽器提供的,雖然HTTP協議上有明確的要求,但是每個瀏覽器對于Referer的具體實現可能有差別,并不能保證瀏覽器自身沒有安全漏洞。使用驗證 Referer 值的方法,就是把安全性都依賴于第三方(即瀏覽器)來保障,從理論上來講,這樣并不是很安全。在部分情況下,攻擊者可以隱藏,甚至修改自己請求的Referer。
2014年,W3C的Web應用安全工作組發布了Referrer Policy草案,對瀏覽器該如何發送Referer做了詳細的規定。截止現在新版瀏覽器大部分已經支持了這份草案,我們終于可以靈活地控制自己網站的Referer策略了。新版的Referrer Policy規定了五種Referer策略:No Referrer、No Referrer When Downgrade、Origin Only、Origin When Cross-origin、和 Unsafe URL。之前就存在的三種策略:never、default和always,在新標準里換了個名稱。他們的對應關系如下:
策略名稱 | 屬性值(新) | 屬性值(舊) |
---|---|---|
No Referrer | no-Referrer | never |
No Referrer When Downgrade | no-Referrer-when-downgrade | default |
Origin Only | (same or strict) origin | origin |
Origin When Cross Origin | (strict) origin-when-crossorigin | - |
Unsafe URL | unsafe-url | always |
根據上面的表格因此需要把Referrer Policy的策略設置成same-origin,對于同源的鏈接和引用,會發送Referer,referer值為Host不帶Path;跨域訪問則不攜帶Referer。例如:aaa.com
引用bbb.com
的資源,不會發送Referer。
設置Referrer Policy的方法有三種:
在CSP設置
頁面頭部增加meta標簽
a標簽增加referrerpolicy屬性
上面說的這些比較多,但我們可以知道一個問題:攻擊者可以在自己的請求中隱藏Referer。如果攻擊者將自己的請求這樣填寫:
<img src="http://bank.example/withdraw?amount=10000&for=hacker" referrerpolicy="no-referrer">
那么這個請求發起的攻擊將不攜帶Referer。
另外在以下情況下Referer沒有或者不可信:
1.IE6、7下使用window.location.href=url進行界面的跳轉,會丟失Referer。
2.IE6、7下使用window.open,也會缺失Referer。
3.HTTPS頁面跳轉到HTTP頁面,所有瀏覽器Referer都丟失。
4.點擊Flash上到達另外一個網站的時候,Referer的情況就比較雜亂,不太可信。
無法確認來源域名情況
當Origin和Referer頭文件不存在時該怎么辦?如果Origin和Referer都不存在,建議直接進行阻止,特別是如果您沒有使用隨機CSRF Token(參考下方)作為第二次檢查。
如何阻止外域請求
通過Header的驗證,我們可以知道發起請求的來源域名,這些來源域名可能是網站本域,或者子域名,或者有授權的第三方域名,又或者來自不可信的未知域名。
我們已經知道了請求域名是否是來自不可信的域名,我們直接阻止掉這些的請求,就能防御CSRF攻擊了嗎?
且慢!當一個請求是頁面請求(比如網站的主頁),而來源是搜索引擎的鏈接(例如百度的搜索結果),也會被當成疑似CSRF攻擊。所以在判斷的時候需要過濾掉頁面請求情況,通常Header符合以下情況:
Accept: text/html Method: GET
但相應的,頁面請求就暴露在了CSRF的攻擊范圍之中。如果你的網站中,在頁面的GET請求中對當前用戶做了什么操作的話,防范就失效了。
例如,下面的頁面請求:
GET https://example.com/addComment?comment=XXX&dest=orderId
注:這種嚴格來說并不一定存在CSRF攻擊的風險,但仍然有很多網站經常把主文檔GET請求掛上參數來實現產品功能,但是這樣做對于自身來說是存在安全風險的。
另外,前面說過,CSRF大多數情況下來自第三方域名,但并不能排除本域發起。如果攻擊者有權限在本域發布評論(含鏈接、圖片等,統稱UGC),那么它可以直接在本域發起攻擊,這種情況下同源策略無法達到防護的作用。
綜上所述:同源驗證是一個相對簡單的防范方法,能夠防范絕大多數的CSRF攻擊。但這并不是萬無一失的,對于安全性要求較高,或者有較多用戶輸入內容的網站,我們就要對關鍵的接口做額外的防護措施。
CSRF Token
前面講到CSRF的另一個特征是,攻擊者無法直接竊取到用戶的信息(Cookie,Header,網站內容等),僅僅是冒用Cookie中的信息。
而CSRF攻擊之所以能夠成功,是因為服務器誤把攻擊者發送的請求當成了用戶自己的請求。那么我們可以要求所有的用戶請求都攜帶一個CSRF攻擊者無法獲取到的Token。服務器通過校驗請求是否攜帶正確的Token,來把正常的請求和攻擊的請求區分開,也可以防范CSRF的攻擊。
利用Cookie的SameSite屬性
SameSite
可以設置為三個值,Strict
、Lax
和None
。
在Strict
模式下,瀏覽器完全禁止第三方請求攜帶Cookie。比如請求sanyuan.com
網站只能在sanyuan.com
域名當中請求才能攜帶 Cookie,在其他網站請求都不能。
在Lax
模式,就寬松一點了,但是只能在 get 方法提交表單
況或者a 標簽發送 get 請求
的情況下可以攜帶 Cookie,其他情況均不能。
在None模式下,Cookie將在所有上下文中發送,即允許跨域發送。
感謝各位的閱讀!關于“CSRF攻擊的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。