补充~~~在说『登录 CSRF』之前先说说『CSRF(Cross Site Request Forgery)』,即跨站请求伪造。
举一个真实发生过的例子,攻击者先在自己网站上创建一个页面,这个页面有一个表单,表单的提交路径却是新浪微博发新微博的地址,并且这个页面有 JS 可以让页面加载完毕的时候就自动提交表单的内容。攻击者再想各种办法,骗新浪微博某些大 V 去点击这个页面的链接,受害大 V 只要在新浪微博是登录状态,表单的内容就会成功被发送。如果攻击者的页面通过 iframe 等方式隐藏页面,大 V 们可能『被动』发了微博都没有任何感知。防守也不难,页面显示表单时,给台设备分配不同的随机码,而处理表单提交的时候,需要验证随机码是否一致。而随机码跟设备是绑定的,攻击者不可能猜的出来受害者的设备的随机码是什么,从而防止了 CSRF 攻击。而这个随机码,就叫 CSRF Token。
再说回『登录 CSRF』这个话题。在过去相当长一段时间里,我认为登录表单是不需要 CSRF 保护的。我的想法是,让受害者在不知情的情况下做一些对攻击者有意义的『操作』才是 CSRF 存在的意义(比如让大 V 发布一些营销类的信息)。骗一个人去登录,意义何在呢?
后来专门上网查阅了一下,才发现事情没这么简单,原来还可以这么玩儿,依然以微博为例子:
- 攻击者在新浪微博创建一个帐号
- 通过登录 CSRF 让被攻击的用户在不知情的情况下登录微博
- 不明真相的受害者如果不注意,还以为是自己的微博账户,创建了相册,并且上传了一些非公开的照片
- 攻击者再登录此账户,就可以随意浏览受害者刚上传的非公开照片了
虽然不如普通 CSRF 造成的危害直接,不过对于注重用户隐私的网站,是没有理由不防此种攻击的。
解决方法
解决方法: Cookies Hashing:每一个表单请求中都加入随机的Cookie,由于网站中存在XSS漏洞而被偷窃的危险。
在Jsp文件头引入 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 在登录的jsp中添加 <% //增加随机数,解决 CSRF 漏洞 String uuid = UUID.randomUUID().toString().replaceAll("-", ""); request.getSession().setAttribute("randTxt",uuid); //设置cookie只读 String sessionid = request.getSession().getId(); response.setHeader("SET-COOKIE", "JSESSIONID=" + sessionid + "; secure ; HttpOnly"); %> form表单中添加一个隐藏域:Input <input type="hidden" name="randSesion" value = "<%=request.getSession().getAttribute("randTxt")%>" /> 或者~在表单内增加了一个隐藏域,再登陆页面增加,然后扫描软件在扫描就扫描不出来了。如下: <form id="fm" class="layui-form layui-form-panel" style="height: auto"> <input type="hidden" name="token" value="uu-90:pp:ll-qq" /> </form> 注:login.html页面中的所有form标签下都添加上面那一个input 的隐藏域
CSRF的利用与原理
0x01 攻击条件
1、受害者在受害网站处于已登录状态
2、受害者需要打开恶意站点
0x02 漏洞成因
通俗来讲,在进行请求操作的时候,服务端并没有判断客户端发送的请求是否是用户本身发送的。服务端接受到了来自某个cookie发送来的请求,就当成一个正常的请求来执行。但是可能是网站本身存在CSRF漏洞。
0x03 漏洞危害
这里就举例说的,这里只是部分
1. 配合XSS漏洞可造成蠕虫。
2. 更改用户密码
3. 更改(商城)用户收货地址
一切用户可以操作的,黑客都可以操作。只需要构造PoC让受害者点击。
通俗点就是说,B以A的身份执行了A可以执行的操作,当然,我们这里B是黑客,A是受害者。
0x04 漏洞修复
1、 通过token或者session来判断当前用户身份
2、 敏感操作需要验证码,更改密码需要验证老密码。(导致构造PoC时无法构造,如果知道你密码,直接进后台了,为什么还要用CSRF)
旁白:不过这样用户体验就有点不好了,但是遇到安全问题,用户体验就得给安全让路了。