你了解可怕的CSRF攻击吗?
来源丨小怪聊职场
www.jianshu.com/p/67408d73c66d
CSRF
攻击的全称是跨站请求伪造( cross site request forgery
),是一种对网站的恶意利用。CSRF
是通过伪装来自受信任用户的请求来利用受信任的网站。你可以这么理解 CSRF
攻击:攻击者盗用了你的身份,以你的名义向第三方网站发送恶意请求。CRSF
能做的事情包括:利用你的身份发邮件、发短信、进行交易转账等,甚至盗取你的账号。
首先用户
C
浏览并登录了受信任站点A
;登录信息验证通过以后,站点
A
会在返回给浏览器的信息中带上已登录的cookie
,cookie
信息会在浏览器端保存一定时间(根据服务端设置而定);完成这一步以后,用户在没有登出(清除站点
A
的cookie
)站点A
的情况下,访问恶意站点B
;这时恶意站点
B
的某个页面向站点A
发起请求,而这个请求会带上浏览器端所保存的站点A
的cookie
;站点
A
根据请求所带的cookie
,判断此请求为用户C
所发送的。
因此,站点 A
会根据用户 C
的权限来处理恶意站点 B
所发起的请求,而这个请求可能以用户 C
的身份发送 邮件、短信、消息,以及进行转账支付等操作,这样恶意站点 B
就达到了伪造用户 C
请求站点 A
的目的。
受害者只需要做下面两件事情,攻击者就能够完成 CSRF
攻击:
登录受信任站点
A
,并在本地生成cookie
;在不登出站点
A
(清除站点A
的cookie
)的情况下,访问恶意站点B
。
很多情况下所谓的恶意站点,很有可能是一个存在其他漏洞的受信任且被很多人访问的站点,这样,普通用户可能在不知不觉中便成为了受害者。
当你登录网站 A
后,没有及时登出,这时你访问了论坛 B
,不幸的事情发生了,你会发现你的账号里面少了 10000
块...
当然,绝大多数网站都不会使用 GET
请求来进行数据更新,因此,攻击者也需要改变思路,与时俱进。
假设银行将其转账方式改成 POST
提交,而论坛 B
恰好又存在一个 XSS
漏洞,恶意用户在它的页面上植入如下代码:
<form id="aaa" action="http://www.xxx.com/transfer.do" metdod="POST" display="none">
<input type="text" name="accountNum" value="10001"/>
<input type="text" name="money" value="10000"/>
</form>
<script>
var form = document.forms('aaa');
form.submit();
</script>
当然,以上只是举例,正常来说银行的交易付款会有USB key、验证码、登录密码和支付密码等一系列屏障,流程比上述流程复杂得多,因此安全系数也高得多!
尽量使用POST,限制GET
GET
接口太容易被拿来做 CSRF
攻击,看上面示例就知道,只要构造一个 img
标签,而 img
标签又是不能过滤的数据。接口最好限制为 POST
使用, GET
则无效,降低攻击风险。
当然 POST
并不是万无一失,攻击者只要构造一个 form
就可以,但需要在第三方页面做,这样就增加暴露的可能性。
将 cookie设置为 HttpOnly
CRSF
攻击很大程度上是利用了浏览器的 cookie
,为了防止站内的 XSS
漏洞盗取 cookie
,需要在 cookie
中设置 “HttpOnly”
属性,这样通过程序(如 JavaScript
脚本、 Applet
等)就无法读取到 cookie
信息,避免了攻击者伪造 cookie
的情况出现。
在 Java
的 Servlet
的API中设置 cookie
为 HttpOnly
的代码为:response.setHeader("Set-Cookie","cookiename=cookievalue;HttpOnly");
增加Token
CSRF
攻击之所以能够成功,是因为攻击者可以伪造用户的请求,该请求中所有的用户验证信息都存在于 cookie
中,因此攻击者可以在不知道用户验证信息的情况下直接利用用户的 cookie
来通过安全验证。由此可知,抵御 CSRF
攻击的关键在于:在请求中放入攻击者所不能伪造的信息,并且该信总不存在于 cookie
之中。鉴于此,系统开发人员可以在 HTTP
请求中以参数的形式加入一个随机产生的 token
,并在服务端进行 token
校验,如果请求中没有 token
或者 token
内容不正确,则认为是 CSRF
攻击而拒绝该请求。
通过Referer识别
参考文献
-
《大型分布式网站架构设计与实践》