安全攻击---csrf
- csrf:跨站请求伪造
- 通过伪装成受信任用户的请求来利用受信任的网站
三种常见的安全攻击
- sql注入(防御方式:使用execute提交参数)
- xss跨站脚本攻击(防御方式:对客户端发来的数据进行转义)
- csrf跨站请求伪造(防御方式:提交数据时进行验证)
csrf概念
攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等。
csrf攻击原理及过程
- 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A
- 在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A
- 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B
- 网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A
- 浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行
python防御原理
开启中间件(django.middleware.csrf.CsrfViewMiddleware),全局csrf验证后,当用post提交数据的时候,django会去检查是否有一个csrf的随机字符串,如果没有就会报错,这也是之前我们一直将其注释的原因。
开启全局的csrf验证
1. settings中,打开注释 'django.middleware.csrf.CsrfViewMiddleware',
2. 表单中,开启csrf_token
<form>
{% csrf_token %} # 如果不书写,就会报错
<input type='text'>
</form>
# 使用这种方式,当你查看页面源码的时候,可以看到form中有一个input是隐藏的
# 总结原理:当用户访问login页面的时候,会生成一个csrf的随机字符串,,并且cookie中也存放了这个随机字符串,当用户再次提交数据的时候会带着这个随机字符串提交,如果没有这个随机字符串则无法提交成功
# 并且在查看页面的network时,会发现cookies下面多了一个csrftoken
开启全局的csrf,但是部分业务函数不进行检验
1. settings中,打开注释 ====》'django.middleware.csrf.CsrfViewMiddleware',
2. views中,引入如下函数
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('ok')
# 如上, 即便全局开启验证,但是可以使用装饰器进行特殊处理,对部分业务函数不进行检验
关闭全局的csrf, 但是部分业务函数要使用csrf验证
1. settings中,注释 ===》 #'django.middleware.csrf.CsrfViewMiddleware',
2. views中,引入如下函数
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('ok')
如果是CBV
from django.views.decorators.csrf import csrf_protect
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
# 如果是csrf_protect就是使用验证,csrf_exempt就是不使用验证
@method_decorator(csrf_protect, name='get') # 只能在get和post中选择一个
class User(View):
def get(self, request):
pass
def post(self, request):
pass
ajax方式
# 将token放置到请求头中, 携带过来
# 上面用一个hiddle的input把token拿到
token = $('input').val()
$.ajax({
type: 'POST',
URL: '/test/',
data: {name:'xxx'},
headers : {'X-CSRFToken': token},
success: function(response){
console.log(response)
}
})
疑问:
在设置cookie和csrf后,在前端使用document.cookie
获取到的却是csrf的值