flask中的csrf防禦機制

重灌大師1024發表於2018-07-17

csrf概念

CSRF(Cross-site request forgery)跨站請求偽造,也被稱為“One Click Attack”或者Session Riding,通常縮寫為CSRF或者XSRF,是一種對網站的惡意利用。儘管聽起來像跨站指令碼(XSS),但它與XSS非常不同,XSS利用站點內的信任使用者,而CSRF則通過偽裝來自受信任使用者的請求來利用受信任的網站。與XSS攻擊相比,CSRF攻擊往往不大流行(因此對其進行防範的資源也相當稀少)和難以防範,所以被認為比XSS更具危險性。

攻擊者盜用了你的身份,以你的名義傳送惡意請求,對伺服器來說這個請求是完全合法的,但是卻完成了攻擊者所期望的一個操作,比如以你的名義傳送郵件、發訊息,盜取你的賬號,新增系統管理員,甚至於購買商品、虛擬貨幣轉賬等

csrf攻擊過程

  1. 使用者C開啟瀏覽器,訪問受信任網站A,輸入使用者名稱和密碼請求登入網站A;
  2. 在使用者資訊通過驗證後,網站A產生Cookie資訊並返回給瀏覽器,此時使用者登入網站A成功,可以正常傳送請求到網站A;
  3. 使用者未退出網站A之前,在同一瀏覽器中,開啟一個TAB頁訪問網站B;
  4. 網站B接收到使用者請求後,返回一些攻擊性程式碼,併發出一個請求要求訪問第三方站點A;
  5. 瀏覽器在接收到這些攻擊性程式碼後,根據網站B的請求,在使用者不知情的情況下攜帶Cookie資訊,向網站A發出請求。網站A並不知道該請求其實是由B發起的,所以會根據使用者C的Cookie資訊以C的許可權處理該請求,導致來自網站B的惡意程式碼被執行。
    這裡寫圖片描述

防禦措施
1.開啟csrf保護

在建立app例項的時候
from flask import Flask
from flask_wtf.csrf import CSRFProject
app=Flask(__name__)
#開啟CSRF保護
CSRFProject(app)

2.對頁面HTML加上csrf_token 的標籤

# coding:utf-8

from flask import Blueprint, current_app,make_response
from flask_wtf.csrf import generate_csrf

# 構造一個藍圖物件
html = Blueprint("html", __name__)

@html.route("/<re(r'.*'):file_name>")
def get_html_file(file_name):
    '''提供html檔案'''
    # 根據使用者指明的html檔名,提供相應的html檔案
    if not file_name:
        file_name = "index.html"
    if file_name != "favicon.ico":
        file_name = "html/" + file_name    
    #使用wtf幫助我們生成csrf_token字串
    csrf_token=generate_csrf()
    #為使用者設定cookie值為csrf_token 防止csrf攻擊
    resp=make_response(current_app.send_static_file(file_name))
    resp.set_cookie("csrf_token",csrf_token)
    return resp

3.給post請求的ajax中的headers新增“X-CSRFToken”

 req_json = JSON.stringify(req_data);
        $.ajax({
            url: "/api/v1_0/users",
            type: "post",
            data: req_json,
            contentType: "application/json",//指明向後端傳送的是json格式資料
            dataType: "json",//指明從後端收到的資料是json格式的
            headers:{
                "X-CSRFToken":getCookie("csrf_token")
            },
            success: function (resp) {
                if (resp.errno == 0) {
                    //註冊成功,引導到主頁介面
                    location.href = "/";

                } else {
                    alert(resp.errmsg);
                }
            }
        })

getCookie()函式是定義在js中的功能函式,如下:

function getCookie(name) {
    var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
    return r ? r[1] : undefined;
}

1.在客戶端向後端請求介面資料的時候,後端會往響應中的 cookie 中設定 csrf_token 的值
2.給post請求的ajax中的headers新增“X-CSRFToken”,新增值也是 csrf_token
3.在使用者發起請求以後,會帶上這兩個值向後臺發起請求
4.後端接受到請求,會做以下幾件事:
1.從 cookie中取出 csrf_token
2.從headers中取出csrf_token
3.CSRFProtect會為我們自動比較這兩個值
如果比較之後兩值一樣,那麼代表是正常的請求,如果沒取到或者比較不一樣,代表不是正常的請求,不執行下一步操作
另外不要擔心黑客能拿到csrf_token值,由於同源策略, 黑客是沒辦法獲取使用者瀏覽器中的csrf_token隱藏域,由於瀏覽器安全機制,黑客也沒辦法獲取cookie中的csrf_token。
這裡寫圖片描述

相關文章