漏洞名称:
跨站请求伪造(CSRF)
描述:
跨站请求伪造攻击,Cross-Site Request Forgery(CSRF),攻击者在用户浏览网页时,利用页面元素(例如img的src),强迫受害者的浏览器向Web应用服务器发送一个改变用户信息的HTTP请求。CSRF攻击可以从站外和站内发起。从站内发起CSRF攻击,需要利用网站本身的业务,比如“自定义头像”功能,恶意用户指定自己的头像URL是一个修改用户信息的链接,当其他已登录用户浏览恶意用户头像时,会自动向这个链接发送修改信息请求。从站外发送请求,则需要恶意用户在自己的服务器上,放一个自动提交修改个人信息的htm页面,并把页面地址发给受害者用户,受害者用户打开时,会发起一个请求。威胁描述:攻击者使用CSRF攻击能够强迫用户向服务器发送请求,导致用户信息被迫修改,甚至可引发蠕虫攻击。如果恶意用户能够知道网站管理后台某项功能的URL,就可以直接攻击管理员,强迫管理员执行恶意用户定义的操作。
检测条件:
Web业务运行正常
存在数据提交的所有功能点。
检测方法:
检测方式多种多样:工具常常会扫描得到CSRF的漏洞,但是一般常常为误报,重点还是依靠手工来进行检测,以下来举例说明其中一种检测以及攻击方案:
1.设置页面test.htm中,页面中有一个表单,和一段脚本,脚本的作用是,当页面加载时,浏览器会自动提交请求。页面代码如下:
<form id="modify" action="http://www.test.com/servlet/modify" method="POST"> <input name="email"> <input name="tel"> <input name="realname"> <input name="userid"> <input type="submit"> </form> <script> document.getElementById("modify").submit(); </script>
2.诱使用户在登录目标系统后执行URL链接http://xx.x.xx.xxx /test.htm
3.用户打开test.htm后,会自动提交表单,发送给www.test.com下的那个存在CSRF漏洞的web应用,用户信息被篡改
4.在整个攻击过程中,受害者用户仅仅看到了一个空白页面(可以伪造成其他无关页面),并且一直不知道自己的信息已经被修改了
漏洞修复:
1.通过referer判断页面来源进行CSRF防护,该方式无法防止站内CSRF攻击及referer字段伪造。
2.重要功能点使用动态验证码进行CSRF防护。
3.通过token方式进行CSRF防护:
1、在Session中绑定token。如果不能保存到服务器端Session中,则可以替代为保存到Cookie里。 2、在form表单中自动填入token字段,比如 <input type=hidden name="anti_csrf_token" value="$token" />。 3、在HTTP请求中自动添加token。 在服务器端对比POST提交参数的token与Session中绑定的token是否一致,以验证CSRF攻击
4.为每个session创建唯一的随机字符串,并在受理请求时验证:
<form action="/transfer.do" method="post"> <input type="hidden" name="randomStr" value=<%=request.getSession().getAttribute("randomStr")%>> ...... </form> //判断客户端提交的随机字符串是否正确 String randomStr = (String)request.getParameter("randomStr"); if(randomStr == null) randomStr=""; if(randomStr.equals(request.getSession().getAttribute("randomStr"))) {//处理请求} else{ //跨站请求攻击,注销会话 }
攻击原理:链接:https://www.jianshu.com/p/67408d73c66d
- 首先用户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。
很多情况下所谓的恶意站点,很有可能是一个存在其他漏洞(如XSS)的受信任且被很多人访问的站点,这样,普通用户可能在不知不觉中便成为了受害者。
其他补充:
参考:https://www.imooc.com/article/13552
https://www.jianshu.com/p/2b6c69f2d520
CSRF攻击是什么
CSRF
是跨站请求伪造的缩写,也被称为XSRF
, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。
跟跨网站脚本(XSS)相比,XSS利用的是用户对指定网站的信任,CSRF利用的是网站对用户网页浏览器的信任。
因为CSRF攻击利用的是冲着浏览器分不清发起请求是不是真正的用户本人。也就是说,简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。CSRF攻击基本原理
最简单的CSRF攻击
- 用户Alice登录和访问某银行网站A,保留
cookie
。- Alice被某些信息诱导访问危险网站B。
- 危险网站B上有一个
<img>
标签:<img src="http://www.examplebank.com/account=Alice&amount=1000&payfor=Badman" >
- 这个标签的src不指向一张图片,而是一个http请求,这个请求向银行要求将Alice的1000元转给Badman,由于Alice的浏览器上有
cookie
,这样浏览器发出的这个请求就能得到响应执行。- 这样Alice的钱就被偷了。
进阶攻击
危险网站可以伪造一个表单并隐藏,并在自己网站的
onload
事件中,触发这个表单的提交事件,就可以改GET攻击为POST攻击CSRF攻击的对象与防范思路
我们要防范它,先要知道它的目标,然后设法保护这些目标。
我们要明白,仅仅靠发起CSRF攻击的话,黑客只能借助受害者的cookie
骗取服务器的信任,但是黑客并不能凭借拿到cookie
,也看不到cookie
的内容。另外,对于服务器返回的结果,由于浏览器同源策略的限制,黑客也无法进行解析。
这就告诉我们,我们要保护的对象是那些可以直接产生数据改变的服务,而对于读取数据的服务,则不需要进行CSRF
的保护。
而保护的关键,是在请求中放入黑客所不能伪造的信息。防范手段
最基本的手段:涉及敏感操作的请求改为POST请求
这个方法的确可以防范一些
CSRF
攻击,但是对于进阶攻击就无能为力了——POST
请求一样可以伪造。
所以这个方法不够安全。只能提高攻击的门槛。一般手段
用户操作限制——验证码机制
方法:添加验证码来识别是不是用户主动去发起这个请求,由于一定强度的验证码机器无法识别,因此危险网站不能伪造一个完整的请求。
优点:简单粗暴,低成本,可靠,能防范99.99%的攻击者。
缺点:对用户不友好。请求来源限制——验证 HTTP Referer 字段
方法:在
HTTP
请求头中有一个字段叫Referer
,它记录了请求的来源地址。 服务器需要做的是验证这个来源地址是否合法,如果是来自一些不受信任的网站,则拒绝响应。
优点:零成本,简单易实现。
缺点:由于这个方法严重依赖浏览器自身,因此安全性全看浏览器。
- 兼容性不好:每个浏览器对于
Referer
的具体实现可能有差别。- 并不一定可靠:在一些古老的垃圾浏览器中,
Referer
可以被篡改。- 对用户不友好:
Referer
值会记录下用户的访问来源,有些用户认为这样会侵犯到他们自己的隐私权。因此有些用户可能会开启浏览器防止跟踪功能,不提供Referer
,从而导致正常用户请求被拒绝。额外验证机制——token的使用
方法:使用
token
来代替验证码验证。由于黑客并不能拿到和看到cookie
里的内容,所以无法伪造一个完整的请求。基本思路如下:
- 服务器随机产生
token
(比如把cookie
hash化生成),存在session
中,放在cookie
中或者以ajax
的形式交给前端。- 前端发请求的时候,解析
cookie
中的token
,放到请求url
里或者请求头中。服务器验证
token
,由于黑客无法得到或者伪造token
,所以能防范csrf
更进一步的加强手段(不需要session):
- 服务器随机产生
token
,然后以token
为密钥散列生成一段密文- 把
token
和密文都随cookie
交给前端- 前端发起请求时把密文和
token
都交给后端- 后端对
token
和密文进行正向散列验证,看token
能不能生成同样的密文- 这样即使黑客拿到了
token
也无法拿到密文。优点:
- 安全性:极大地提高了破解成本(当然还是有办法破解),但是99%的攻击者看到散列的时候就已经望而生畏了。
- 易用性:非常容易实现。
- 友好性:对用户来说十分友好。
缺点:
- 性能担忧:需要
hash
计算,增加性能上的成本cookie
臃肿:更加依赖网络的情况- 并不绝对安全:
- 一些论坛之类支持用户自己发表内容,由于系统也会在这个地址后面加上
token
,这样黑客可以在自己的网站上得到这个token
,并马上就可以发动CSRF攻击。(进一步加强法可以防范,或者验证链接是否是链到自己本站的,是就在后面添加token
,如果是通向外网则不加)- 其他攻击方式如XSS攻击能拿到
cookie
和token
,当然这不在本文的讨论范围之内。- 对于POST请求,难以将
token
附在请求中。(可以通过框架和库解决)曲线救国——在HTTP头中自定义属性并验证
方法:这种方法也是使用token并进行验证,和上一种方法不同的是把它放到HTTP头中自定义的属性里。
优点:
- 这样解决了上种方法在请求中加入 token 的不便
- 通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,安全性较高
缺点:
- 局限性非常大:XMLHttpRequest请求通常用于Ajax,并非所有的请求都适合用这个类来发起,而且通过该类请求得到的页面不能被浏览器所记录下,造成不便。
- 对于旧网站,要把所有请求都改为XMLHttpRequest请求,这样几乎是要重写整个网站,这代价无疑是不能接受的。
总结
因为CSRF攻击利用的是冲着浏览器分不清发起请求是不是真正的用户本人,所以防范的关键在于在请求中放入黑客所不能伪造的信息。从而防止黑客伪造一个完整的请求欺骗服务器。