CSRF詳解

CSRF

xss***:網站評論裏等允許別人寫js的時候,別人進行的惡意操作。csrf類似。


CSRF的防護通常有兩種方式:

一個是通過Challenge-Response的方式,例如通過Captcha和重新輸入密碼等方式來驗證請求是否僞造,但這會影響用戶體驗,類似銀行付款會採用這樣的方式。

另一種是通過隨機Token的方式,多數Web系統都會採用這種方式,Django也是用的這種。


Token,就是令牌,最大的特點就是隨機性,不可預測。一般***或軟件無法猜測出來。 

那麼,Token有什麼作用?又是什麼原理呢? 


Token一般用在兩個地方: 


1)防止表單重複提交、 2)anti csrf***(跨站點請求僞造)。 

兩者在原理上都是通過session token來實現的。

當客戶端請求頁面時,服務器會生成一個隨機數Token,並且將Token放置到session當中,然後將Token發給客戶端(一般通過構造hidden表單)。下次客戶端提交請求時,Token會隨着表單一起提交到服務器端。 

然後,如果應用於"anti csrf***",則服務器端會對Token值進行驗證,判斷是否和session中的Token值相等,若相等,則可以證明請求有效,不是僞造的。 

不過,如果應用於"防止表單重複提交",服務器端第一次驗證相同過後,會將session中的Token值更新下,若用戶重複提交,第二次的驗證判斷將失敗,因爲用戶提交的表單中的Token沒變,但服務器端session中Token已經改變了。 


上面的session應用相對安全,但也叫繁瑣,同時當多頁面多請求時,必須採用多Token同時生成的方法,這樣佔用更多資源,執行效率會降低。

因此,也可用cookie存儲驗證信息的方法來代替session Token。比如,應對"重複提交"時,當第一次提交後便把已經提交的信息寫到cookie中,當第二次提交時,由於cookie已經有提交記錄,因此第二次提交會失敗。 

不過,cookie存儲有個致命弱點,如果cookie被劫持(xss***很容易得到用戶cookie),那麼又一次gameover。***將直接實現csrf***。 


所以,安全和高效相對的。具體問題具體對待吧。 


此外,要避免"加token但不進行校驗"的情況,在session中增加了token,但服務端沒有對token進行驗證,根本起不到防範的作用。 


還需注意的是,對數據庫有改動的增刪改操作,需要加token驗證,對於查詢操作,一定不要加token,防止***者通過查詢操作獲取token進行csrf***。但並不是這樣***者就無法獲得token,只是增大***成本而已。 


1、csrf原理:

form提交

客戶端get請求時,django會生成隨機字符串給客戶,當客戶端提交form表單的時候,如果沒有隨機字符串,則django不允許,報403錯誤。

加上{% csrf_token %}在html form裏生成了一個

<input type="hidden" name="csrfmiddlewaretoken" value="2DjOYDHPE1zO8A0vQQJFS022UkvkUFTPaFPBEYufVjY0Vru07rzhueJ6zQYvlUva">


在HTML模板中添加 {% csrf_token %}



ajax提交

form提交數據需要帶隨機字符串過去,Ajax提交也需要帶着過去。

客戶端get請求時,django會生成隨機字符串給Cookie,瀏覽器審查元素 –> Network –> Cookies 裏也能找到隨機字符串。

blob.png


所以ajax提交的時候,只需要把cookie裏的隨機字符串拿到,放到請求頭裏面發過去就可以了

    <script>
        $(function(){
            $.ajaxSetup({
                beforeSend: function(xhr,settings){
                    xhr.setRequestHeader('X-CSRFtoken', $.cookie('csrftoken'));
                }
            });  //可以爲之後所有的事件header中加入csrf_token《=====》等價於下一個事件中被註釋掉的行
            
         

            $('#btn1').click(function () {
                $.ajax({
                    url: '/login/',
                    type:"GET",
                    data: {'user': 'root', 'pwd': '123'},
                    // headers: {'X-CSRFtoken': $.cookie('csrftoken')},  //此行
                    success:function(arg){

                    }
                })
            });
        })
    </script>



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章