业务安全之登录流程 01 用户名枚举

前言

为了方便讲解,本系列引入了一个主人公——王小明。他刚刚通过面试,以外包的形式进入了一个甲方公司,成为了安全部门的一个初级人员,负责漏洞测试、写漏洞报告和监督开发修复。

本来想写是正式职工的,但感觉不太现实。在某些单位,正式工负责渗透测试挺少的,一般都交给外包来做。

本文主要涉及用户名枚举:
801686de02a2380a19f6f84d4aad988d.png

登录流程

一个登录流程会出现哪些漏洞呢?

我们以若依的登录功能为模板,讲一下登录流程中可能存在哪些漏洞,为什么会出现这样的问题,以及如何修复。
再次声明:拿若依举例,并不是说若依就存在这些漏洞。其中绝大多数是ruoyi不存在的,是我修改代码来达成漏洞存在的目的的。

我们把流程抽象化,摒弃多余的部分,其实登录这个过程就是一个认证使用者身份的过程。

  1. 用户证明自己的身份。
  2. 系统鉴定身份与用户匹配。有效,则返回凭证。无效,则拒绝。

若依登录页面

f97fbd60fa73349c558456bb927db9d7.png

若依登录页面:

  • 账号密码输入框
  • 验证码

顺带一提,在前后端不分离的若依版本中,你可以选择非字母验证码。
访问:https://demo.ruoyi.vip/captcha/captchaImage?type=char
80961631eb8df732ca93ecb661d6813a.png
你抓包修改验证码的请求,替换成上述URL,然后输入字母验证码也可以登录成功。

用户名枚举

为了方便,我们先把若依的验证码给关了。
ccdc6ddc38eb9bcc602bd39550be9903.png

测试方法

  1. 输入存在的用户名,发送
  2. 输入不存在的用户名,发送
  3. 对比二者的返回包,看能否辨别用户名是否存在

可以将二者的响应包发送到yakit 对比器中,更方便自己判断
发送到对比器

结果如下图,只有时间的区别,说明不存在用户名枚举。
33ca2a9eabbc0ead70b9c605c10e4b37.png

我们来看若依的源码,若依的相关配置信息保存在
ruoyi-admin\src\main\resources\i18n\messages.properties

查看配置,可以看到这些的消息返回值统一
87e8adea7fca69911e5ed49e10494552.png

存在用户名枚举

我们知道了返回内容存放的位置,修改字符串,即可看到用户名枚举
37182e6863ee80399abe8b1746535845.png

此时,用户不存在时
e4643023ceb6d6bcffac7cc89a97d758.png
用户存在,密码错误时
c0feadbbb4e05a2a495f383df00f6115.png
数据对比:
3db6a3fdd5f84cd24772ae163163b513.png

漏洞修复

知道了漏洞成因,修复方法也很简单,把用户名不存在密码错误的返回值统一为用户不存在/密码错误

以为这就结束了?不,才刚刚开始。

开发修复

这时候,小明把漏洞写成报告,交给开发,告诉他们抓紧时间修复。
小明正准备看别的地方时,一个电话打过来了,是产品设计的成员打来的。

产品设计A:听说你要修改这个地方?
小明(点头):没错,这里存在用户名枚举漏洞,要把错误的返回值修改成统一的。
产品设计A:那用户体验怎么办?
小明(疑惑):用户体验?这是个漏洞。
产品设计A:我看你报告里写的是一个低危,那修不修都没关系吧。
小明(疑惑):……

王小明应该怎么做?开发修 or 不修?
答案是 or 。
漏洞是否要修复,不是王小明该决定的,而是将产品设计A的诉求,以及漏洞的修和不修的危害告诉领导,由领导拍板。
当然,硬气一点的,可以直接让对方去找领导,你没必要理他。

王小明把用户名枚举的问题告知领导,领导大腿一拍:“修,为什么不修?上次攻防演练,我们刚被弱口令打进来了。”

有了领导拍板,产品设计A让步了。
开发修改完成,发版,联系王小明复测。

漏洞复测

此时,漏洞修复了,不管输入的用户名是否存在,返回的都是用户不存在/密码错误
王小明点点头,正准备表示通过的时候,他的手突然多点了几下。紧接着,用户名存在的响应包中返回密码错误次数达到最大

王小明的手颤抖了一下。他赶紧试了不存在的用户名,发了10次包,均提示用户不存在/密码错误

哦吼~

根据密码最大错误次数判断用户名是否存在

这种比较缺德。一般来说,你可以尝试先输入常见的用户名以及不存在用户名。看是否会有密码错误次数达到最大的提示。
如果不存在的用户名,没有这个提示。存在的用户名有这个提示,那也能爆破。只是会影响业务。
而且这种一般不好动。因为,这比上一种更影响用户体验。

我们看一下对若依的爆破
admin
def46f703d096cfe2340a85ae201c1ac.png

snjnjaa
5227578e82e896c7f23feac2e1452b75.png

因为在设计的时候,不存在的用户名直接返回用户不存在/密码错误,而没有记录密码错误的情况。
这在流程上是一种优化,但在控制用户名枚举上面,就有点尴尬。

锁用户这种行为不是很好,爆破次数多了,很容易变成拒绝服务了,影响用户体验。
从实际出发,我感觉还是封禁IP+验证码好一些,不过也是治标不治本。
或者摒弃密码,改用微信扫码,或者的手机号+短信的形式。

让不存在的用户,也计算次数进行封禁
com.ruoyi.framework.web.service.UserDetailsServiceImpl#loadUserByUsername
借助若依采用的Redis,我们把相关代码从 com.ruoyi.framework.web.service.SysPasswordService#validate 取出来
f3539bbc9ff5f7f9cda70acd088a7cf6.png

此时
787ba8831abd265a5f7a08055391ab5d.png

不过,不建议这么做。遇到找事的,Redis的性能可能吃不消。

新的问题

他陷入了纠结,因为此时用户名枚举并没有修复。因为攻击者完全可以对一个用户名多爆破几次,出现密码锁定的就是存在的,没锁的就是不存在的。

王小明只能继续联系开发。
这次产品设计A没意见,这个修改对他没有影响。
但是开发不干了。
开发:这个设计流程就是这样的,我是按照流程走的。先校验存不存在用户名,不存在就拒绝。
王小明提出建议:可以记录爆破的账号的次数,不管账号是否存在,只要爆破超过N次,都提示账号锁定。
开发:这么保存会影响数据库性能。这个系统平时用的人很多,并发量很大。
王小明坚持:可是用户名枚举并没有修复。

此时,开发不说话了。
正当王小明以为事情结束时,坐在他前排的领导忽然接到了一个电话,是这个项目的开发负责人。
开发负责人大吼,声音大的跟手机开免提了一样:你提的单子只让修改用户不存在的返回信息,我就问你我修没修吧。怎么又说不行了?
领导转头看向小明。
小明解释了一通,用户名枚举还存在。
开发负责人:我问你单子里有没有提修改最大报错次数。影响业务性能了,是你负责还是我负责?而且这个系统外面有风控。
领导汗流下来:知道了。
挂完电话,领导对你说:这个漏洞算他们过了。反正是一个低危,能有多大危害。
王小明:好的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值