CSRF的攻击、防御与挖掘
知识要点:
浏览器发送请求的特性
Cookie与session
0×01 攻击篇
正常用户:userA
存在CSRF漏洞的网站:siteA
恶意用户:userB
恶意网战:siteB
1. 先聊一聊cookie
通常我们访问网站时用到的协议为HTTP/HTTPS,他们一种没有状态的协议,用户A、用户B、用户C…..同时访问一个url,而网站是无法确认是谁访问的它。上面这种说法比较模糊,举个显而易见的例子:用户A将某个物品添加到购物车中,用户B也将某个物品添加到购物车中,如果单纯使用这种无状态的协议,那么问题来了,怎么区分用户A和B的购物车呢?
早先时候Cookie是用来解决这种问题的,但因为Cookie存储在客户端很容易被利用,因而后来发展为Session+Cookie的方式。用户A访问购物网站,那么购物网站分给用户A一个标识session_id=userA;用户B访问购物网站,那么同样的,购物网站分给用户B一个标识session_id=userB。session_id存储在浏览器的Cookie中之后,用户A和B之后每次访问网站,都要在HTTP的请求头中附加上这个标识,因而购物网站可以通过这个标识来区分每个用户的购物车。
2. 重点
浏览器访问一个网站,会主动的加上目标网站的Cookie(这是浏览器的一个特性)
3. 一个示例
因为网站服务端是通过session_id来标识每个用户的,session_id存储在浏览器的Cookie中,而浏览器访问目标网站时,又会带上目标网站的Cookie。那么问题来了,用户A访问购物网站,通过用户名和密码获得了自己的一个session_id,并存储在了Cookie中。那么如果这时,用户B构造了一个添加某商品至购物车,并付款的链接,将这个链接发送给了用户A。用户A在点击这个链接后,浏览器会自动带上用户A的存储在浏览器中的Cookie去请求访问这个URL。因而造成了用户A在非主动的情况下购买某商品的情况。这就是一个简单的CSRF(Cross Site Request Forgery,跨站请求伪造)攻击
4. 攻击成功的原因
造成这次攻击成功的原因有以下几点:
用来标识用户A的身份的Cookie在点击链接时依然存在
浏览器访问URL会自动带上目标站点的Cookie
服务端过于相信Cookie,没有做二次验证。
简而言之:CSRF攻击是恶意用户B通过冒用正常用户A的身份做了一个操作,并没有获得正常用户A的Cookie。从这点上来说,相比于XSS的危害要小些,因为恶意用户B可以通过XSS直接获得正常用户A的Cookie,并在自己的电脑上通过Cookie登录网站。
0×02 防御篇
那么如何防御呢?
1. 个人:
在访问重要网站时,不随意点开链接
退出网站时,注意清除Cookie
2. 网站开发人员:
上面的描述,可以得出解决问题的重点是在服务端验证完cookie后,还要再加一次验证,无论这个验证方式是什么,满足一个要求即可:
浏览器直接访问这个恶意攻击者B构造出来的URL不会自动的带上这个验证方式的值
大概的思路:
1)验证码/密码:
正常用户A通过浏览器直接访问这个URL,跳转后,返回一个输入验证码/密码的响应,而恶意攻击者仅仅通过CSRF是无法获得这个值的,因而可以防范CSRF攻击
各大银行及支付功能的应用,通常我们在转账或者付款的时候,都要求我们输入一个密码或指纹就是这么一个道理。
2)双重Cookie:
①正常用户A通过用户名和密码访问网站,得到一个cookie存在浏览器中。
②如果用户访问网站中比较敏感的功能(比如添加商品至购物车),服务端在返回响应的时候,会将之前分给用户A的cookie值在页面中的form表单中存一份。
③正常用户A正常访问网站时,form表单中和Cookie中的cookie值是相同的;而如果正常用户A通过恶意攻击者构造的URL访问站点时,Cookie中有标识用户A的cookie值,但是表单中或者请求参数中并没有或没有一个正确的cookie值。因而服务端通过对比form表单或者请求参数中的cookie值与Cookie中的cookie值是否相同来判断是否收到了CSRF攻击。
3)csrftoken:
和双重cookie的原理相同,不过form表单或者请求参数中的不再是标识用户身份的cookie值,而是将用户身份标识符cookie值、时间戳、有效期等一系列信息通过某个函数得出的一个值。
如django:
0×03 挖掘篇
理论上讲,在提交表单或者GET请求的地方,凡是没有用户进行二次验证或没有csrftoken(其他网站可能不叫csrftoken)的地方大概率存在csrf漏洞。
乌云白帽子