• Django—XSS及CSRF


    一、XSS

    跨站脚本攻击(Cross Site Scripting),为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。

    1. 工作流程

    a. 恶意用户,在一些公共区域(例如,建议提交表单或消息公共板的输入表单)输入一些文本,这些文本被其它用户看到,但这些文本不仅仅是他们要输入的文本,同时还包括一些可以在客户端执行的脚本。如:

    <script>
       this.document = "*********"; 
      alert(
    'Not Safe'); </script>

    b. 恶意提交这个表单

    c. 其他用户看到这个包括恶意脚本的页面并执行,获取用户的cookie等敏感信息。

     2. 实例-未防范XSS攻击

     1 pinglu = []     # 评论列表
     2 
     3 #提交表单
     4 def commit(request):
     5     if request.method == 'GET':
     6         return render(request, 'commit.html')
     7     else:
     8         com = request.POST.get('commit')
     9         pinglu.append(com)
    10         return redirect('/index.html/')
    11 
    12 
    13 #查看评论页面
    14 def index(request):
    15     return render(request, 'index.html', {'commit': pinglu})
    view.py
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Title</title>
     6 </head>
     7 <body>
     8 <h1>评论</h1>
     9 <form action="/commit.html/" method="post">
    10     <input type="text" name="commit">
    11     <input type="submit" value="sumbit"> {{ error }}
    12 </form>
    13 </body>
    14 </html>
    commit.html
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Title</title>
     6 </head>
     7 <body>
     8 <h1>评论</h1>
     9 {% for item in commit %}
    10     <div>{{ item|safe }}</div>
    11 {#    item后加safe,默认数据安全,django不会做特殊处理#}
    12 {% endfor %}
    13 </body>
    14 </html>
    index.html

    以上实例中,若在commit.html页面输入以下内容并提交:

    <script> alert('恶意脚本') </script>

    则会在index页面执行此行代码,弹出警告框(若包含恶意代码,则会执行)

    3. 防范XSS攻击

    • 最直接的方法就是对于无法控制的输入在html页面内不要使用safe
    {#    <div>{{ item|safe }}</div>#}
        <div>{{ item }}</div>
    • 也可以在views里进行过滤,防止特殊字符提交到数据库或网页内
    def commit(request):
        if request.method == 'GET':
            return render(request, 'commit.html')
        else:
            com = request.POST.get('commit')
            if '<script>' in com:    # 过滤“<script>”关键字,防止恶意代码的提交
                return render(request, 'commit.html', {'error': '此条评论有毒,已被和谐'})
            else:
                pinglu.append(com)
                return redirect('/index.html/')

    •  对于信任的链接或用户输入,使用 mark_safe 标记为安全
    1 def make_safe(request):
    2     from django.utils.safestring import mark_safe
    3     temp = "<a href='http://www.baidu.com'>百度</a>"
    4     #temp = mark_safe(temp)
    5     return render(request, 'make_safe.html', {'temp': temp})
    未使用mark_safe标记的链接

    1 def make_safe(request):
    2     from django.utils.safestring import mark_safe
    3     temp = "<a href='http://www.baidu.com'>百度</a>"
    4     temp = mark_safe(temp)
    5     return render(request, 'make_safe.html', {'temp': temp})
    使用mark_safe标记的安全链接

    二、CSRF

    CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。

    1. 工作流程

    攻击通过在授权用户访问的页面中包含链接或者脚本的方式工作:

     2. django中如何防范

    django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。

    全局:

    • 启用中间件 django.middleware.csrf.CsrfViewMiddleware

     

    局部:

    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    • @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件
    • @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

     3. django中的具体应用方法

    • form表单中添加{csrf_token %}

    若form表单中未添加{csrf_token %},则会报403错误。

    #settings.py中打开MIDDLEWARE设置
    'django.middleware.csrf.CsrfViewMiddleware',
    1 from django.shortcuts import render, HttpResponse, redirect
    2 
    3 def csrf_test(request):
    4     if request.method == 'GET':
    5         return render(request, 'csrf_test.html')
    6     else:
    7         return HttpResponse('ok')
    views.py
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>csef_test</title>
     6 </head>
     7 <body>
     8 <form action="/csrf_test.html/" method="post">
     9     <input type="text" name="user" id="user">
    10     <input type="submit" value="submit">
    11 </form>
    12 
    13 </body>
    14 </html>
    csef_test.html

    修改csef_test.html:

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>csef_test</title>
     6 </head>
     7 <body>
     8 <form action="/csrf_test.html/" method="post">
     9     {% csrf_token %}
    10     <input type="text" name="user" id="user">
    11     <input type="submit" value="submit">
    12 </form>
    13 
    14 </body>
    15 </html>
    form表单中添加{% csrf_token %}

    • 全站禁用,即将settings.py中的 'django.middleware.csrf.CsrfViewMiddleware' 注释掉即可
    • 基于FBV视图的局部禁用和使用
     1 #settings.py
     2 #启用 'django.middleware.csrf.CsrfViewMiddleware',
     3 
     4 
     5 from django.views.decorators.csrf import csrf_exempt
     6 
     7 
     8 @csrf_exempt
     9 def csrf_test(request):
    10     if request.method == 'GET':
    11         return render(request, 'csrf_test.html')
    12     else:
    13         return HttpResponse('ok')
    局部禁用
     1 #settings.py
     2 #禁用 #'django.middleware.csrf.CsrfViewMiddleware',
     3 
     4 
     5 from django.views.decorators.csrf import csrf_protect
     6 
     7 
     8 @csrf_protect
     9 def csrf_test(request):
    10     if request.method == 'GET':
    11         return render(request, 'csrf_test.html')
    12     else:
    13         return HttpResponse('ok')
    局部使用
    •  基于CBV视图的(只能局部使用或禁用类,不能在类方法里局部使用或禁用
     1 #settings.py
     2 #禁用    'django.middleware.csrf.CsrfViewMiddleware',
     3 
     4 
     5 from django.views import View
     6 from django.views.decorators.csrf import csrf_protect
     7 from django.utils.decorators import method_decorator
     8 
     9 
    10 @method_decorator(csrf_protect, name='dispatch')
    11 class Foo(View):
    12     def get(self, request):
    13         pass
    14 
    15     def post(self, request):
    16         pass
    局部使用
     1 #settings.py
     2 #启用    'django.middleware.csrf.CsrfViewMiddleware',
     3 
     4 
     5 from django.views import View
     6 from django.views.decorators.csrf import csrf_exempt
     7 from django.utils.decorators import method_decorator
     8 
     9 
    10 @method_decorator(csrf_exempt, name='dispatch')
    11 class Foo(View):
    12     def get(self, request):
    13         pass
    14 
    15     def post(self, request):
    16         pass
    局部禁用
    • Ajax提交数据时,携带CSRF
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>csef_test</title>
     6 </head>
     7 <body>
     8 <form action="/csrf_test.html/" method="post">
     9     {% csrf_token %}
    10     <input type="text" name="user" id="user">
    11 {#    <input type="submit" value="submit">#}
    12     <a onclick="submitForm();">Ajax提交表单</a>
    13 </form>
    14 
    15 <script src="/static/jquery-3.2.1.js"></script>
    16 <script>
    17     function submitForm() {
    18             var csrf = $("input[name='csrfmiddlewaretoken']").val()
    19             var user = $("#user").val()
    20             $.ajax({
    21                 url: '/csrf_test.html/',
    22                     type: 'POST',
    23                     data: {"user": user, "csrfmiddlewaretoken": csrf},
    24                     success: function (arg) {
    25                             console.log(arg);
    26           }
    27             })
    28   }
    29 </script>
    30 </body>
    31 </html>
    Ajax重写csrf_test,html,csrf数据存放于data中
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>csef_test</title>
     6 </head>
     7 <body>
     8 <form action="/csrf_test.html/" method="post">
     9     {% csrf_token %}
    10     <input type="text" name="user" id="user">
    11 {#    <input type="submit" value="submit">#}
    12     <a onclick="submitForm();">Ajax提交表单</a>
    13 </form>
    14 
    15 <script src="/static/jquery-3.2.1.js"></script>
    16 {#专门处理cookie的插件,提取cookie字符串#}
    17 <script src="/static/jquery.cookie.js"></script>
    18 
    19 {#csrf数据放于data中#}
    20 {#<script>#}
    21 {#    function submitForm() {#}
    22 {#            var csrf = $("input[name='csrfmiddlewaretoken']").val();#}
    23 {#            var user = $("#user").val();#}
    24 {#            $.ajax({#}
    25 {#                url: '/csrf_test.html/',#}
    26 {#                    type: 'POST',#}
    27 {#                    data: {"user": user, "csrfmiddlewaretoken": csrf},#}
    28 {#                    success: function (arg) {#}
    29 {#                            console.log(arg);#}
    30 {#          }#}
    31 {#            })#}
    32 {#  }#}
    33 {#</script>#}
    34 
    35 {#csrf数据放于请求头中#}
    36 <script>
    37     function submitForm() {
    38             var csrf = $.cookie('csrftoken');
    39             var user = $("#user").val();
    40             $.ajax({
    41                 url: '/csrf_test.html/',
    42                     type: 'POST',
    43                     headers: {'X-CSRFToken': csrf},
    44                     data: {"user": user},
    45                     success: function (arg) {
    46                             console.log(arg);
    47           }
    48             })
    49   }
    50 </script>
    51 
    52 
    53 
    54 </body>
    55 </html>
    Ajax重写csrf_test.html,csrf数据存放于headers中

    注意:{csrf_token %}和cookie中的csrftoken值不一样。

    form表单中的隐藏csrf_token

     cookie中

     

    参考资料:

    1. http://www.cnblogs.com/wupeiqi/articles/5246483.html

    2. http://baike.baidu.com/link?url=zgAGPI1IKiAXCgFLNPVNhmZJI5SP4omb3zHchzPLuivW7QDRDxmAUDt7ZA8aqNlr-YuKKgp4GRmIvXucHHsPkq

    3. http://baike.baidu.com/link?url=TN7axYhM1xYyXqfjjxDglcNEVBKhuEKs-axcWfV8MnDC0om8slvw_V3Cw4RQJyrnJ9yEQvyAu8Ndf8yKzbj0YK

  • 相关阅读:
    从零开始PHP学习
    从零开始PHP学习
    从零开始PHP学习
    从零开始PHP学习
    从零开始PHP学习
    [暂停一天]从零开始PHP学习
    [Laravel 5] 表单验证 Form Requests and Controller Validation
    JQuery 在$(window).load() 事件中 不运行 $(window).resize()
    JS计算两个日期相差几天
    python 学习之Windows 下的编码处理!
  • 原文地址:https://www.cnblogs.com/OldJack/p/7090406.html
Copyright © 2020-2023  润新知