在《JSON必知必会》第5章讲到JSON中的安全问题时,有提到一个概念 - CSRF,查阅相关资料后,做下总结记录。
一.什么是CSRF
CSRF - cross-site request forgery,即跨站请求伪造,是一种利用站点对用户浏览器信任而发起攻击的方式。这种信任通常是本地浏览器 Cookie 的方式。
CSRF攻击可以盗用你的信息后,以你的名义发送邮件、发消息、盗取账号甚至转账,造成个人隐私泄露,危及财产安全。
从上图可以看出,攻击主要利用了客户本地浏览器的 Cookie ,在没有退出的情况下,通过 Cookie 凭证,恶意网站B通过用户向受信网站A请求执行恶意代码。
二.CSRF攻击的几种情况
1.通过嵌入包含恶意请求或者执行代码的链接放到HTML中:
<img src=http://www.rumoss.com/admin.php?uid=001&op=modify>
当用户没有退出受信网站A的情况下,访问恶意网站B时,这个请求就会随着Cookie发送到受信网站A,执行恶意代码。
2.上面是 GET 的方式,有人可能说,换成 POST 不就可以避免了?接着看:
假如网站B是这样处理:
<script type="text/javascript">
function csrfTest()
{
iframe = document.frames["csrfFrame"];
iframe.document.Submit("csrfForm");
}
</script>
<body onload="csrfTest()">
<iframe name="csrfFrame" display="none">
<form method="POST" name="csrfForm" action="http://www.rumoss.com/admin.php">
<input type="hidden" name="uid" value="001">
<input type="hidden" name="op" value="modify">
</form>
</iframe>
</body>
假如用户同样没有退出受信网站A,直接访问网站B,B也能做到偷偷滴往网站A通过 POST 方式提交恶意表单执行恶意代码。
查阅资料的时候看到一句话:
CSRF攻击是源于WEB的隐式身份验证机制!WEB的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的!
三.如何防御CSRF
在客户端页面增加伪随机数。
1.Cookie Hashing
所有表单都包含同一个伪随机值,这种方式我在typecho的代码里面见过:
<form method="post" id="comment-form" role="form" onsubmit="return TypechoComment.subComment();">
<input type="hidden" name="_" value="90e8es60a0d8dd2f2ca23890f4408c">
</form>
在表单里增加Hash值,以认证这确实是用户发送的请求,然后在服务器端进行Hash值验证。
据说这种方式可以防止99%的CSRF攻击。但也还有10%的概率被攻击,原因是Cookie信息有可能被盗取。
2.验证码
验证码就不用说了,很常见,不管如何变化,除非是人脸识别验证,一般的验证码都会有办法破解的。
3.一次性凭证
在做公众号的时候,每次通过微信服务器重定向过来的请求里面就有一个code,每次通过这个code能获取当前请求微信用户的信息。用完一次不能再次使用。这种方式如果使用不当可能也会出现问题,当同一个用户有多个会话的时候,不能影响到其他会话的表单提交。
然后是后台进行凭证的校验。
四.实际应用的例子
网易云音乐API,通过CSRF伪造请求头,调用官方API。