1. 程式人生 > >django-csrf攻擊

django-csrf攻擊

電商網站 動態 ava ood 過程 目標 解析 err 解決

原理

csrf(Cross Site Request Forgery, 跨站域請求偽造:CSRF 攻擊允許惡意用戶在另一個用戶不知情或者未同意的情況下,以他的身份執
行操作。

CSRF 攻擊是黑客借助受害者的 cookie 騙取服務器的信任,但是黑客並不能拿到 cookie,也看不到 cookie 的內容。另外,對於服務器返回的結果,由於瀏覽器同源策略的限制,黑客也無法進行解析。因此,黑客無法從返回的結果中得到任何東西,他所能做的就是給服務器發送請求,以執行請求中所描述的命令,在服務器端直接改變數據的值,而非竊取服務器中的數據 。黑客無法獲取cookie和session值更無法進行解析。

過程:

假如用戶A在某電商網站註冊過並且用戶本地瀏覽器又存在網站服務端頒發給自己的通行證(也就是cookie),那麽對於用戶A來說自己訪問網站並且提交請求購買商品都是暢通無阻,不需要身份驗證。但是黑客B想要利用A的賬戶給自己買東西,用戶B直接訪問電商網站當然無法實現這一目的,原因是B沒有A的通行證,想要利用A的賬戶在訪問網站時又不知道A的密碼。那麽B自己建造了一個黑客網站,這個黑客網站中存在跳轉向目標電商網站的黑客url鏈接,url鏈接又包含了用戶的請求(假如是A購買了一個iphone X發給某地址,當然這是B想要的地址)。當用戶訪問黑客網站時,點擊黑客鏈接時,目標網站就會接受到請求,由於該請求是A的瀏覽器發出的,所以又包含A的cookie,服務端就會將一個iphone X發往B的地址,那麽黑客B的目的就達到了。所以在csrf中黑客B並不知道A的cookie,只是間接利用了cookie,拿著A的通行證瞞過目標網站,實現自己目的。

實現的方式:

  1. 黑客網頁存在指向目標站點的鏈接,直接跳轉

  2. 黑客網頁存在技術分享圖片,其中xxx就是指向目標站點的鏈接,並且包含請求,例如 src=”http://goumai.example/withdraw?account=A&goods=iphonex&for=B ”

  3. 黑客網頁包含動態加載的JavaScript,存在轉向目標站點的動作。

防禦策略:在請求地址中添加 token 並驗證

CSRF 攻擊之所以能夠成功,是因為黑客可以完全偽造用戶的請求,該請求中所有的用戶驗證信息都是存在於 cookie 中,因此黑客可以在不知道這些驗證信息的情況下直接利用用戶自己的 cookie 來通過安全驗證。要抵禦 CSRF,關鍵在於在請求中放入黑客所不能偽造的信息

,並且該信息不存在於 cookie 之中。可以在 HTTP 請求中以參數的形式加入一個隨機產生的 token,並在服務器端建立一個攔截器(中間件:django.middleware.csrf.CsrfViewMiddleware)來驗證這個 token,如果請求中沒有 token 或者 token 內容不正確,則認為可能是 CSRF 攻擊而拒絕該請求。

token 可以在用戶登陸後產生並放於 session 之中,然後在每次請求時把 token 從 session 中拿出,與請求中的 token 進行比對,但這種方法的難點在於如何把 token 以參數的形式加入請求。對於 GET 請求,token 將附在請求地址之後,這樣 URL 就變成 http://url?csrftoken=tokenvalue。 而對於 POST 請求來說,要在 form 的最後加上‘ ‘,這樣就把 token 以參數的形式加入請求了。但是,在一個網站中,可以接受請求的地方非常多,要對於每一個請求都加上 token 是很麻煩的,並且很容易漏掉,通常使用的方法就是在每次頁面加載時,使用 javascript 遍歷整個 dom 樹,對於 dom 中所有的 a 和 form 標簽後加入 token。這樣可以解決大部分的請求,但是對於在頁面加載之後動態生成的 html 代碼,這種方法就沒有作用,還需要程序員在編碼時手動添加 token。dom對象以及cookie

兩種防禦csrf的方式

1、form表單提交

<form action="/login/" method="POST">
    {#         {{ csrf_token }}#}
{{ csrf_token }}表示隨機字符串交給服務端通過測試並隱藏在頁面的input中
         {% csrf_token %}
{#         隨機字符串隱藏在頁面中的<input>中發送給後臺#}
         <input type="text" name="user"/>
         <input type="text" name="pwd"/>
         <input type="submit" value="提交"/>
</form>

2、ajax提交

$(function () {

{#            在Ajax請求前設置請求頭#}
            $.ajaxSetup({
                beforeSend: function (xhr, settings) {
                    xhr.setRequestHeader('X-CSRFtoken', $.cookie('csrftoken'));
                }
            });

            $('#btn').click(function () {
                $.ajax({

{#                    關於ajax中data#}
{#                    第一個data就是發送給服務端的數據,success裏面的data是服務器返回的數據#}

                    url: '/login',
                    type:'POST',
                    data:{'user':'root', "pwd":'123'},
                    headers:{'X-CSRFtoken': $.cookie('csrftoken')},
{#                    請求頭中不能出現下劃線否則視為非法#}
                    success: function (data) {
                        console.log(data);
                        alert(data);
                    },
                    error: function (data) {
                      alert(data);
                    }
                    }
                )
            })
        });

對於Ajax提交時通常還需要對提交請請求的方法進行判斷如果是get,head,options,trace方法,不會改變數據,CSRF 攻擊
無法解析服務器返回的結果,無需保護。則不需要進行攜帶csrftoken所以請求前需要進行判斷、

<script type="text/javascript">
        var csrftoken = $.cookie('csrftoken');

        function csrfSafeMethod(method) {
            // these HTTP methods do not require CSRF protection
            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
        }
        $.ajaxSetup({
            beforeSend: function(xhr, settings) {
                if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                    xhr.setRequestHeader("X-CSRFToken", csrftoken);
                }
            }
        });
        function Do(){

            $.ajax({
                url:"/app01/test/",
                data:{id:1},
                type:'POST',
                success:function(data){
                    console.log(data);
                }
            });

        }
</script>

其他攻擊

xss攻擊

sql註入

django-csrf攻擊