CSRF攻击与防御

Posted CNNS安全

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CSRF攻击与防御相关的知识,希望对你有一定的参考价值。

CSRF是什么

CSRF(Cross-site request forgery),中文名称:跨站请求伪造,是一种广泛存在于网站中的安全漏洞,缩写为:CSRF/XSRF。

CSRF的原理

CSRF攻击能劫持终端用户在已登录的Web站点上执行本意操作。简单的说,攻击者透过盗用用户身份悄悄发送一个请求,或执行某些恶意操作,CSRF的过程非常隐秘,受害人甚至无法察觉。

产生CSRF漏洞的原因主要有两点:一方面是开发者不够谨慎,编写的Web应用程序存在漏洞导致恶意利用:另一方面,是因为Web浏览器对于Cookie和HTTP身份验证的回话信息的处理存在一定的缺陷。

CSRF的攻击流程

CSRF的恶意利用

执行恶意操作

举个例子,假设某个站点具有转账功能,实现该功能的html表单如下:

<form action="transfer.php" method="POST">

账号:<input type="text" name="toBankId"/></br>

金额:<input type="text" name="money"/></br>

<input type="submit" value="提交"/>

</form>

这时候,只要输入对应的账号和金额提交,就能实现转账。假设,受害者点击含有恶意代码的链接,并浏览带有下面HTML代码的网页:

<img src=”http://www.xxx.com.transfer.php?toBankId=99&money=1000”

在这个CSRF的过程中,受害者是毫不知情的,莫名其妙发生了转账行为。CSRF的攻击最大的特点就是完全以用户的身份发起的,很难防御。

以上CSRF能成功地原因,还有一个是因为开发人员滥用$_REQUEST方法,导致本来的POST操作可以用GET方式实现。那么,开发人员改用$_POST()方法来获取数据,那么要想成功执行CSRF,需要加上javascript代码。如下HTML:

<form id="test" action="http://www.xxx.com.transfer.php" method="POST">

账号:<input type="text" name="toBankId"/></br>

金额:<input type="text" name="money"/></br>

<input type="submit" value="提交"/>

</form>

<script>document.getElementById("test").submit()</script>

执行恶意操作

举个例子,假设某个站点具有转账功能,实现该功能的HTML表单如下:

<form action="transfer.php" method="POST">

账号:<input type="text" name="toBankId"/></br>

金额:<input type="text" name="money"/></br>

<input type="submit" value="提交"/>

</form>

这时候,只要输入对应的账号和金额提交,就能实现转账。假设,受害者点击含有恶意代码的链接,并浏览带有下面HTML代码的网页:

<img src=”http://www.xxx.com.transfer.php?toBankId=99&money=1000”

在这个CSRF的过程中,受害者是毫不知情的,莫名其妙发生了转账行为。CSRF的攻击最大的特点就是完全以用户的身份发起的,很难防御。

以上CSRF能成功地原因,还有一个是因为开发人员滥用$_REQUEST方法,导致本来的POST操作可以用GET方式实现。那么,开发人员改用$_POST()方法来获取数据,那么要想成功执行CSRF,需要加上Javascript代码。如下HTML:

<form id="test" action="http://www.xxx.com.transfer.php" method="POST">

账号:<input type="text" name="toBankId"/></br>

金额:<input type="text" name="money"/></br>

<input type="submit" value="提交"/>

</form>

<script>document.getElementById("test").submit()</script>

获取信息

同源策略,是浏览器安全的基石。但是,有时开发中要求B站中获取A站的数据,不得不使用JSONP等方式进行跨域请求。JSONP是通过GET请求跨域,因此,一般情况下,任何人都可以获取信息,并把信息发给自己。JSONP如下:

 

function addScriptTag(src) {

  var script = document.createElement('script');

  script.setAttribute("type","text/javascript");

  script.src = src;

  document.body.appendChild(script);

}

window.onload = function () {

  addScriptTag('http://example.com/ip?callback=foo');

}

function foo(data) {

  console.log('Your public IP address is: ' + data.phone);

};

JSONP最大特点就是简单适用,老式浏览器全部支持,服务器改造非常小。但是,这种跨同源策略的的行为,也大大带来了风险,不可滥用。因为这些数据别人也是可以获取的。最好不要用JSONP传递敏感的信息。

CSRF的防御

验证HTTP Referer

使用Token

CSRF攻击之所以能够成功,是因为攻击者可以伪造用户的请求,该请求中所有的用户验证信息都存在于Cookie中。因此,抵御CSRF攻击的关键在于:在请求中放入攻击者所不能伪造的信息,并且该信息不存在于Cookie之中。开发者可以在HTTP请求中以参数的形式加入一个随机产生的token,对于token错误的请求,则认为是CSRF攻击,并拒绝该请求。

下面有一种很好用的Token验证方法。在HTTP头中自定义属性并验证,如下:

 

自定义HTTP头X-CSRF-Token。先把token放入meta:

<meta name="csrf-token" content="{{ csrf_token() }}">

然后在全局Ajax中使用这种方式设置X-CSRF-Token请求头并提交:

$.ajaxSetup({ headers: {  'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')

    }

});

每次Ajax请求则会自动加上自定义的HTTP头X-CSRF-Token。

安全的跨域请求

使用新的W3C标准CORS,全称是"跨域资源共享"(Cross-origin resource sharing)。

         下面是一个例子,浏览器发现这次跨源AJAX请求是一般请求,就自动在头信息之中,添加一个Origin字段。如下

 GET /cors HTTP/1.1

Origin: http://api.bob.com

Host: api.alice.com

Accept-Language: en-US

Connection: keep-alive

User-Agent: Mozilla/5.0

上面的头信息中,Origin字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。如果在B站请求A站,浏览器是不允许跨域获取数据的。如果在A站返回的数据加上一个Access-Control-Allow-Origin:*的HTTP的头。这时所有网站都能访问。但是,这并不是我们想要的,只需把Access-Control-Allow-Origin修改成需要给权限的网站即可。

           cnns安全


以上是关于CSRF攻击与防御的主要内容,如果未能解决你的问题,请参考以下文章

CSRF攻击与防御

安全系列CSRF攻击与防御

csrf攻击与csrf防御

CSRF攻击与防御

CSRF的攻击与防御 详细版

CSRF攻击与防御