实习面试篇–web安全之CSFR(跨站侵请求伪造)
**
知识储备:
**
cookie:Cookie 是浏览器访问服务器后,服务器传给浏览器的一段数据。(存储在用户本地的)
作用:
1.识别身份
2.记录历史,以后每次访问该网站都带cookie
token生成流程
用户访问某个表单页面。
服务端生成一个Token,放在用户的Session中,或者浏览器的Cookie中。
在页面表单附带上Token参数。
用户提交请求后,服务端验证表单中的Token是否与用户Session(或Cookies)中的Token一致,一致为合法请求,不是则非法请求。
一、CSRF基本概念
1.CSRF(Cross Site Request Forgery) 跨站请求伪造。也被称为One Click Attack和Session Riding,通常缩写为CSRF或XSRF。
简单来说就是攻击者假装成别人去发送恶意请求
请求包括发送邮件、发送消息、盗取账号、购买商品、银行转账,从而使你的个人隐私泄露和财产损失
二、CSRF原理
要完成CSRF这个攻击必须满足两点:
1.登录受信任网站A,并在本地生成Cookie
2.在不登出A的情况下,访问危险网站B
三、CSRF实例
我们先假设支付宝存在CSRF漏洞
受害者支付宝账号是:th
攻击者的支付宝账号是:qyc
通过网页请求的方式
http://zhifubao.com/withdraw?account=th&amount=10000&for=th2
可以把我账号th的10000元转到我的另外一个账号th2上去
通常情况下,服务器会先验证该请求是否来自一个合法的session并且该session的用户已经成功登陆
受害者点击链接之后,被动的发送一个请求到支付宝后台
http://zhifubao.com/withdraw?account=th&amount=10000&for=qyc
而且这个请求会附带受害者的浏览器中的cookie。我的浏览器中的cookie存有我的认证信息,这个请求就会得到响应,从我的账户中转10000元到qyc账户里,而我丝毫不知情,攻击者拿到钱后逍遥法外。
四、CSRF防御
- 服务器端的防御措施
(1)验证HTTP Referer字段
HTTP头中有一个字段叫Referer,它记录了该HTTP请求的来源地址。在通常情况下,访问一个安全受限页面的请求必须来自于同一个网站。
比如上面支付宝转账界面当用户提交请求时,该转账请求的Referer值就会是转账按钮所在页面的URL(本例中,通常是以zhifubao.com域名开头的地址)。而如果攻击者要对银行网站实施CSRF攻击,他只能在自己的网站构造请求,当用户通过攻击者的网站发送请求到支付宝时,该请求的Referer是指向攻击者的网站。
因此,要防御CSRF攻击,支付宝只需要对于每一个转账请求验证其Referer值,如果是以zhifubao.com开头的域名,则说明该请求是来自支付宝网站自己的请求,是合法的。如果Referer是其他网站的话,就有可能是CSRF攻击,则拒绝该请求。
(2)在请求地址中添加token并验证
CSRF攻击之所以能够成功,是因为攻击者可以伪造用户的请求,该请求中所有的用户验证信息都存在于Cookie中,因此攻击者可以在不知道这些验证信息的情况下直接利用用户自己的Cookie来通过安全验证。
由此可知,抵御CSRF攻击的关键在于:在请求中放入攻击者所不能伪造的信息,并且该信息不存在于Cookie之中。
鉴于此,系统开发者可以在HTTP请求中以参数的形式加入一个随机产生的token,并在服务器端建立一个拦截器来验证这个token,如果请求中没有token或者token内容不正确,则认为可能是CSRF攻击而拒绝该请求。
(3)在HTTP头中自定义属性并验证
自定义属性的方法也是使用token并进行验证,和前一种方法不同的是,这里并不是把token以参数的形式置于HTTP请求之中,而是把它放到HTTP头中自定义的属性里。通过XMLHttpRequest这个类,可以一次性给所有该类请求加上csrftoken这个HTTP头属性,并把token值放入其中。
这种方法解决了前一种方法在请求中加入token的不便,同时,通过这个类请求的地址不会被记录到浏览器的地址栏,也不用担心token会通过Referer泄露到其他网站。但是需要整站加入ajax,比较麻烦。
- 其他方式的防御措施
(1)验证码,强制用户必须与应用进行交互,才能完成最终请求。通常情况下,验证码能够很好的遏制CSRF攻击。但是出于用户体验考虑,网站不能给所有的操作都加上验证码。因此验证码只能作为一种辅助手段。
(2)尽量使用POST,限制GET,GET接口能够直接将请求地址暴露给攻击者,所以要防止CSRF一定最好不要用GET。当然POST并不是万无一失,攻击者只需要构造一个form表单就可以,但需要在第三方页面做,这样就增加了暴露的可能性。