目錄
啥是CSRF攻擊
CSRF(Cross-site request forgery)跨站請求偽造,CSRF通過偽裝來自受信任用戶的請求來利用受信任的網站,也就是說,請求是攻擊者偽造了請求,使服務器以為是用戶發起的。CSRF通常由以下流程構成:
以下引自(https://juejin.im/post/5bc009996fb9a05d0a055192):
- 受害者登錄a.com,並保留了登錄憑證(Cookie)。
- 攻擊者引誘受害者訪問了b.com。
- b.com 向 a.com 發送了一個請求:a.com/act=xx。瀏覽器會…
- a.com接收到請求后,對請求進行驗證,並確認是受害者的憑證,誤以為是受害者自己發送的請求。
- a.com以受害者的名義執行了act=xx。
- 攻擊完成,攻擊者在受害者不知情的情況下,冒充受害者,讓a.com執行了自己定義的操作
總結來說,攻擊者沒有竊取你的登錄信息,但是利用你的登錄信息,冒充你或者在你不知情的情況下發起了一個請求。這通常也不是你希望的。接下來我們寫一個CSRF攻擊小例子。
寫一個CSRF攻擊
假設我是攻擊者,我寫了一篇博客,然后希望收到更多的贊(這個動機似乎不足以搞個CSRF),但是博文質量不是很高。於是我首先去研究了點👍的API,以及它所需的字段:
url: mvc/vote/VoteBlogPost.aspx
postData
"{\"blogApp\":\"imgss\",\"postId\":9700617,\"voteType\":\"Digg\",\"isAbandoned\":false}"
接下來我寫了一個網頁,並模擬這個post請求
<form action="https://www.cnblogs.com/mvc/vote/VoteBlogPost.aspx" method="POST">
<input type="hidden" name="blogApp" value="imgss" />
<input type="hidden" name="postId" value="9700617" />
<input type="hidden" name="voteType" value="Digg" />
<input type="hidden" name="isAbandoned" value="false" />
</form>
<script> document.forms[0].submit(); </script>
然后部署到服務器上,鏈接在這里:這里有你想要的小電影
如果你點擊了,這時這個頁面就會發起一個post請求,由於你可能登錄了博客園,post時會帶上你的登錄cookie信息,從而就會觸發csrf攻擊,莫名其妙的給這篇文章點了一個贊,(一天后更新:今天獲得5個贊,也不知道是CSRF的功勞,還是我寫的好😂)。
注意:實際點贊(點擊右下角的推薦)的觸發是基於ajax(xhrHttpRequest)實現的,提交的是json數據。但是在實際測試中發現,這個api也支持表單提交。
json的CSRF攻擊似乎有點復雜,如果api不支持跨域,那么ajax請求會因為同源策略的限制而訪問失敗。
如何避免CSRF攻擊
從用戶的角度來說,當然是不要點擊不明鏈接了,語言越刺激越要警惕,如果非要滿足一下好奇心,可以使用不常用的沒什么登錄賬戶的瀏覽器,或者通過無痕窗口、隱身窗口訪問。
從開發人員的角度來說,第一要同源檢測,具體而言就是判斷請求頭里的origin
和refer
字段,origin和refer字段如下所示,可以告訴服務器的請求來源,但是refer卻不是強制的。
Origin: https://juejin.im
Referer: https://juejin.im/post/5bc009996fb9a05d0a055192
其次是設置CSRF token
前面講到CSRF的另一個特征是,攻擊者無法直接竊取到用戶的信息(Cookie,Header,網站內容等),僅僅是冒用Cookie中的信息。
而CSRF攻擊之所以能夠成功,是因為服務器誤把攻擊者發送的請求當成了用戶自己的請求。那么我們可以要求所有的用戶請求都攜帶一個CSRF攻擊者無法獲取到的Token。服務器通過校驗請求是否攜帶正確的Token,來把正常的請求和攻擊的請求區分開,也可以防范CSRF的攻擊。(https://juejin.im/post/5bc009996fb9a05d0a055192)
這個就不詳細講了,大家可以參考掘金美團技術團隊的那篇文章。(完)
參考: