Backend - Django CSRF 跨域请求伪造

目录

一、CSRF & XSS

(一)CSRF

1. 含义

2. 攻击原理

(1)浏览器特点

(2)攻击方式

(二)XSS

1. 含义

2. 攻击原理

(三)二者区别

二、Django Ajax CSRF 防御

(一)令牌同步模式(Synchronizer Token Pattern,简称 STP )

1. 原理

2. 设置验证

(二)双重 cookie 验证(Double Submit Cookie)

1. 原理

2. 设置验证

(三)X-Csrf-Token 验证(Cookie-to-header token)

1. 原理

2. 设置验证

三、设定 CSRF 验证

(一)settings.py

(二)base.html

1. 针对 ajax 请求,body 里添加{% csrf_token %}

2. 针对 form 表单,form 表单里添加{% csrf_token %}

(三)JS

1. 针对 双重cookie验证

(1)方法1

(2)方法2

2. 针对 X-Csrf-Token验证(Cookie-to-header token)

(1)方法1

3. 针对所有模式的综合验证

(1)写入位置

(2)引入顺序

四、关闭 CSRF 防御功能

1. 方法1:全局禁用

2. 方法2:局部禁用

五、Django CSRF 的控制台 Error

(一)Reason given for failure: CSRF cookie not set.

1. 原因

2. 解决

(二)CSRF verification failed. Request aborted.

1. 原因

(1)原因1:csrf_token 过期

(2)原因2:请求头的 csrf_token 与 session 存储的 token 不匹配

(3)原因3:模板里没有 csrfmiddlewaretoken


一、CSRF & XSS

(一)CSRF

1. 含义

        跨站请求伪造(Cross-site Request Forgery )。

2. 攻击原理

(1)浏览器特点

同个浏览器上,无论是目标网站A还是其他网站B,发送对目标网站A的HTTP请求,都会自动带上目标网站A的cookie,发送给服务端。

(2)攻击方式

同个浏览器上,当用户登录了目标网站(已登录状态),再进入攻击网站,攻击网站发送对目标网站的HTTP请求,则会自动带上“已登录的目标网站”的cookie,就可以进行攻击服务端。

(二)XSS

1. 含义

跨站脚本攻击(Cross-Site Scripting,为了和 CSS 区分,则简称 XSS)。

2. 攻击原理

在目标网站上注入恶意脚本进行攻击。(攻击者提交恶意代码,浏览器再执行恶意代码,篡改了网页)

(三)二者区别

CSRF 是 HTTP 问题,XSS 是代码注入问题。

CSRF需登录目标网站,XSS不用登录。

二、Django Ajax CSRF 防御

采取以下任意一种防御模式即可。

(一)令牌同步模式(Synchronizer Token Pattern,简称 STP )

1. 原理

(1)找到数据库Session的session_csrftoken参数。成功登录网站后,后端随机产生一个csrftoken值,并把该值保存在数据库Session参数中。

(2)找到网页模板的隐藏csrfmiddlewaretoken名的标签。初始化某界面时,前端模板会根据{% csrf_token %}生成一个隐藏的name='csrfmiddlewaretoken'的input标签,存放后端随机生成的csrftoken值。

(3)用户进行 ajax post 请求。post请求时,csrfmiddlewaretoken值会一并放在请求数据(或头信息)中,发送给后端。后端会根据前端csrfmiddlewaretoken的 value值、和服务端数据库 public.django_session 表的 session_csrftoken参数值,判断两个csrf_token解密后的值是否一致。

(4)一致则正常访问,不一致则拒绝访问。

2. 设置验证

在第三点“设定 CSRF 验证”中。

(二)双重 cookie 验证(Double Submit Cookie)

1. 原理

(1)找到浏览器cookie的csrftoken。成功登录网站后,整个浏览器中Cookie的csrftoken属性,存放后端随机生成的csrftoken值。

(2)找到网页模板的隐藏csrfmiddlewaretoken名的标签。初始化某界面时,前端模板会根据{% csrf_token %}生成一个隐藏的 name='csrfmiddlewaretoken' 的input标签,存放后端随机生成的csrftoken值。

(3)用户进行 ajax post 请求。post请求时,csrfmiddlewaretoken值会一并放在请求数据(或头信息)中,发送给后端。后端会根据前端csrfmiddlewaretoken的 value值、和浏览器Cookie的csrftoken值,判断两个csrf_token解密后的值是否一致。

(4)一致则正常访问,不一致则拒绝访问。

2. 设置验证

在第三点“设定 CSRF 验证”中。

(三)X-Csrf-Token 验证(Cookie-to-header token)

1. 原理

(1)确保同源政策。

(2)系统主要使用 JavaScript 进行交互。(因为恶意攻击无法读取 cookie 值,并复制到 HTTP 请求头中)

(3)将 cookie 上的 token 复制到 HTTP 请求头中。

(4)后端验证 HTTP 请求头中 token 的存在和完整性。

(5)X-Csrf-Token 头存在且完整,则正常访问,否则拒绝访问。

2. 设置验证

在第三点“设定 CSRF 验证”中。

三、设定 CSRF 验证

以下主要针对基于 django 使用 ajax 发送 post 请求时的验证。

(一)settings.py

        MIDDLEWARE 里添加 'django.middleware.csrf.CsrfViewMiddleware'  # 设置CSRF检测功能

(二)base.html

1. 针对 ajax 请求,body 里添加{% csrf_token %}

例如:

<body id="body">
    {% csrf_token %}
    <div>{% block content %} {% endblock %}</div>
</body>

渲染后:

<body id="body">
    <input type="hidden" name="csrfmiddlewaretoken" value="vUAPUcghecxAGlraGaFGbikXz3SOPcWtmMtk8o1UQ1PpYYAhxg2cAiAaLyQ9HEY9" />
    <div>插入的子模板</div>
</body>

2. 针对 form 表单,form 表单里添加{% csrf_token %}

因为若在 base.html 中加入 {% csrf_token %},则不在 form 表单的范围内。所以需要在 form 表单里添加。

例如:

<form action="http://127.0.0.1:8080/myApp/test" method=POST>
	{% csrf_token %}
	<input type="submit"/>
</form>

(三)JS

采取以下任意一种验证即可。

1. 针对 双重cookie验证

(1)方法1

        后端将 csrftoken 传到前端(放置在隐藏标签里),发送 post 请求时,请求数据 data 中加上csrftoken,一起发送给后端。

        在 base.html 中的 script 里写上。

$.ajaxSetup({
    data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
});
(2)方法2

        后端将 csrftoken 传到前端(放置在隐藏标签里),发送 post 请求时,请求数据 data 中加上csrftoken。

        在 base.html 中的 script 里写上。

$.ajaxSetup({
    data: {csrfmiddlewaretoken: $('[name="csrfmiddlewaretoken"]').val()},
});

2. 针对 X-Csrf-Token验证(Cookie-to-header token)

(1)方法1

        cookie 中存在 csrftoken,请求头 headers 中加上 csrftoken。

        在 base.html 中的 script 里写上。

        前提:

                ① 引入 jquery-3.1.1.min.js 和 jquery.cookie.js。

                ② 引入顺序:jQuery 库文件必须先于 cookie 文件。

$.ajaxSetup({
    headers:{ "X-CSRFtoken":$.cookie("csrftoken")},
});

3. 针对所有模式的综合验证

(1)写入位置

        前面两个验证的所有方法只能写在html中,不能写到外部js文件。因为 {{ csrf_token }} 渲染在模板上,若以外部文件引入,则不能执行。

        以下代码可以写在外部js文件里,并在 base.html 里引入该js文件。

(2)引入顺序

        该 js 文件的引入顺序必须在 jquery.js 文件之后。

/**
 * 【 Cross Site Request Forgery TOKEN 】
 *  Forbidden 403 - CSRF check with an AJAX POST request in Django.
 */
jQuery(document).ajaxSend(function (event, xhr, settings) {
    function getCookie(name) {
        let cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            let cookies = document.cookie.split(';');
            for (let i = 0; i < cookies.length; i++) {
                let cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) === (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    function sameOrigin(url) {
        // url could be relative or scheme relative or absolute
        let host = document.location.host; // host + port
        let protocol = document.location.protocol;
        let sr_origin = '//' + host;
        let origin = protocol + sr_origin;
        // Allow absolute or scheme relative URLs to same origin
        return (url === origin || url.slice(0, origin.length + 1) === origin + '/') ||
            (url === sr_origin || url.slice(0, sr_origin.length + 1) === sr_origin + '/') ||
            // or any other URL that isn't scheme relative or absolute i.e relative.
            !(/^(\/\/|http:|https:).*/.test(url));
    }
    function safeMethod(method) {
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }
    if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
        xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
    }
});

四、关闭 CSRF 防御功能

不推荐关闭 CSRF 防御功能,因为取消了 CSRF 防御保护。

1. 方法1:全局禁用

        settings.py 中,注释掉 'django.middleware.csrf.CsrfViewMiddleware'

2. 方法2:局部禁用

        views.py 中,导入from django.views.decorators.csrf import csrf_exempt;

        并给要处理 post 数据的函数补充 @csrf_exempt(post 函数有 request 参数)。

五、Django CSRF 的控制台 Error

(一)Reason given for failure: CSRF cookie not set.

1. 原因

        django 中使用 jquery ajax post 数据出现 403 错误。

        即,settings 设置了 Django CSRF 检测功能(防止跨站请求伪造),需要在 django 发送 post 请求时进行字符串验证,但还没有设置 CSRF cookie。

2. 解决

(1)第一种:关闭 CSRF 检测功能

(2)第二种:设定 CSRF 验证

(这两种方式在前面第三点中已介绍)

(二)CSRF verification failed. Request aborted.

1. 原因

(1)原因1:csrf_token 过期

        解决:重新登录(若还未写前端登录,则admin登录)

(2)原因2:请求头的 csrf_token 与 session 存储的 token 不匹配

        解决:清除浏览器缓存; 重新登录

(3)原因3:模板里没有 csrfmiddlewaretoken

        解决:模板中(或表单内)添加 {% csrf_token %} 

  • 24
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值