django⾃⾝安全机制-XSS和csrf
xss攻击:----->web注⼊
定义:
xss跨站脚本攻击(Cross site script,简称xss)是⼀种“HTML注⼊”,由于攻击的脚本多数时候是跨域的,所以称之为“跨域脚本”。
我们常常听到“注⼊”(Injection),如SQL注⼊,那么到底“注⼊”是什么?注⼊本质上就是把输⼊的数据变成可执⾏的程序语句。SQL注⼊是如此,XSS也如此,只不过XSS⼀般注⼊的是恶意的脚本代码,这些脚本代码可以⽤来获取合法⽤户的数据,如Cookie信息。
PS:把⽤户输⼊的数据以安全的形式显⽰,那只能是在页⾯上显⽰字符串。
django框架中给数据标记安全⽅式显⽰(但这种操作是不安全的!):
- 模版页⾯上对拿到的数据后写上safe. ----> {{XXXX|safe}}
- 在后台导⼊模块:from django.utils.safestring import mark_safe
把要传给页⾯的字符串做安全处理 ----> s = mark_safe(s)
实施XSS攻击需要具备两个条件:
⼀、需要向web页⾯注⼊恶意代码;
⼆、这些恶意代码能够被浏览器成功的执⾏。
解决办法:
1、⼀种⽅法是在表单提交或者url参数传递前,对需要的参数进⾏过滤。
2、在后台对从数据库获取的字符串数据进⾏过滤,判断关键字。
3、设置安全机制。
django框架:内部机制默认阻⽌了。它会判定传⼊的字符串是不安全的,就不会渲染⽽以字符串的形式显⽰。如果⼿贱写了safe,那就危险了,若想使⽤safe,那就必须在后台对要渲染的字符串做过滤了。所以在开发的时候,⼀定要慎⽤安全机制。尤其是对⽤户可以提交的并能渲染的内容
- ⽰例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<form method="POST" action="/comment/">
<h4>评论</h4>
<input type="text" name="content"/>
<input type="submit" value="提交"/>{{ error }}
</form>
</body>
</html>
comment.html :评论提交页⾯
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h1>评论内容</h1>
{% for item in msg %}
<div>{{ item|safe }}</div>
{% endfor %}
</body>
</html>
index.html 评论显⽰页⾯:
from django.shortcuts import render
msg = []
def comment(request):
hod == "GET":
return render(request,'comment.html')
else:
v = ('content')
if"script"in v:
return render(request,'comment.html',{'error': '⼩⽐崽⼦还⿊我'})
else:
msg.append(v)
return render(request,'comment.html')
def index(request):
return render(request,'index.html',{'msg':msg})
def test(request):
from django.utils.safestring import mark_safe
temp = "<a href='www.baidu'>百度</a>"
newtemp = mark_safe(temp)
return render(request,'test.html',{'temp':newtemp}
views.py 后台处理
csrf: Cross Site Request Forgery, 跨站请求伪造
什么是 CSRF
CSRF, Cross Site Request Forgery, 跨站点请求伪造。举例来讲,某个恶意的⽹站上有⼀个指向你的⽹站的链接,如果某个⽤户已经登录到你的⽹站上了,那么当这个⽤户点击这个恶意⽹站上的那个链接时,就会向你的⽹站发来⼀个请求,你的⽹站会以为这个请求是⽤户⾃⼰发来的,其实呢,这个请求是那个恶意⽹站伪造的。
经典案例:银⾏转账:
Django 提供的 CSRF 防护机制
django 第⼀次响应来⾃某个客户端的请求时(get⽅式),会在服务器端随机⽣成⼀个 token,然后把这个 token 写在⽤户请求的 cookie ⾥,同时也会给客户端页⾯发送⼀个随机的 token (form表单中以{% csrf_token %}⽅式获取)⽤以认证。之后客户端每次以 POST ⽅式向服务端提交请求时,都会带上这个 token,这样就能避免被 CSRF 攻击。
1.在返回的 HTTP 响应的 cookie ⾥,django 会为你添加⼀个 csrftoken 字段,其值为⼀个⾃动⽣成的 token;
2.在所有的 POST 表单中,必须包含⼀个 csrfmiddlewaretoken 字段(只需要在模板⾥加⼀个 tag, django 就会⾃动帮你⽣成,见下⾯)
3.在处理 POST 请求之前,django 会验证这个请求的 cookie ⾥的 csrftoken 字段的值和提交的表单⾥的 csrfmiddlewaretoken 字段的值是否⼀样。如果⼀样,则表明这是⼀个合法的请求,否则,这个请求可能是来⾃于别⼈的 csrf 攻击,返回 403 Forbidden.
4.在所有 ajax POST 请求⾥,添加⼀个 X-CSRFTOKEN header,其值为 cookie ⾥的 csrftoken 的值
Django ⾥如何使⽤ CSRF 防护
⾸先,最基本的原则是:GET 请求不要⽤!有副作⽤!也就是说任何处理 GET 请求的代码对资源的访问都⼀定要是“只读“的;
其次,要启⽤ django.middleware.csrf.CsrfViewMiddleware 这个中间件;
最后,在所有的 POST 表单元素中,需要加上⼀个 {% csrf_token %} tag。原因:⽤于csrf在模版渲染过程中,会⾃动为表单添加⼀个名为 csrfmiddlewaretoken , type属性为 hidden 的 input。
Django CSRF 应⽤<;基本应⽤,FBV和CBV不同,ajax应⽤>
a. 基本应⽤:
直接在form表单中添加:就能应⽤。
{% csrf_token %} -----> 转换成⼀个hidden属性的input标签
{{ csrf_token }} -----> 直接获取csrf的随机字符串
注意:本地的cookies中也会添加随机字符串 ---> 注意key名
b. 全站禁⽤:
- 整个框架不使⽤csrf安全机制,直接在settings.py⽂件中注销,整个⽹站都不再应⽤。
# 'django.middleware.csrf.CsrfViewMiddleware',
c. 局部禁⽤:全局使⽤,但是某些函数不需要应⽤。
- settings.py⽂件中不注销,在项⽬的views.py函数中导⼊模块,给函数或是类加上对应⽅法的装饰器:
'django.middleware.csrf.CsrfViewMiddleware',
from django.views.decorators.csrf import csrf_exempt,csrf_protect
@csrf_exempt #不再做检测!其他没加装饰器的函数还是会检测
def csrf1(request):
hod == 'GET':
return render(request,'csrf1.html')
else:
return HttpResponse('ok')
d. 局部使⽤:全局不使⽤,但是某些函数需要应⽤。
# 'django.middleware.csrf.CsrfViewMiddleware',
from django.views.decorators.csrf import csrf_exempt,csrf_protect
@csrf_protect #全站不⽤,某个函数需要使⽤认证的时候
def csrf1(request):
hod == 'GET':
return render(request,'csrf1.html')
else:
return HttpResponse('ok')
e. 特殊CBV:在CBV应⽤中,有些特殊!
django 不认给类内的函数名上添加装饰器,只能是在类上添加。
同时django限制若是应⽤装饰器,必须⽤它的⽅法去添加,同时添加的语法格式也有限制。
django登录注册功能from django.views import View
from django.utils.decorators import method_decorator #必须使⽤这个⽅法
- 语法:@method_decorator(装饰器函数名称或⽅法,name='被装饰的函数名')
#先导⼊⽅法,然后装饰器以参数的形式添加,其次指定要添加这个⽅法的函数名<;样式:name="函数名">
@method_decorator(csrf_protect,name='dispatch')
class Foo(View):
#请求来了,都是先执⾏类View的内置函数dispatch,然后再映射到对应的⽅法上!
#所以给dispatch添加上就相当于给所有的⽅法添加了
def get(self,request):
pass
def post(self,request):
pass
PS:CBV中添加装饰器
#⾃定义的装饰器
def wrapper(func):
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner
# 1. 指定⽅法上添加装饰器
class Foo(View):
@method_decorator(wrapper) #先导⼊⽅法,然后装饰器以参数的形式添加
def get(self,request):
pass
def post(self,request):
pass
# 2. 在类上添加
@method_decorator(wrapper,name='dispatch')
class Foo(View):
def get(self,request):
pass
def post(self,request):
pass
f.Ajax提交数据时候,携带CSRF:
a. 以post⽅式提交,放置在data中携带
<form method="POST" action="/csrf1.html">
{% csrf_token %}
<input id="user" type="text" name="user" />
<input type="submit" value="提交"/>
<a onclick="submitForm();">Ajax提交</a>
</form>
<script src="/static/jquery-1.12.4.js"></script>
<script>
function submitForm(){
var csrf = $('input[name="csrfmiddlewaretoken"]').val();
var user = $('#user').val();
$.ajax({
url: '/csrf1.html',
type: 'POST',
data: { "user":user,'csrfmiddlewaretoken': csrf},
#注意csrf随机字符串,后台有固定的名字接收,这种⽅式是通过标签获取的对应值
success:function(arg){
console.log(arg);
}
})
}
</script>
b. POST⽅式提交,信息放在请求头中,从cookies中获取的csrf随机字符串
<form method="POST" action="/csrf1.html">
{% csrf_token %}
<input id="user" type="text" name="user" />
<input type="submit" value="提交"/>
<a onclick="submitForm();">Ajax提交</a>
</form>
<script src="/static/jquery-1.12.4.js"></script>
<script src="/kie.js"></script>
<script>
function submitForm(){
var token = $.cookie('csrftoken');
var user = $('#user').val();
$.ajax({
url: '/csrf1.html',
type: 'POST',
headers:{'X-CSRFToken': token}, #注意csrf随机字符串后台有固定的名字接收
data: { "user":user},
success:function(arg){
console.log(arg);
}
})
}
</script>
django csrf注意点:
注意⼀定注意:ajax POST提交的时候,csrf-token 随机字符串直接放在data数据中的⽅式为:data:{csrfmiddlewaretoken:"{{
csrf_token }}"}
若是导⼊⾃⼰写的JS⽂件,那上述⽅法就不能获取到Django后台发送的随机字符串,⽽是需要利⽤上⾯介绍的两种⽅式获取(页⾯写上{% csrf_token %},通过隐藏的input标签取value值写在POST提交的data数据中;或是从cookie中获取,写在头⽂件中。)
使⽤django框架时:
每次初始化⼀个项⽬时都要看看 django.middleware.csrf.CsrfViewMiddleware 这个中间件
每次在模板⾥写 form 时都需要加⼀个 {% csrf_token %} tag
每次发 ajax POST 请求,都需要加⼀个 X_CSRFTOKEN 的 header
流程:
⽤户第⼀次访问页⾯,肯定是get请求,此时服务端就会给客户端发送⼀段随机字符串的数据,当客户提交数据的时候,常在POST请求中带回,就会发送随机字符串给服务端(上⼀次请求获取的数据)⽤于验证。
服务端给客户端发送的随机字符串作为⼀种安全机制,客户端往服务端发送请求时再携带回来,⽤于匹配认证。
可以从form表单中接收,也可以在cookies中查看,注意:这两个的随机字符串是不同的!
如果开启了csrf认证,后台没有拿到对应的字符串的话就会报错---> 403
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论