1. 程式人生 > >CSRF詳解

CSRF詳解

CSRF 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 裏也能找到隨機字符串。

技術分享圖片


所以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>



CSRF詳解