CSRF的原理與防御 | 你想不想來一次CSRF攻擊?


CSRFCross Site Request Forgery的縮寫,中文翻譯過來是跨站請求偽造。這個漏洞往往能給用戶帶來巨大的損失,CSRF在等保安全檢測中,也是一個非常重要的檢測項。但是在我們的網站中,大部分都沒有做CSRF的防御,小伙伴們想不想來一次CSRF攻擊,體驗一下做黑客感覺?如果想要做黑客,可要仔細的往下看喲~

CSRF攻擊的原理

要想理解CSRF攻擊的原理,我們從一個經典的案例出發,看看它是如何進行攻擊的。假設你的銀行網站的域名是www.a-bank.com,這個銀行網站提供了一個轉賬的功能,在這個功能頁面中,有一個表單,表單中有兩個輸入框,一個是轉賬金額,另一個是對方賬號,還有一個提交按鈕。當你登錄了你的銀行網站,輸入轉賬金額,對方賬號,點擊提交按鈕,就會進行轉賬。

當然,現在的銀行網站不會有這么簡單的轉賬操作了,我們在這里只是舉一個簡單的例子,讓大家明白CSRF的原理。咱們可以發散思維,聯想到其他類似的操作。

這個轉賬的表單項,如下所示:

<form method="post" action="/transfer">
    <input type="text" name="amount"/>
    <input type="text" name="account"/>
    <input type="submit" value="Transfer"/>
</form>

當我們輸入金額和賬號,點擊提交按鈕,表單就會提交,給后端的銀行網站服務發送請求。請求的內容如下:

POST /transfer HTTP/1.1
Host: www.a-bank.com
Cookie: JSESSIONID=randomid
Content-Type: application/x-www-form-urlencoded

amount=100.00&account=9876

請求成功后,你輸入的轉賬金額100元,將轉賬到9876這個賬戶當中。假如你完成轉賬操作后,並沒有退出登錄,而是訪問了一個惡意網站,這時,你的銀行網站www.a-bank.com還是處於登錄狀態,而這個惡意網站中,出現了一個帶有”贏錢“字樣的按鈕,這個”贏錢“字樣的按鈕后面是一個form表單,表單如下:

<form method="post" action="https://www.a-bank.com/transfer">
    <input type="hidden" name="amount" value="100.00"/>
    <input type="hidden" name="account" value="黑客的銀行賬戶"/>
    <input type="submit" value="贏錢!"/>
</form>

我們可以看到這個表單中,金額和賬戶都是隱藏的,在網頁上只看到了一個贏錢按鈕。這時,你忍不住沖動,點了一個”贏錢“按鈕,這時,將會發生什么操作呢?我們仔細看一下上面表單中的action寫的是什么?action寫的是你的銀行網站的轉賬請求接口。你點了一下贏錢按鈕,在這個不正規的網站中,將會發送https://www.a-bank.com/transfer這個請求,在發送這個請求的時候,會自動帶上www.a-bank.com的cookie,不要問我為什么是這樣,這是瀏覽器的標准,標准就是這樣規定的。銀行后台接到這個請求后,首先要判斷用戶是否登錄,由於攜帶了cookie,是登錄的,會繼續執行后面的轉賬流程,最后轉賬成功。你點了一下”贏錢“按鈕,自己沒有賺到錢,而是給黑客轉賬了100元。

這就是CSRF攻擊的原理,在其他的網站向你的網站發送請求,如果你的網站中的用戶沒有退出登錄,而發送的請求又是一些敏感的操作請求,比如:轉賬,那么將會給你的網站的用戶帶來巨大的損失。

CSRF的防御

我們知道了CSRF攻擊的原理,就可以做針對性的防御了。CSRF的防御可以從兩個方面考慮,一個是后台接口層做防御;另一個則是在前端做防御,這種不同源的請求,不可以帶cookie。

后端防御CSRF

我們先聊聊后端的防御,后端防御主要是區分哪些請求是惡意請求,哪些請求是自己網站的請求。區分惡意請求的方式有很多,在這里給大家介紹兩種吧。

第一種,CSRF Token的方式。這種方式是在表單頁面生成一個隨機數,這個隨機數一定要后端生成,並且對這個隨機數進行存儲。在前端頁面中,對這個Token表單項進行隱藏。代碼如下:

<form method="post" action="/transfer">
    <input type="hidden" name="_csrf" value="4bfd1575-3ad1-4d21-96c7-4ef2d9f86721"/>
    <input type="text" name="amount"/>
    <input type="hidden" name="account"/>
    <input type="submit" value="Transfer"/>
</form>

_csrf就是CSRF Token。我們看到他的value是一個UUID,這個UUID是后台生成的。當用戶點擊轉賬按鈕時,會給銀行的后台發送請求,請求中包含_csrf參數,如下:

POST /transfer HTTP/1.1
Host: www.a-bank.com
Cookie: JSESSIONID=randomid
Content-Type: application/x-www-form-urlencoded

amount=100.00&account=9876&_csrf=4bfd1575-3ad1-4d21-96c7-4ef2d9f86721

銀行后台接收到這個請求后,判斷_csrf的值是否存在,如果存在則是自己網站的請求,進行后續的流程;如果不存在,則是惡意網站的請求,直接忽略。

第二種,通過請求頭中的referer字段判斷請求的來源。每一個發送給后端的請求,在請求頭中都會包含一個referer字段,這個字段標識着請求的來源。如果請求是從銀行網站發出的,這個字段會是銀行網站轉賬頁的鏈接,比如:https://www.a-bank.com/transfer-view;如果是從惡意網站發出的,那么referer字段一定不會是銀行網站。我們在做后端防御時,可以先取出每個請求的請求頭中的referer字段,判斷是不是以自己網站的域名開頭,在咱們的示例中,如果referer字段是以https://www.a-bank.com/開頭的,則繼續執行轉賬操作;如果不是,則直接忽略掉這個請求。

以上就是后端防御CSRF攻擊的兩種方式,都需要在后端做特殊的處理。當然也可以在前端做處理,怎么做呢?我們接着往下看。

前端防御CSRF

既然CSRF攻擊的危害這么大,為什么不能在前端禁止這種請求呢?各大瀏覽器廠商似乎也注意到了這個問題,谷歌提出了same-site cookies概念,same-site cookies 是基於 Chrome 和 Mozilla 開發者花了三年多時間制定的 IETF 標准。它是在原有的Cookie中,新添加了一個SameSite屬性,它標識着在非同源的請求中,是否可以帶上Cookie,它可以設置為3個值,分別為:

  • Strict
  • Lax
  • None

Cookie中的內容為:

POST /transfer HTTP/1.1
Host: www.a-bank.com
Cookie: JSESSIONID=randomid;SameSite=Strict;

Strict是最嚴格的,它完全禁止在跨站情況下,發送Cookie。只有在自己的網站內部發送請求,才會帶上Cookie。不過這個規則過於嚴格,會影響用戶的體驗。比如在一個網站中有一個鏈接,這個鏈接連接到了GitHub上,由於SameSite設置為Strict,跳轉到GitHub后,GitHub總是未登錄狀態。

Lax的規則稍稍放寬了些,大部分跨站的請求也不會帶上Cookie,但是一些導航的Get請求會帶上Cookie,如下:

請求類型 示例 Lax情況
鏈接 <a href="..."></a> 發送 Cookie
預加載 <link rel="prerender" href="..."/> 發送 Cookie
GET 表單 <form method="GET" action="..."> 發送 Cookie
POST 表單 <form method="POST" action="..."> 不發送
iframe <iframe src="..."></iframe> 不發送
AJAX $.get("...") 不發送
Image <img src="..."> 不發送

上面的表格就是SameSite設置為Lax的時候,Cookie的發送情況。

None就是關閉SameSite屬性,所有的情況下都發送Cookie。不過SameSite設置None,還要同時設置Cookie的Secure屬性,否則是不生效的。

以上就是在前端通過Cookie的SameSite屬性防御CSRF攻擊,不過大家在使用SameSite屬性時,要注意瀏覽器是否支持SameSite屬性。

總結

到這里CSRF的攻和防都已經介紹完了,大部分網站都是沒有做CSRF防御的,小伙伴們有沒有想當黑客的癮,找幾個網站搞一下試試吧~~
微信公眾號


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM