天天看點

[ Security ] WEB安全(二)之圖解 CSRF 注入

CSRF 攻擊的原理

CSRF 攻擊,英文全稱就是 Cross Site Request Forgy,意思就是跨站僞造請求。CSRF 簡單來說就是利用站點對使用者的信任資訊僞造一個使用者的請求,去請求這個信任站點進行非法的操作。

CSRF 的破壞力主要是看被攻擊者的權限,如果被攻擊者權限非常小那最多也就是影響一些使用者的資料或者功能,比如在某個地方插入了一些亂碼或者是插入一些非法的圖檔。如果被攻擊的權限是管理者權限,那影響将會很大甚至直接影響到了整個站點的安全,比如盜取使用者資料庫或者是觸發交易邏輯進而導緻資金損失。

CSRF 的危險性要比 XSS 更高一些,因為他會更加的難以防範。

在今天的浏覽器,都是可以支援多開視窗的,既然支援多開就說明可能會同時的登入了幾個站點,那麼,這個就可能有 CSRF 的攻擊風險。這裡有個小技巧,就是不要隻使用一個浏覽器,用一個浏覽器專門用于通路重要網站,另一個浏覽器專門用于網上沖浪,這樣就可以避免 session 共享的問題。換句話說就是再開個小号去 “ 玩 ”。

CSRF 攻擊原理

他的攻擊原理就是将一段非法的連接配接位址以某種方法發送給使用者,誘因使用者點選,而點選這個是會向另一個接口發送請求資訊,在不知不覺中就暗中進行了一些敏感的操作。

攻擊流程如下圖:

[ Security ] WEB安全(二)之圖解 CSRF 注入
  • A/B:A 和 B 表示是正常的使用者和站點之間的通信。
  • C: 黑客發出了帶有惡意腳本的連結僞裝成一個圖檔或者文字。
  • D:使用者被這個圖檔或者文字所吸引,同時對她進行點選操作。
  • E:在點選了這個連結之後,惡意腳本執行請求了 website 站點僞造使用者請求。

CSRF 攻擊的特點

CSRF 的攻擊最大的特點就是利用了使用者的身份資訊,在使用者毫不知覺的情況下進行一些非法的操作。但是這裡面也有個前提,即将被攻擊的網站是需要使用者登入過的,也就是使用者已經有了登入資訊的情況下。

CSRF 攻擊的防禦

same-site

same-site,顧名思義就是隻允許統一站點的 cookie ,話句話說就是禁止第三方的 cookie 進而減少安全風險。他的處理方法就是在設定 cookie 的時候加上 same-site 這個屬性 。

這個方法是可以防禦 CSRF ,但是,same-site 這個方法有相容性問題,這個屬性最開始是在谷歌浏覽器 51 版本上新增的,能夠支援的比較好的就是谷歌浏覽器自己。是以,并不是一個比較好的解決 CSRF 攻擊的問題。

referee

referer 是 HTTP 協定的請求頭,裡面的資訊是請求源位址資訊,而需要做的就是驗證 referer 的位址是不是目前域,如果不是就拒絕,意思就是禁止第三方網站的請求,進而阻止 CSRF 的攻擊。

這個地方需要注意一點的是,對于 referer 的校驗最好是使用正則比較嚴謹的方法校驗,是因為 referer 是一段網址,判斷是否來自某個域就是判斷時候包含某個域名資訊,例如:

referer = "www.ke.com";
referer.indexOf('www.qq.com') > 0 
// false           

複制

上面的方法顯然是可以,但是如果位址稍微變化一下

referer = "www.ke.com?id=www.qq.com";
referer.indexOf('www.qq.com') > 0 
// ture           

複制

很明顯這樣就出問題了,是以必須使用正則校驗的方法驗證:

let referer = "www.ke.com?id=www.qq.com";
let Reg = /^https?:\/\/www\.qq\.com/;  
Reg.test(referer) 
// false           

複制

這樣才能正确的校驗 referer ,但是有些場景下的跳轉是不帶有 referer 的或者是這個 referer 是允許發送的等等情況綜合,一般也不以 referer 來校驗是否合法請求。除非有些業務是純内部或者是使用範圍比較小的,那就可以考慮用這個方法。

驗證碼

前面提到了 CSRF 的攻擊特點就是利用使用者的登入資訊在使用者完全不知覺的情況下進行非法操作。而使用驗證碼這個東西的目的就是要驗證該操作是否是使用者操作。

以圖形驗證碼為例,他的實作原理就是前端引入 SDK 生成一段規則,然後使用者通過某種方法去進行操作,操作完成之後若符合操作條件就根據規則生成一段驗證碼。

這一段的驗證碼是會在下一次的請求中帶上一起發給後端。後端在接收到請求的第一件事就是校驗驗證碼的正确性。如果比對則說明操作合法向下執行,若不比對或者為空,就說明這是一個非法操作直接攔截。流程如圖:

[ Security ] WEB安全(二)之圖解 CSRF 注入
  • A:使用者通路 website 發送請求
  • B:在某種條件下觸發了圖形驗證
  • C:在前端界面完成指定的校驗操作
  • D:下一次請求請求中帶上驗證碼給伺服器校驗

另外一個注意點時,上面說的在某種條件下出發是因為圖形驗證碼一般不會每次都出現,因為這個對使用者的體驗是在太差,是以一般都是背景有自己的一套判斷規則,比如這個ip請求的比較頻繁或者是多次請求登入,這個時候判斷為異常操作觸發驗證碼邏輯。

我記得以前做 h5 活動的時候,其中一個活動中頁面有個按鈕涉及到了給作品加分的操作,按理說應該給這個按鈕設定一個最進階别的圖形校驗,但是産品同學卻建議不要設定的太高。因為加上了最進階别的圖形校驗就意味着出現圖形校驗的機率變高,流失率也就越大。

在大廠裡這個驗證碼元件這個東西都不需要 WEB 端的同學去開發,是由一些公司級基建相關的部門進行研發,比如像騰訊最為常見的 WEB QQ登入,登入時有時候會出現一個要求向右拖動小方塊的過程,這個就是他們自己的防水牆。

如果想要了解一下整個過程,可以去程式員的後花園(npmjs)上面随便找一個,然後本地運作個簡單的伺服器安裝試試。剛剛搜了一下,貌似下面這個還行,emm,雖然沒用過

[ Security ] WEB安全(二)之圖解 CSRF 注入

token

token 這個方法就會比圖型驗證碼的體驗效果要好一點,首先,它由後端生成一段加密過後的字元串,之後将這個字元串寫進 cookie 和頁面的某個位置表單域或者http頭自己定義的屬性裡面,在送出資料的時候會從頁面的某個位置取出一起随 form 和 cookie 到達背景,背景把這兩段資料進行對比,通過了才算合法操作。

也可以說是在使用者登入驗證通過後,由伺服器下發的 token 是一個身份令牌,這個是給使用者的一個身份标記。每一次的請求都是會帶上這個ID。

需要注意的就是,這兩段資料缺一不可,必須兩個都同時存在,缺少某一個都會認為是非法操作。

這個方法看似就解決了這個問題,但是再考慮一種情況,浏覽器是可以多開的,如果浏覽器同時多開了相同的頁面,那麼這幾個頁面隻有最新的那個 token 才是有效的,因為他們會把之前的覆寫。

有更簡單的方法,那個就是 CSRF Guard ,可能現在會有更好的方法,這個就不在這個進行描述了。

以上就是關于 CSRF 的介紹。

免辣的毛血旺和加糖的冰美式都是沒有靈魂的。

[ Security ] WEB安全(二)之圖解 CSRF 注入

歡迎各位小夥伴在我的背景留言 @GavinUI