關於ajax請求的安全,如何避免csrf類似的攻擊?

ajax發出的請求是http,那麼如果類似火狐或者一些工具,能夠偽造請求,這個時候如何保證請求是正常發出,保證安全?

我現在一般的做法是在fun beforesend的時候設置一個由隨機數字+字母的token。這樣會存在安全問題嗎?如果存在,如何改進?如果不存在,有沒有其他更好更多的方式?

望深入回答。


基於 csrf 請求發起方無法拿到被攻擊站點 cookie 這一前提,在用戶登錄之後塞一個 token 到 cookie 中,表單提交時把 token 塞到表單提交給後端,後端校驗表單和 cookie 的 token 是否存在且一致,就可以防禦 csrf 攻擊。

實踐上,要對 ajax 庫做一個封裝,或者註冊 beforeAjaxSend 之類的方法,自動把 token 帶進去。支付寶有個叫 request 的 js 庫就是干這個的,上 http://alipay.com 扒一扒就有了。

token 的有效期和 session 一樣就可以了。

用這種方式,token 的生成方不一定必須是伺服器端,瀏覽器端也完全可以,伺服器端生成比較普遍。

另外,伺服器端是不可能確定請求是正常發起,而不是用 firebug/curl 之類的工具發起的。就算你的技術非常非常牛逼,也不行。


題主說的用工具偽造請求不屬於csrf範疇,實際上,使用工具偽造請求和正常請求沒有任何區別,沒有任何防範方法。

一般情況下,csrf由img等自動載入標籤或form.submit自動提交表單完成攻擊,它越過了瀏覽器的跨域限制,而ajax跨域正常情況下是瀏覽器所禁止的,ajax並不適用於csrf攻擊。


瀉藥 token 必須是由 server 端下發的才行,前端請求的時候再帶上。


大家說的都很詳細了,我來安利一個東西

JSON Web Token

https://jwt.io/


首先,後端介面本身需要完善的鑒權機制。

其次,對於CSRF攻擊,做好雙身份認證即可,補一個身份識別參數在queryString或者header上即可,不要單單通過cookie來識別身份。

網上提到的各種token,其實就是第二個身份識別碼。


CRSF攻擊的原理看其他回答都已經很清楚了,攻擊的原理主要還是歸結於瀏覽器同源策略限制級別的問題。

瀏覽器同源策略的限制級別

同源策略可以說是瀏覽器安全最最基本的一個保障,所謂同源即是協議、域名和埠一致。

雖然所有瀏覽器都遵守了同源策略,但是各家瀏覽器同源策略的判斷和限制級別卻有些差異,比如IE不把埠納入同源的判定因子。

同源策略最初的定義是A網站設置的cookie,B網站不能訪問該cookie。瀏覽器發起請求時也遵守著這一策略,會根據請求的協議、域名和埠,以及path來決定請求帶上哪些cookie。

對於Cookie,DOM和XMLHttpRequest(ajax)所有瀏覽器都會嚴格遵守同源策略。但是也有例外,如&標籤,&標籤,&標籤等的鏈接會自動載入,更重要的是,表單提交也是可以跨域的。

正是因為部分html標籤和表單提交的可以跨域問題,一些黑產在惡意站點設置了在用戶不感知的情況下發起其他站點的請求,比如用戶登錄了某支付網站後,不經意點開了某惡意站點,該站點自動請求某支付網站(瀏覽器會匹配domain和path自動帶上了cookie憑證),此時就相當於黑產拿到用戶的身份憑證了。

表單提交請求CRSF攻擊防禦

因為表單提交是可以跨域的,所以表單提交的CRSF防禦已經成為站點的標配了。原理也很簡單,因為表單的提交都要分為兩個階段,表單渲染和表單提交。檢查表單提交的表單是否是自己的伺服器渲染的即可。(就好像黑產放了一個看起來一模一樣的ATM機,讓用戶插入銀行卡輸入密碼,伺服器端需要校驗這個ATM機是不是可信的)。

Ajax請求CRSF攻擊防禦

回到題主的問題,一般Ajax請求都認為是XMLHttpRequest請求,但是廣義上也有人會把Jsonp請求也放在Ajax請求的範疇。暫且不去談概念的問題,反正原理是不一樣的。

對於XMLHttpRequest請求,瀏覽器都是嚴格遵守同源策略限制的,看起來是無傷的。但是對於有一些請求,攻擊者其實是可以通過模擬表單進行提交的。

對於Jsonp請求,主要是利用&標籤載入javascript函數回調實現的,這個瀏覽器是不會進行同源限制的。

與表單提交不一樣,XMLHttpRequest請求和Jsonp請求都是一步的完成的,而且可以連續重複的進行請求。

但是通常有一個規律:在執行這兩種請求時,我們都會先向伺服器get請求載入頁面,不可能用戶一來,就對伺服器發起XMLHttpRequest請求和Jsonp請求。基於這一點,可以使用cookie來存儲可信令牌,可信令牌的生命周期可以跟session同步。

可能有人會問,通過在cookie上設置令牌token看起來是一個殺手鐧啊,表單提交也是可以這樣做的。的確如此,但是設置表單級別的令牌token可以起到另外一種作用,就是防表單重複提交,只要伺服器保證每次請求的表單的令牌都不一樣即可。

以上介紹的防禦CRSF攻擊的方案,都可以概括為:頒發一個令牌token,放在嚴格遵循同源策略的媒介上來識別請求是否可信

對於表單提交來說,令牌token存儲在表單DOM上,其他站點無法獲取到。

對於Ajax提交來說,令牌token存儲在Cookie上,其他站點無法獲取到。

當然,其他答案中也提到了另外一種方案,檢查請求的referer是否可信,伺服器端只需要配置一個referer白名單即可,也是一種非常好的解決方案。


  • 首先我們科普一下 csrf到底是什麼樣子的攻擊

一個網站用戶Bob可能正在瀏覽聊天論壇,而同時另一個用戶Alice也在此論壇中,並且後者剛剛發布了一個具有Bob銀行鏈接的圖片消息。設想一下,Alice編寫了一個在Bob的銀行站點上進行取款的form提交的鏈接,並將此鏈接作為圖片tag。如果Bob的銀行在cookie中保存他的授權信息,並且此cookie沒有過期,那麼當Bob的瀏覽器嘗試裝載圖片時將提交這個取款form和他的cookie,這樣在沒經Bob同意的情況下便授權了這次事務。

  • 然後我們來看看題主的問題:

關於ajax請求的安全,如何避免csrf類似的攻擊?

ajax發出的請求是http,那麼如果類似火狐或者一些工具,能夠偽造請求,這個時候如何保證請求是正常發出,保證安全?

我現在一般的做法是在fun beforesend的時候設置一個由隨機數字+字母的token。這樣會存在安全問題嗎?如果存在,如何改進?如果不存在,有沒有其他更好更多的方式?

首先,csrf攻擊不需要火狐或者一些工具來實現。偽造請求?你連cookie都沒有你怎麼偽造。攻擊者始終拿不到cookie的,只是用戶替你執行了你編造的請求罷了。

然後,token是通用的解決方法,基本能解決問題。哪怕發送了請求,cookie證明了用戶的登陸狀態也不能直接授權進行操作,所以前端就要和後端約定一個規則。

這個規則沒必要太複雜。要注意一些實現細節,比如如果用戶在一個站點上同時打開了兩個不同的表單,CSRF保護措施不應該影響到他對任何錶單的提交。考慮一下如果每次表單被裝入時站點生成一個偽隨機值來覆蓋以前的偽隨機值將會發生什麼情況:用戶只能成功地提交他最後打開的表單,因為所有其他的表單都含有非法的偽隨機值。必須小心操作以確保CSRF保護措施不會影響選項卡式的瀏覽或者利用多個瀏覽器窗口瀏覽一個站點。

參考:淺談CSRF攻擊方式


按照防禦CSRF攻擊的方法來回答好了:

1、加token,隱藏表單,伺服器驗證,注意token的時效性

2、驗證referer,注意一些外域flash請求是不帶referer的,如果同域下也有flash,並且有些鏈接為了這些flash並沒有校驗referer,這就給外部referer跨域請求開了通道。

3、用js在cookie中設置一個臨時欄位,伺服器去做校驗,如果是單域名站點,可以使用


第一,理解csrf tokenn設計的初衷,本質是防止參數預測,只要防止參數預測不管你咋用都是對的。藏cookie藏時間戳,藏哪裡都隨便你,放在自定義的頭裡也可以。

第二,只要你同域下有一個xss,那你這個token也就可以讀取,然後拼湊一個請求,這時候這個就失效了,千里之提毀於蟻穴哈哈哈,不過你可以把token寫cookie然後用httponly,雖然還是有辦法讀取到cookie但是門檻已經很高了


在Chrome51中出現的Same Origin Cookies有望解決這個棘手的問題。


ajax 受SOP 限制,無法跨域。除非人為設置。


瀉藥。

對於這塊研究不多,對於一般而言的請求,驗證用戶信息就夠了,也就是驗證 session 里的用戶信息及用對應的許可權(是否有許可權訪問該介面)。

對於安全性比較高或者說無法驗證用戶的情況,一般的做法是生成隨機碼,同時將隨機碼存入session,然後發送請求的時候帶上這個隨機碼,後端則通過 session 驗證這個隨機碼,這樣就可以保證求情來源的可控(和你說到的類似)。


推薦閱讀:

Aspera技術如何實現原來需要傳26小時的24GB文檔做到只需30秒?
為什麼fiddler無法抓到訊飛語音輸入的請求?
怎麼瀏覽器打開圖片的url默認是下載?
服務端處理耗時請求(發郵件/壓縮圖片/抓取網頁)一般有幾種方法?

TAG:JavaScript | 網路安全 | Ajax | HTTP | CSRF |