@淺談CSRF
CSRF的定義
跨站請求僞造(英語:Cross-site request forgery),也被稱爲 one-click attack 或者 session riding,通常縮寫爲 CSRF 或者 XSRF, 是一種挾制用戶在當前已登錄的Web應用程序上執行非本意的操作的攻擊方法。
簡單來說,CSRF是一種劫持受信任用戶向服務器發送非預期請求的攻擊方式。通常情況下,CSRF 攻擊是攻擊者藉助受害者的 Cookie 騙取服務器的信任,可以在受害者毫不知情的情況下以受害者名義僞造請求發送給受攻擊服務器,從而在並未授權的情況下執行在權限保護之下的操作。
在講CSRF之前,先介紹一下網絡請求的基礎知識。
什麼是認證
通俗地講就是驗證當前用戶的身份,證明“你是你自己”。而體現在互聯網中,就是服務器怎麼知道現在發送請求的這個用戶是有權限的用戶,比如用戶有沒有登錄,是通過賬號密碼,還是郵箱手機號?通常來說,我們認爲當你知道某個應用賬號的用戶名密碼,或者說你能收到手機驗證碼的時候,就認爲你是賬號的主人。
什麼是憑證
實現認證和授權的前提是需要一種媒介(證書) 來標記訪問者的身份
在現實生活中,每個人都會有一張專屬的居民身份證,是用於證明持有人身份的一種法定證件。通過身份證,我們可以辦理手機卡/銀行卡/個人貸款/交通出行等等,這就是認證的憑證。
在互聯網應用中,一般網站會有兩種模式,遊客模式和登錄模式。遊客模式下,可以正常瀏覽網站上面的文章,一旦想要點贊/收藏/分享文章,就需要登錄或者註冊賬號。當用戶登錄成功後,服務器會給該用戶使用的瀏覽器頒發一個令牌(token),這個令牌用來表明你的身份,每次瀏覽器發送請求時會帶上這個令牌,就可以使用遊客模式下無法使用的功能。
什麼是 Cookie
- HTTP 是無狀態的協議(對於事務處理沒有記憶能力,每次客戶端和服務端會話完成時,服務端不會保存任何會話信息):每個請求都是完全獨立的,服務端無法確認當前訪問者的身份信息,無法分辨上一次的請求發送者和這一次的發送者是不是同一個人。所以服務器與瀏覽器爲了進行會話跟蹤(知道是誰在訪問我),就必須主動的去維護一個狀態,這個狀態用於告知服務端前後兩個請求是否來自同一瀏覽器。而這個狀態需要通過 cookie 或者 session 去實現。
- cookie 存儲在客戶端:
cookie是服務器發送到用戶瀏覽器並保存在本地的一小塊數據,它會在瀏覽器下次向同一服務器再發起請求時被攜帶併發送到服務器上。 - cookie 是不可跨域的:
每個 cookie都會綁定單一的域名,無法在別的域名下獲取使用,一級域名和二級域名之間是允許共享使用的(靠的是 domain)。
那麼在瞭解到瀏覽器請求的基礎知識之後,我們再來具體描述一下CSRF攻擊是如何工作的。
CSRF攻擊實例
例如,一論壇網站A的發貼是通過 GET 請求訪問的,點擊發貼之後,網站會發送一個請求:
http://www.example.com/postmessage?title=標題&content=內容
這個時候,我們構建一個攻擊網站B,網站中放入一個如下的image標籤,其地址指向剛纔所說的發貼接口
< img src=“http://www.example.com/postmessage?title=哈哈&content=被攻擊了吧”>
當登錄用戶C進入攻擊者B網站的時候,頁面會自動向A網站發送一個請求,這個時候,由於用戶C已經登錄,cookie中攜帶A網站的用戶認證信息,服務器端會認爲這就是用戶C自發發送的請求,這個時候,B網站就在C用戶完全不知情的情況下,利用C用戶的身份,完成了一次發帖請求,這也就是我們所說的CRSF攻擊。
在這個攻擊過程中,攻擊者藉助受害者的 Cookie 騙取服務器的信任,但並不能拿到 Cookie,也看不到 Cookie 的內容。而對於服務器返回的結果,由於瀏覽器同源策略的限制,攻擊者也無法進行解析。因此,攻擊者無法從返回的結果中得到任何東西,他所能做的就是給服務器發送請求,以執行請求中所描述的命令,在服務器端直接改變數據的值,而非竊取服務器中的數據。
如何防範 CSRF 攻擊
-
關鍵操作只接受 POST 請求
-
驗證碼
CSRF攻擊的過程,往往是在用戶不知情的情況下構造網絡請求。所以如果使用驗證碼,那麼每次操作都需要用戶進行互動,從而簡單有效的防禦了CSRF攻擊。
但是如果你在一個網站作出任何舉動都要輸入驗證碼會嚴重影響用戶體驗,所以驗證碼一般只出現在特殊操作裏面,或者在註冊時候使用。
-
檢測 Referer
常見的互聯網頁面與頁面之間是存在聯繫的,比如你在 www.baidu.com 應該是找不到通往www.google.com的鏈接的,再比如你在論壇留言,那麼不管你留言後重定向到哪裏去了,之前的那個網址一定會包含留言的輸入框,這個之前的網址就會保留在新頁面頭文件的Referer 中
通過檢查 Referer 的值,我們就可以判斷這個請求是合法的還是非法的,但是問題出在服務器不是任何時候都能接受到 Referer的值,所以 Referer Check 一般用於監控 CSRF 攻擊的發生,而不用來抵禦攻擊。
-
Token
目前主流的做法是使用 Token 抵禦 CSRF 攻擊。
CSRF 攻擊之所以能夠成功,是因爲攻擊者可以完全僞造用戶的請求,該請求中所有的用戶驗證信息都是存在於 Cookie 中,因此攻擊者可以在不知道這些驗證信息的情況下直接利用用戶自己的 Cookie 來通過安全驗證。要抵禦 CSRF,關鍵在於在請求中放入攻擊者所不能僞造的信息,並且該信息不存在於 Cookie 之中。可以在 HTTP 請求中以參數的形式加入一個隨機產生的 token,並在服務器端建立一個攔截器來驗證這個 token,如果請求中沒有 token 或者 token 內容不正確,則認爲可能是 CSRF 攻擊而拒絕該請求。
具體流程簡介: -
客戶端使用用戶名跟密碼請求登錄
-
服務端收到請求,去驗證用戶名與密碼
-
驗證成功後,服務端會簽發一個 token 並把這個 token 發送給客戶端
-
客戶端收到 token 以後,會把它存儲起來,比如放在 cookie 裏或者 localStorage裏
-
客戶端每次向服務端請求資源的時候需要帶着服務端簽發的 token,把token 放到 HTTP 的 Header 裏,服務端收到請求,然後去驗證客戶端請求裏面帶着的 token ,如果驗證成功,就向客戶端返回請求的數據。
總結
本文主要介紹了CSRF 的攻擊原理和防禦措施。當然,在 Web 安全領域,除了這種常見的CSRF攻擊方式,還存在XSS,SQL 注入等其它攻擊方式,本文不做詳細介紹。最後,總結一下
CSRF攻擊原理:
- 劫持受信任用戶的cookie, 向服務器發送非預期請求的攻擊
CSRF常見防禦措施:
- 驗證碼
- Referer Check
- Token 驗證