跨站请求伪造(英语:Cross-site request forgery),也被称为one-click attack或者session riding,通常缩写为CSRF或者XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。

跟跨网站脚本(XSS)相比,XSS利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。

例如:

如果用户登录网络银行去查看其存款余额,他没有退出网络银行系统就去了自己喜欢的论坛去灌水,如果攻击者在论坛中精心构造了一个恶意的链接并诱使该用户点击了该链接,那么该用户在网络银行帐户中的资金就有可能被转移到攻击者指定的帐户中。

造成CSRF的原因

跨站请求伪造能否得逞,与以下几个方面密不可分,分别是浏览器对会话的处理,攻击者对Web应用有关URL的了解,应用程序赖以管理会话的信息对浏览器的透明性以及各种能够引发资源请求HTML标签等。

正常:
a. 先GET请求:
页面
隐藏:input 随机字符串
b. POST
数据
input 随机字符串 非法:
b. POST
数据

首先,我们来了解一些Web浏览器对于Cookie和HTTP身份验证信息之类的会话信息的处理方式。目前,浏览器会自动地发送标识用户对话的信息,而无需用户干预,换句话说,当浏览器发送这些身份信息的时候,用户根本感觉不到。假设站点A上有一个Web应用程序,并且受害者正好已经在该站点上通过了身份认证,这时,站点会向受害者发送一个cookie作为响应,这个cookie的作用是什么呢?主要是被站点作为用户会话的标志,即如果站点收到了带有受害者的cookie的请求,那么它就会把这个请求看作是已登录的受害者发来的。一般情况下,浏览器收到站点设置的cookie之后,每当向该站点发送请求的时候,浏览器都会“自动地”连同该cookie一起发出。

然后,我们再来讨论一下攻击者对Web应用程序URL的了解。如果应用程序没有在URL中使用跟会话有关的信息的话,那么通过代码分析或者通过访问该应用程序并查看嵌入HTML/JavaScript中的URL以及表单来了解应用程序有关的URL、参数和容许值。

接下来,我们讨论一下应用程序赖以管理会话的信息对浏览器的透明性问题。我们知道,为了提高Web应用的便利性,用来管理会话的信息,例如Cookie或者基于HTTP的身份验证(例如HTTP基本认证、非基于表单的认证)等敏感信息,都是由浏览器来存放的,并在每当向需要身份验证的应用程序发送请求时自动捎带上这些信息。也就是说,浏览器可以访问会话管理信息,如果Web应用程序完全依赖于这类信息来识别一个用户会话,这就为跨站请求伪造创造了条件。

上面所说的三个因素,是跨站请求伪造攻击的必要的条件,而下面所说的,是一个“锦上添花”的因素,即没有它也能发动跨站请求伪造攻击,但是有了它能使该攻击更加容易。这就是存在多种HTML标签,如果页面内出现这些标签,会立刻引起浏览器对http[s]资源的访问,例如图像标签img便是其中之一。

在Django中

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

全局:

中间件 django.middleware.csrf.CsrfViewMiddleware

局部:

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

注:from django.views.decorators.csrf import csrf_exempt,csrf_protect

应用

1、普通表单

veiw中设置返回值:
  return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))  
或者
return render(request, 'xxx.html', data) html中设置Token:
  {% csrf_token %}

Form提交:

<form action="/icbc.html" method="POST">
{% csrf_token %}
<input type='text' name='from' />
<input type='text' name='to' />
<input type='text' name='money' />
<input type='submit' value='转账' />

2、Ajax

对于传统的form,可以通过表单的方式将token再次发送到服务端,而对于ajax的话,使用如下方式。

view.py

from django.template.context import RequestContext
# Create your views here. def test(request): if request.method == 'POST':
print request.POST
return HttpResponse('ok')
return render_to_response('app01/test.html',context_instance=RequestContext(request))

text.html

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
{% csrf_token %} <input type="button" onclick="Do();" value="Do it"/> <script src="/static/plugin/jquery/jquery-1.8.0.js"></script>
<script src="/static/plugin/jquery/jquery.cookie.js"></script>
<script type="text/javascript">
var csrftoken = $.cookie('csrftoken'); function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
function Do(){ $.ajax({
url:"/app01/test/",
data:{id:1},
type:'POST',
success:function(data){
console.log(data);
}
}); }
</script>
</body>
</html>

Ajax提交:

1)基于请求体:

function ajaxSubmit() {
$.ajax({
url: "/icbc.html",
type: 'POST',
data: {'k1':'v1','k2':'v2','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val() },
success:function (arg) {
console.log(arg)
}
})
} // 只能写在模板中
function ajaxSubmit() {
$.ajax({
url: "/icbc.html",
type: 'POST',
data: {'k1':'v1','k2':'v2','csrfmiddlewaretoken':"{{ csrf_token }}" },
success:function (arg) {
console.log(arg)
}
})
} function ajaxSubmit() {
$.ajax({
url: "/icbc.html",
type: 'POST',
data: $('#f1').serialize(),
success:function (arg) {
console.log(arg)
}
})
}
// 以上都是放在请求体中

2)基于请求头:

a. 在cookie中获取csrftoken对应的值 l2kEqQLhR1gH0hh3ioZ1dfxT3iSwjXoKTf7GNFggJZ7E6DROB6k33L7vdqe5lV1v
b. 发送请求时,放在请求头中也可以 function ajaxSubmit() {
$.ajax({
url: "/icbc.html",
type: 'POST',
data: {'k1':'v1','k2':'v2'},
headers: {"X-CSRFToken": $.cookie('csrftoken')},
success:function (arg) {
console.log(arg)
}
})
}

跨站请求伪造对策

跨站请求伪造的危害非常之大,所以无论是用户还是开发人员都应该引起足够的重视,下面是给Web应用程序终端用户和Web应用程序开发人员的一些有用的建议。

用户:

因为CSRF漏洞有流行之趋势,所以建议用户遵循最佳实践来降低风险,可以降低风险的习惯包括:

使用Web应用程序之后立即登出

不要让浏览器保存用户名/口令,也不要让站点“记住”您不要使用同一个浏览器同时访问敏感的应用程序和随意冲浪;如果必须同时做多件事情的话,最好单独使用不同的浏览器。

对于支持HTM格式邮件/浏览器集成式软件以及集成了新闻阅读程序/浏览器的软件都会带来额外的风险,因为只要查看邮件或者新闻就有可能被迫执行一次攻击,所以使用这类软件时格外小心。

开发人员:

开发人员应当向URL添加跟会话有关信息。该攻击类型之所以得逞,是因为会话是由cookie唯一标识的,并且该cookie是由浏览器自动发送的。

如果我们在URL级别为会话生成其它相关信息,那么就会给攻击者为发动攻击而了解URL的结构造成更多的障碍。

至于其它的对策,虽然也无法解决该问题,但是能够使得利用该漏洞更加困难,例如使用POST而不是GET。虽然POST请求可以通过JavaScript进行模仿,但是它提高了发动这种攻击的难度。使用中间确认页也能带来相同的效果,比如“您确信要这样做吗?”之类的页面。虽然攻击者可以绕过这些措施,但是这些措施提供了实施攻击的难度。因此,不能完全依赖这些手段来保护您的应用程序。自动登出机制也能减轻这种攻击带来的危害,但这最终依赖于具体情况(一个整天跟有这种漏洞的网络银行程序打交道的用户所面临的风险要远远大于临时使用同一网络银行的用户所面临的风险)。

Django框架之跨站请求伪造的更多相关文章

  1. Django框架 之 跨域请求伪造

    Django框架 之 跨域请求伪造 浏览目录 同源策略与Jsonp 同源策略 Jsonp jQuery对JSONP的实现 CORS 简介 两种请求 同源策略与Jsonp 同源策略 同源策略(Same ...

  2. Django之CSRF 跨站请求伪造

    一.简介 1.点我了解什么是跨站请求伪造 2.django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成.而对 ...

  3. Django添加防跨站请求伪造中间件

    第一步: 在全局设置中打开此中间件: MIDDLEWARE_CLASSES = [ ... 'django.middleware.csrf.CsrfViewMiddleware', ... ]     ...

  4. Django之cfrs跨站请求伪造和xfs攻击

    跨站请求伪造 一.简介 django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成.而对于django中设置防 ...

  5. django CBV装饰器 自定义django中间件 csrf跨站请求伪造 auth认证模块

    CBV加装饰器 第一种 @method_decorator(装饰器) 加在get上 第二种 @method_decorator(login_auth,name='get') 加在类上 第三种 @met ...

  6. django的csrf跨站请求伪造

    1.什么是跨站请求伪造 请看图: 我们自行写了一个网站模仿中国银行,用户不知道是否是真的中国银行,并且提交了转账信息,生成一个form表单,向银行服务器发送转账请求,这个form表单和正规银行网站的f ...

  7. Django之CSRF跨站请求伪造(老掉牙的钓鱼网站模拟)

    首先这是一个测试的代码 请先在setting页面进行下面操作 注释完成后,开始模拟钓鱼网站的跨站请求伪造操作: 前端代码: <!DOCTYPE html> <html lang=&q ...

  8. django中csrftoken跨站请求伪造的几种方式

    1.介绍 我们之前从前端给后端发送数据的时候,一直都是把setting中中间件里的的csrftoken这条给注释掉,其实这个主要起了一个对保护作用,以免恶意性数据的攻击.但是这样直接注释掉并不是理智型 ...

  9. Web框架之Django_09 重要组件(Django中间件、csrf跨站请求伪造)

    摘要 Django中间件 csrf跨站请求伪造 一.Django中间件: 什么是中间件? 官方的说法:中间件是一个用来处理Django的请求和响应的框架级别的钩子.它是一个轻量.低级别的插件系统,用于 ...

随机推荐

  1. ABP之应用服务(1)

    在一个理想的层级项目中,展现层是不能直接访问领域对象的,那么展现层如何获取到自己需要的数据呢?也就是今天的主角-Application层,它的职责就是为展现层服务,它通过仓储获取到相应的数据,然后将数 ...

  2. Python面向对象:继承和多态

    继承与多态简介: 继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写. 动态语言的鸭子类型特点决定了继承不像静态语言那样是必须的. ...

  3. Circular reference 循环引用 第二联系人

    A circular reference is a series of references where the last object references the first, resulting ...

  4. The third column indicates whether subclasses of the class declared outside this package have access to the member.;

    总结1.modifier 改性剂 修饰符 修饰语 调节器access modifier 访问修饰符 存取权限 存取修饰词 存取修饰字官网“can”Access level modifiers dete ...

  5. JAVA队列的使用

    JAVA队列的使用 今天跟大家来看看如何在项目中使用队列.首先我们要知道使用队列的目的是什么?一般情况下,如果是一些及时消息的处理,并且处理时间很短的情况下是不需要使用队列的,直接阻塞式的方法调用就可 ...

  6. [GDAL]写入shp

    C#通过Wkt码构建shp,记录写不进去! static void WriteVectorFile() { string strVectorFile = "E:\\"; // 注册 ...

  7. golang使用vet进行语法检查

    go tool vet是你的好朋友,不要忽视它. vet是一个优雅的工具,每个Go开发者都要知道并会使用它.它会做代码静态检查发现可能的bug或者可疑的构造.vet是Go tool套件的一部分,我们会 ...

  8. 开源的挖矿软件,sha256

    http://cryptomining-blog.com/tag/sha-256d-miner/ https://github.com/cbuchner1/CudaMiner/blob/master/ ...

  9. Gcc ------ gcc的使用简介与命令行参数说明

    gcc的使用简介与命令行参数说明 2011年06月19日 20:29:00 阅读数:10221 2011-06-19 wcdj 参考:<GNU gcc嵌入式系统开发 作者:董文军> (一) ...

  10. Linux学习网站推荐

    最近想重新拾起Linux,发现了实验楼这个网站:https://www.shiyanlou.com/,可以通过这个网站学习Linux以及其他一些知识,可以直接学习直接动手操作,比较方便.