Welcome to kimi's blog

csrf跨站请求伪造

csrf跨站请求伪造

1.csrf介绍

CSRF (Cross-site request forgery,跨站请求伪造)也被称为One Click Attack或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装成受信任用户请求受信任的网站。

2.原理

image

1. 用户打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
2. 用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
3. 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
4. 网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
5. 浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。

钓鱼网站

​ 模仿正规网站,让用户在这网站上做操作,但是操作的结果会影响到用户正常的官方网站账号.其中就是有些投机分子做了手脚

eg: 四六级考试之前需要网上先缴费,你缴完费发现卡里的钱扣了,但是却交大了一个莫名其妙的账户,并不是教育院考试院

模拟钓鱼网站案例:转账
    内部隐藏标签
    
简易真实网站 
<h1>我是真的网站</h1>  http://127.0.0.1:8000/transfer/
<form action="" method="post">
    <p>付款人:
        <input type="text" name="username" >
    </p>
    <p>收款账户:
        <input type="text" name="target_name">
    </p>
        <p>转账金额:
        <input type="text" name="money">
    </p>
    <input type="submit">
</form>

简易假骗网站
<h1>我是假的网站</h1>
<form action="http://127.0.0.1:8000/transfer/" method="post">  # 是朝真实的网址发送请求的
    <p>付款人:
        <input type="text" name="username" >
    </p>
    <p>收款账户:
        <input type="text">  # 因为没有name值,是不会发送的
        <input type="text" name="target_name" value="黑客jason" style="display: none">
        # 利用隐藏的标签,发送真实数据
    </p>
        <p>转账金额:
        <input type="text" name="money">
    </p>
    <input type="submit">
</form>

如何能区分真假网站页面发送的请求呢?

​ 我们引入了csrf校验策略。我们在访问官方网站时,我们需要访问一些核心页面的时候,我们会给核心页面做唯一的标识,当核心页面朝官方网站发送的请求时,官方会根据唯一标识做判断的,没有标识则有可能是恶意网站

csrf相关校验策略

csrf校验策略可以在提交数据的位置添加唯一标识。

方式一:

1.form表单csrf策略
	form表单内部添加{% csrf_token %}
    
 eg:
<h1>我是真的网站</h1>
<form action="" method="post">
        {% csrf_token %}
    <p>付款人:
        <input type="text" name="username" >
    </p>
    <p>收款账户:
        <input type="text" name="target_name">
    </p>
        <p>转账金额:
        <input type="text" name="money">
    </p>
    <input type="submit">
</form>

2.ajax请求csrf策略

方式一:

<script>
    $('#d1').click(function (){
        $.ajax({
            url:'',
            type:'post',
            // 方式1:自己动手取值,较为繁琐
            data:{'csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},
            success:function (args){

            }
        })
    })
</script>

方式二:

<script>
    $('#d1').click(function (){
        $.ajax({
            url:'',
            type:'post',
             // 方式2:利用模板语法自动获取(一定要用引号引起来)
            data:{'csrfmiddlewaretoken':'{{ csrf_token }}','username':'kimi'},
            {#data:{'csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},#}
            success:function (args){

            }
        })
    })
</script>

方式三

// 方式3:直接引入一个js脚本即可(官网提供的)
    
js直接复制下面的代码
function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var 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;
}
var csrftoken = getCookie('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);
    }
  }
});

将上述的文件配置到项目的静态文件中,在html页面上通过导入该文件即可自动帮我们解决ajax提交post数据时校验csrf_token的问题,导入配置文件必须先导入jQuery,因为上述文件的内容时基于jQuery来实现的

csrf相关装饰器

csrf是一个唯一标识,只有在进行第二次请求的时候才会去校验(如get请求就不会校验),校验的位置在setting里面,就是post请求注释掉的哪个位置:

'django.middleware.csrf.CsrfViewMiddleware'

当我们有不一样的要求时:

整个django项目都校验csrf 但是某些个视图函数\类不想校验
整个django项目都不校验csrf 但是某些个视图函数\类需要校验

FBV添加装饰器的方式

​ 与正常函数添加装饰器一致

from django.views.decorators.csrf import csrf_exempt,csrf_protect
# @csrf_exempt  # 全局csrf校验时,该装饰器作用是不校验此函数
@csrf_protect # 注释掉csrf,该装饰器还是会校验此函数
def transfer_func(request):pass

CBV添加装饰器的多种方式

​ 与正常情况不一致,需要引入method_decorator模块

# 引入模块
from django import views
from django.utils.decorators import method_decorator

# @method_decorator(csrf_protect, name='post')  # 方式2:单独生效
class MyView(views.View):
    @method_decorator(csrf_protect)  # 方式3:整个类中生效
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    # @method_decorator(csrf_protect)  # 方式1:单独生效
    def post(self, request):
        return HttpResponse('from cbv post view')

注意:有一个装饰器是特例,只能由一种添加方法>>>:csrf_exempt,只有在dispatch方法添加才会生效

from django.views.decorators.csrf import csrf_exempt
class MyView(views.View):
    @method_decorator(csrf_exempt)  # csrf_exempt只能通过第三种方式全类取消csrf校验
    def dispatch(request):
        return super().dispatch(request, *args, **kwargs)
    def get(request):pass
    def post(request):pass
posted @ 2022-12-28 18:47  魔女宅急便  阅读(28)  评论(0)    收藏  举报
Title