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攻击与防御的主要内容,如果未能解决你的问题,请参考以下文章