CSRF是Cross Site Request Forgery的縮寫峻仇,中文翻譯過來是跨站請求偽造公黑。這個漏洞往往能給用戶帶來巨大的損失,CSRF在等保安全檢測中摄咆,也是一個非常重要的檢測項凡蚜。但是在我們的網(wǎng)站中,大部分都沒有做CSRF的防御吭从,小伙伴們想不想來一次CSRF攻擊朝蜘,體驗一下做黑客感覺?如果想要做黑客涩金,可要仔細的往下看喲~
CSRF攻擊的原理
要想理解CSRF攻擊的原理谱醇,我們從一個經(jīng)典的案例出發(fā)暇仲,看看它是如何進行攻擊的。假設(shè)你的銀行網(wǎng)站的域名是www.a-bank.com
副渴,這個銀行網(wǎng)站提供了一個轉(zhuǎn)賬的功能奈附,在這個功能頁面中,有一個表單煮剧,表單中有兩個輸入框斥滤,一個是轉(zhuǎn)賬金額,另一個是對方賬號勉盅,還有一個提交按鈕佑颇。當你登錄了你的銀行網(wǎng)站,輸入轉(zhuǎn)賬金額草娜,對方賬號漩符,點擊提交按鈕,就會進行轉(zhuǎn)賬驱还。
當然,現(xiàn)在的銀行網(wǎng)站不會有這么簡單的轉(zhuǎn)賬操作了凸克,我們在這里只是舉一個簡單的例子议蟆,讓大家明白CSRF的原理。咱們可以發(fā)散思維萎战,聯(lián)想到其他類似的操作咐容。
這個轉(zhuǎn)賬的表單項,如下所示:
<form method="post" action="/transfer">
<input type="text" name="amount"/>
<input type="text" name="account"/>
<input type="submit" value="Transfer"/>
</form>
當我們輸入金額和賬號蚂维,點擊提交按鈕戳粒,表單就會提交,給后端的銀行網(wǎng)站服務(wù)發(fā)送請求虫啥。請求的內(nèi)容如下:
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
請求成功后蔚约,你輸入的轉(zhuǎn)賬金額100元,將轉(zhuǎn)賬到9876這個賬戶當中涂籽。假如你完成轉(zhuǎn)賬操作后苹祟,并沒有退出登錄,而是訪問了一個惡意網(wǎng)站评雌,這時树枫,你的銀行網(wǎng)站www.a-bank.com
還是處于登錄狀態(tài),而這個惡意網(wǎng)站中景东,出現(xiàn)了一個帶有”贏錢“字樣的按鈕砂轻,這個”贏錢“字樣的按鈕后面是一個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>
我們可以看到這個表單中斤吐,金額和賬戶都是隱藏的搔涝,在網(wǎng)頁上只看到了一個贏錢按鈕厨喂。這時,你忍不住沖動体谒,點了一個”贏錢“按鈕杯聚,這時,將會發(fā)生什么操作呢抒痒?我們仔細看一下上面表單中的action
寫的是什么幌绍?action
寫的是你的銀行網(wǎng)站的轉(zhuǎn)賬請求接口。你點了一下贏錢按鈕故响,在這個不正規(guī)的網(wǎng)站中傀广,將會發(fā)送https://www.a-bank.com/transfer
這個請求,在發(fā)送這個請求的時候彩届,會自動帶上www.a-bank.com
的cookie伪冰,不要問我為什么是這樣,這是瀏覽器的標準樟蠕,標準就是這樣規(guī)定的贮聂。銀行后臺接到這個請求后,首先要判斷用戶是否登錄寨辩,由于攜帶了cookie吓懈,是登錄的,會繼續(xù)執(zhí)行后面的轉(zhuǎn)賬流程靡狞,最后轉(zhuǎn)賬成功耻警。你點了一下”贏錢“按鈕,自己沒有賺到錢甸怕,而是給黑客轉(zhuǎn)賬了100元甘穿。
這就是CSRF攻擊的原理,在其他的網(wǎng)站向你的網(wǎng)站發(fā)送請求梢杭,如果你的網(wǎng)站中的用戶沒有退出登錄温兼,而發(fā)送的請求又是一些敏感的操作請求,比如:轉(zhuǎn)賬武契,那么將會給你的網(wǎng)站的用戶帶來巨大的損失妨托。
CSRF的防御
我們知道了CSRF攻擊的原理,就可以做針對性的防御了吝羞。CSRF的防御可以從兩個方面考慮兰伤,一個是后臺接口層做防御;另一個則是在前端做防御钧排,這種不同源的請求敦腔,不可以帶cookie。
后端防御CSRF
我們先聊聊后端的防御恨溜,后端防御主要是區(qū)分哪些請求是惡意請求符衔,哪些請求是自己網(wǎng)站的請求找前。區(qū)分惡意請求的方式有很多,在這里給大家介紹兩種吧判族。
第一種躺盛,CSRF Token的方式。這種方式是在表單頁面生成一個隨機數(shù),這個隨機數(shù)一定要后端生成,并且對這個隨機數(shù)進行存儲白筹。在前端頁面中宰啦,對這個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是后臺生成的。當用戶點擊轉(zhuǎn)賬按鈕時各薇,會給銀行的后臺發(fā)送請求,請求中包含_csrf
參數(shù)君躺,如下:
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
的值是否存在,如果存在則是自己網(wǎng)站的請求棕叫,進行后續(xù)的流程朝抖;如果不存在,則是惡意網(wǎng)站的請求谍珊,直接忽略。
第二種急侥,通過請求頭中的referer
字段判斷請求的來源砌滞。每一個發(fā)送給后端的請求,在請求頭中都會包含一個referer
字段坏怪,這個字段標識著請求的來源贝润。如果請求是從銀行網(wǎng)站發(fā)出的,這個字段會是銀行網(wǎng)站轉(zhuǎn)賬頁的鏈接铝宵,比如:https://www.a-bank.com/transfer-view
打掘;如果是從惡意網(wǎng)站發(fā)出的,那么referer
字段一定不會是銀行網(wǎng)站鹏秋。我們在做后端防御時尊蚁,可以先取出每個請求的請求頭中的referer
字段,判斷是不是以自己網(wǎng)站的域名開頭侣夷,在咱們的示例中横朋,如果referer
字段是以https://www.a-bank.com/
開頭的,則繼續(xù)執(zhí)行轉(zhuǎn)賬操作百拓;如果不是琴锭,則直接忽略掉這個請求晰甚。
以上就是后端防御CSRF攻擊的兩種方式,都需要在后端做特殊的處理决帖。當然也可以在前端做處理厕九,怎么做呢?我們接著往下看地回。
前端防御CSRF
既然CSRF攻擊的危害這么大扁远,為什么不能在前端禁止這種請求呢?各大瀏覽器廠商似乎也注意到了這個問題落君,谷歌提出了same-site cookies概念穿香,same-site cookies 是基于 Chrome 和 Mozilla 開發(fā)者花了三年多時間制定的 IETF 標準。它是在原有的Cookie中绎速,新添加了一個SameSite
屬性皮获,它標識著在非同源的請求中,是否可以帶上Cookie纹冤,它可以設(shè)置為3個值洒宝,分別為:
- Strict
- Lax
- None
Cookie中的內(nèi)容為:
POST /transfer HTTP/1.1
Host: www.a-bank.com
Cookie: JSESSIONID=randomid;SameSite=Strict;
Strict
是最嚴格的,它完全禁止在跨站情況下萌京,發(fā)送Cookie雁歌。只有在自己的網(wǎng)站內(nèi)部發(fā)送請求,才會帶上Cookie知残。不過這個規(guī)則過于嚴格靠瞎,會影響用戶的體驗。比如在一個網(wǎng)站中有一個鏈接求妹,這個鏈接連接到了GitHub上乏盐,由于SameSite設(shè)置為Strict,跳轉(zhuǎn)到GitHub后制恍,GitHub總是未登錄狀態(tài)父能。
Lax
的規(guī)則稍稍放寬了些,大部分跨站的請求也不會帶上Cookie净神,但是一些導(dǎo)航的Get請求會帶上Cookie何吝,如下:
請求類型 | 示例 | Lax情況 |
---|---|---|
鏈接 | <a href="..."></a> |
發(fā)送 Cookie |
預(yù)加載 | <link rel="prerender" href="..."/> |
發(fā)送 Cookie |
GET 表單 | <form method="GET" action="..."> |
發(fā)送 Cookie |
POST 表單 | <form method="POST" action="..."> |
不發(fā)送 |
iframe | <iframe src="..."></iframe> |
不發(fā)送 |
AJAX | $.get("...") |
不發(fā)送 |
Image | <img src="..."> |
不發(fā)送 |
上面的表格就是SameSite設(shè)置為Lax的時候,Cookie的發(fā)送情況鹃唯。
None就是關(guān)閉SameSite屬性爱榕,所有的情況下都發(fā)送Cookie。不過SameSite設(shè)置None坡慌,還要同時設(shè)置Cookie的Secure屬性呆细,否則是不生效的。
以上就是在前端通過Cookie的SameSite屬性防御CSRF攻擊,不過大家在使用SameSite屬性時絮爷,要注意瀏覽器是否支持SameSite屬性趴酣。
總結(jié)
到這里CSRF的攻和防都已經(jīng)介紹完了,大部分網(wǎng)站都是沒有做CSRF防御的坑夯,小伙伴們有沒有想當黑客的癮岖寞,找?guī)讉€網(wǎng)站搞一下試試吧~~