Django—XSS及CSRF

 

一、XSS

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

1. 工作流程

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


   this.document = "*********"; 
  alert('Not Safe');

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 
 2 
 3 
 4     
 5     
 6 
 7 
 8

评论


 9
10 11 {{ error }} 12 13 14 commit.html

 1 
 2 
 3 
 4     
 5     
 6 
 7 
 8

评论


 9 {% for item in commit %}
10
{{ item|safe }}

11 {#    item后加safe,默认数据安全,django不会做特殊处理#}
12 {% endfor %}
13 
14 

index.html

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

 alert(123) 

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

3. 防范XSS攻击

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

二、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 
 2 
 3 
 4     
 5     
 6 
 7 
 8
9 10 11 12 13 14 csef_test.html

修改csef_test.html:


 1 
 2 
 3 
 4     
 5     
 6 
 7 
 8
9 {% csrf_token %} 10 11 12 13 14 15 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 
 2 
 3 
 4     
 5     
 6 
 7 
 8
9 {% csrf_token %} 10 11 {# #} 12 Ajax提交表单 13 14 15 16 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 30 31 Ajax重写csrf_test,htmlcsrf数据存放于data

 1 
 2 
 3 
 4     
 5     
 6 
 7 
 8
9 {% csrf_token %} 10 11 {# #} 12 Ajax提交表单 13 14 15 16 {#专门处理cookie的插件,提取cookie字符串#} 17 18 19 {#csrf数据放于data中#} 20 {##} 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 {##} 34 35 {#csrf数据放于请求头中#} 36 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 51 52 53 54 55 Ajax重写csrf_test.htmlcsrf数据存放于headers

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

form表单中的隐藏csrf_token

cookie中

posted @ 2018-06-07 17:55  诛仙物语  阅读(257)  评论(0编辑  收藏  举报