Django之XSS&CSRF

一、XSS

1.1 何为XSS?

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

1.2 具体表现

Django默认情况下会阻止比如<script>等违法字段的渲染,比如向前端发送以下代码:

<script> alert('xxxx') </script>

在前端渲染时还是会将以上代码原封不动的进行展示。

此时,我们可以在前端或后端加入相应字段来告诉程序输入字段为安全的。

前端实现

{% for item in comments %}
    <p>{{ item|safe }}</p>   <!-- 在需要展示的数据后面加入“|safe”前端即可认为该数据为安全的,将按照HTML语法进行展示 -->
{% endfor %}

后端实现

def backstage_safe(request):
    '''后端实现安全展示'''
    from django.utils.safestring import mark_safe         #引入mark_safe模块实现安全展示
    temp = "<a href='http://www.baidu.com'>百度</a>"
    newtemp = mark_safe(temp)
    return render(request,'test.html',{'temp':newtemp})

总结:

我们需要慎用safe/mark_safe,在存在可能的注入的情况下坚决不使用,如必须使用,需在后端对关键字进行过滤。

#初始化评论内容为空列表
comments = []
def comment(request):
    '''发表评论'''
    if request.method == 'GET':
        return render(request,'comment.html')
    else:
        content =  request.POST.get('content')
        #后台做关键字过滤
        if 'script' in content:
            return render(request,'comment.html',{'error':'输入错误字段!!!'})
        else:
            comments.append(content)
            return render(request, 'comment.html')

 二 、CSRF

2.1 何为CSRF?

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

2.2 基本应用

主要应用在form表单中,在from表单中加入{% csrf_token %},

<form method="post" action="/csrf1/">
	{% csrf_token %}
	<input type="text" name="content">
	<input type="submit" value="提交" />
</form>	

加入后,在通过GET方式访问网站后,通过页面源代码检查发现{% csrf_token %}实则为:

image

我们可以看到,{% csrf_token %}处生成了input标签且带有一段随机字符串(每次访问都是不同的),如果是{{csrf_token }},则会直接在页面生成一段随机字符串。

于此同时,cookie中也被写入了数据:

image

当我们向后台发送数据时,该随机字符串会一起发送至后端,完成验证。

如果在form表单中未加入{% csrf_token %},访问后提交数据,会出现以下错误:

image

2.3 全站禁用

只需将settings.py中的'django.middleware.csrf.CsrfViewMiddleware', 注释掉即可

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    #'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

2.4 局部禁用

在不需要进行CSRF验证的函数上添加相应装饰器

#'django.middleware.csrf.CsrfViewMiddleware'不被注释
			
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def csrf1(request):

	if request.method == 'GET':
		return render(request,'csrf1.html')
		
	else:
		return HttpResponse('...')	

2.5 局部使用

在需要进行CSRF验证的函数上添加相应装饰器

# 'django.middleware.csrf.CsrfViewMiddleware'被注释
			
from django.views.decorators.csrf import csrf_protect

@csrf_protect
def csrf1(request):

	if request.method == 'GET':
		return render(request,'csrf1.html')
		
	else:
		return HttpResponse('...')	

2.6 CBV中的使用

from django.views import View
from django.utils.decorators import method_decorator

@method_decorator(csrf_protect,name='dispatch')   #name指定加装饰器的方法,如为'dispatch'则所有方法加上装饰器
class Foo(View):
	
	def get(self,request):
		pass

	def post(self,request):
		pass

注:关于SCRF对CBV加装装饰器的问题上,只能在类上进行装饰器加装,不能单独在方法上加装,但可以在继承基类的dispatch()方法上加装:@method_decorator(csrf_exempt)。

2.7 Ajax之SCRF

方式一:SCRF放置在data中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    {% csrf_token %}
	<input id="content" type="text" name="content" >
	<input type="button" id="submit-button" value="Ajax提交">

	<script src="/static/jquery-3.2.1.js"></script>
	<script>
		$("#submit-button").click(function () {
			var csrf = $('input[name="csrfmiddlewaretoken"]').val();
			var content = $('#content').val();
			$.ajax({
				url: '/csrf1/',
				type: 'POST',
				data: { "content":content,'csrfmiddlewaretoken': csrf},   <!-- 不加则会报错,也可通过'{{ csrf_token }}'直接获取 -->
				success:function(arg){
					console.log(arg);
				}
			});
		});
	</script>
</body>
</html>

方式二:SCRF放置在放在请求头中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    {% csrf_token %}
	<input id="content" type="text" name="content" />
	<input type="button" id="submit-button" value="Ajax提交">

    <script src="/static/jquery-3.2.1.js"></script>
    <script src="/static/jquery.cookie.js"></script>      <!-- 有关cookie操作的一个插件 -->
    <script>
        $("#submit-button").click(function (){
            var token = $.cookie('csrftoken');     <!-- 可通过$.cookie('k','v')进行cookie设置 -->
            var content = $('#content').val();
            $.ajax({
                url: '/csrf1/',
                type: 'POST',
                headers:{'X-CSRFToken': token},    <!-- 名称固定为'X-CSRFToken' -->
                data: { "content":content},
                success:function(arg){
                    console.log(arg);
                }
            })
        })
    </script>
</body>
</html>

注:一般POST请求需要带SCRF请求

posted @ 2018-10-11 15:41  Joe1991  阅读(121)  评论(0)    收藏  举报