字数 1973,阅读大约需 10 分钟
前言
为了方便讲解,本系列引入了一个主人公——王小明。他刚刚通过面试,以外包的形式进入了一个甲方公司,成为了安全部门的一个初级人员,负责漏洞测试、写漏洞报告和监督开发修复。
本来想写是正式职工的,但感觉不太现实。在某些单位,正式工负责渗透测试挺少的,一般都交给外包来做。
本文主要涉及用户名枚举:
登录流程
一个登录流程会出现哪些漏洞呢?
我们以若依的登录功能为模板,讲一下登录流程中可能存在哪些漏洞,为什么会出现这样的问题,以及如何修复。再次声明:拿若依举例,并不是说若依就存在这些漏洞。其中绝大多数是ruoyi不存在的,是我修改代码来达成漏洞存在
的目的的。
我们把流程抽象化,摒弃多余的部分,其实登录这个过程就是一个认证使用者身份的过程。
-
1. 用户证明自己的身份。 -
2. 系统鉴定身份与用户匹配。有效,则返回凭证。无效,则拒绝。
若依登录页面
若依登录页面:
-
• 账号密码输入框 -
• 验证码
顺带一提,在前后端不分离的若依版本中,你可以选择非字母验证码。访问:https://demo.ruoyi.vip/captcha/captchaImage?type=char [图片] 80961631eb8df732ca93ecb661d6813a.png 你抓包修改验证码的请求,替换成上述URL,然后输入字母验证码也可以登录成功。
用户名枚举
为了方便,我们先把若依的验证码给关了。
测试方法
-
1. 输入存在的用户名,发送 -
2. 输入不存在的用户名,发送 -
3. 对比二者的返回包,看能否辨别用户名是否存在
可以将二者的响应包发送到yakit 对比器中,更方便自己判断
结果如下图,只有时间的区别,说明不存在用户名枚举。
我们来看若依的源码,若依的相关配置信息保存在ruoyi-adminsrcmainresourcesi18nmessages.properties
查看配置,可以看到这些的消息返回值统一
存在用户名枚举
我们知道了返回内容存放的位置,修改字符串,即可看到用户名枚举
此时,用户不存在时
用户存在,密码错误时
数据对比:
漏洞修复
知道了漏洞成因,修复方法也很简单,把用户名不存在
和密码错误
的返回值统一为用户不存在/密码错误
。
以为这就结束了?不,才刚刚开始。
开发修复
这时候,小明把漏洞写成报告,交给开发,告诉他们抓紧时间修复。小明正准备看别的地方时,一个电话打过来了,是产品设计的成员打来的。
产品设计A:听说你要修改这个地方?小明(点头):没错,这里存在用户名枚举漏洞,要把错误的返回值修改成统一的。产品设计A:那用户体验怎么办?小明(疑惑):用户体验?这是个漏洞。产品设计A:我看你报告里写的是一个低危,那修不修都没关系吧。小明(疑惑):……
王小明应该怎么做?开发修 or 不修?答案是 or 。漏洞是否要修复,不是王小明该决定的,而是将产品设计A的诉求,以及漏洞的修和不修的危害告诉领导,由领导拍板。当然,硬气一点的,可以直接让对方去找领导,你没必要理他。
王小明把用户名枚举的问题告知领导,领导大腿一拍:“修,为什么不修?上次攻防演练,我们刚被弱口令打进来了。”
有了领导拍板,产品设计A让步了。开发修改完成,发版,联系王小明复测。
漏洞复测
此时,漏洞修复了,不管输入的用户名是否存在,返回的都是用户不存在/密码错误
。王小明点点头,正准备表示通过的时候,他的手突然多点了几下。紧接着,用户名存在的响应包中返回密码错误次数达到最大
。
王小明的手颤抖了一下。他赶紧试了不存在的用户名,发了10次包,均提示用户不存在/密码错误
。
哦吼~
根据密码最大错误次数判断用户名是否存在
这种比较缺德。一般来说,你可以尝试先输入常见的用户名以及不存在用户名。看是否会有密码错误次数达到最大
的提示。如果不存在的用户名,没有这个提示。存在的用户名有这个提示,那也能爆破。只是会影响业务。而且这种一般不好动。因为,这比上一种更影响用户体验。
我们看一下对若依的爆破admin
snjnjaa
因为在设计的时候,不存在的用户名直接返回用户不存在/密码错误
,而没有记录密码错误的情况。这在流程上是一种优化,但在控制用户名枚举上面,就有点尴尬。
锁用户这种行为不是很好,爆破次数多了,很容易变成拒绝服务
了,影响用户体验。从实际出发,我感觉还是封禁IP+验证码好一些,不过也是治标不治本。或者摒弃密码,改用微信扫码,或者的手机号+短信的形式。
让不存在的用户,也计算次数进行封禁com.ruoyi.framework.web.service.UserDetailsServiceImpl#loadUserByUsername借助若依采用的Redis,我们把相关代码从 com.ruoyi.framework.web.service.SysPasswordService#validate 取出来
此时
不过,不建议这么做。遇到找事的,Redis的性能可能吃不消。
新的问题
他陷入了纠结,因为此时用户名枚举并没有修复。因为攻击者完全可以对一个用户名多爆破几次,出现密码锁定的就是存在的,没锁的就是不存在的。
王小明只能继续联系开发。这次产品设计A没意见,这个修改对他没有影响。但是开发不干了。开发:这个设计流程就是这样的,我是按照流程走的。先校验存不存在用户名,不存在就拒绝。王小明提出建议:可以记录爆破的账号的次数,不管账号是否存在,只要爆破超过N次,都提示账号锁定。开发:这么保存会影响数据库性能。这个系统平时用的人很多,并发量很大。王小明坚持:可是用户名枚举并没有修复。
此时,开发不说话了。正当王小明以为事情结束时,坐在他前排的领导忽然接到了一个电话,是这个项目的开发负责人。开发负责人大吼,声音大的跟手机开免提了一样:你提的单子只让修改用户不存在的返回信息,我就问你我修没修吧。怎么又说不行了?领导转头看向小明。小明解释了一通,用户名枚举还存在。开发负责人:我问你单子里有没有提修改最大报错次数。影响业务性能了,是你负责还是我负责?而且这个系统外面有风控。领导汗流下来:知道了。挂完电话,领导对你说:这个漏洞算他们过了。反正是一个低危,能有多大危害。王小明:好的。
原文始发于微信公众号(进击的HACK):业务安全之登录流程 01 用户名枚举
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论