任意用户登录漏洞挖掘思路
[TOC]
手机验证码问题导致的任意用户登录
手机验证码导致的任意用户登录主要包括:验证码爆破、验证码明文返回、存在万能验证码、验证码未绑定用户、获取验证码的手机号字段可双写、验证码为空/任意验证码可成功验证等。下面展开来讲。
验证码爆破
当登录流程使用手机验证码登录,没有图片验证码/图片验证码可重用/图片验证码简单可识别且后端没有限制手机验证码验证错误次数时,可以尝试爆破手机验证码登录其他用户。
数字验证码的爆破可以是用burpsuite的Turbo Intruder插件编写脚本实现:
修改代码为下面的代码:
import re
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=30,
requestsPerConnection=30,
pipeline=True
)
#生成六位验证码字典
for i in range(1000000):
number = "{:06d}".format(i)
engine.queue(target.req, number.rstrip())
def handleResponse(req, interesting):
# currently available attributes are req.status, req.wordcount, req.length and req.response
if req.status < 404:
#六位数的验证码爆破结果展示列太多,可根据实际情况自行筛选展示
# res = re.findall('Msg":"(.*?)"',req.response)[0]
# if len(res)>18:
table.add(req)
简单图像验证码爆破可以使用:
- burpsuite中的captcha-killer-modified插件,下载地址如下
目前常用的4~6位数验证码,如果不加其他限制(如访问次数)的情况下,均可以爆破
验证码明文返回
获取手机验证码时,验证码直接在返回包里
存在万能验证码
一般是测试为了功能测试方便,设置了诸如000000、111111、123456之类的万能验证码,项目上线时忘记删掉,导致任意用户登录。
同样的,手机号码同样可能存在万能手机号,如13888888888等,这里提供一个脚本可以生成以138、192等常规开头的手机号码:
# 特殊手机号生成
import itertools
a = ['11111111', '00000000','22222222','33333333','44444444','55555555','66666666','77777777','88888888','99999999','12345678']
b = ['0000','1111','2222','3333','4444','5555','6666','7777','8888','9999']
c = ['0000','1111','2222','3333','4444','5555','6666','7777','8888','9999']
d1 = ['134','135','136','137','138','139','147','150','151','152','157','158','159','178','182','183','184','187','188']
d2 = ['130','131','132','145','155','156','185','186','176','175']
d3 = ['133','149','153','180','181','189','177','192','197']
phone = []
for i, n in itertools.product(d1, a):
_ = f'{i}{n}'
phone.append(_)
for i, n in itertools.product(d2, a):
_ = f'{i}{n}'
for i, n in itertools.product(d3, a):
_ = f'{i}{n}'
for i, n, m in itertools.product(d1, b, c):
_ = f'{i}{n}{m}'
phone.append(_)
for i in d2:
for n in b:
for m in c:
_ = f'{i}{n}{m}'
phone.append(_)
for i in d3:
for n in b:
for m in c:
_ = f'{i}{n}{m}'
phone.append(_)
with open('phone.txt','a') as f:
for i in phone:
f.write(str(i) + '\n')
验证码未绑定用户
一般有以下两种情况:
-
后端仅验证了验证码是否正确,没有验证验证码与获取手机号的对应关系,导致可以先输入自己的手机号A获取验证码,再输入他人手机号B获取验证码后,填写自己手机号A接收到的验证码,达到登录手机号B的目的
-
后端仅验证了手机号与验证码是否正确,并未校验手机号是否为号主本人的,导致可以使用自己的手机号+验证码绕过。常见于用户绑定的功能处,如下例子:
获取验证码的手机号字段可双写
输入手机号获取验证码时抓包,双写手机号字段,使得两个手机号获取到同一个验证码,便可以登录其他用户
输入自己的手机号抓包,将手机字段后面加一个逗号,或者分号;后再加一个手机号,或者双写手机号字段phone=13333333333&phone=18888888888,具体可以展开想象力,下面举个例子:
原字段:phone=13333333333
修改后字段:
- phone=13333333333;18888888888
- phone=13333333333,18888888888
- phone=13333333333&phone=18888888888
当两个手机号均收到一个验证码时大概率漏洞存在。使用自己的手机号便可以任意登录其他手机号。
验证码为空/任意验证码可成功验证
比较奇葩的例子,验证码为空时,手机号正确则成功登录(账号密码登录体系也发现过这种情况,空密码的情况下账号存在即登录)
(补充)由于验证码导致的短信轰炸
说到验证码,这里可以再提一下由于验证码导致的短信轰炸。有以下测试思路:
-
在一些能接受验证码的地方,有一些参数是判定验证码是否获取成功、获取已发送短信的次数。我们测试短信轰炸漏洞的时候可以尝试删除一些参数然后观察响应结果
-
在手机号/邮箱的传参处输入一些特殊符号进行绕过短信限制(如逗号,),有些发送手机号的接口或者邮箱接口当发送时抓包,如果在接受手机参数处没有过滤好一些特殊符号,会导致短信轰炸
这里提供几种思路,这里以手机号15312341234,请求参数为mobile=15312341234为例:
- 手机号前添加国际电话区号,以中国地区为例,即+8615312341234,这样的话服务器就有可能判定为和15312341234是不同的手机号
- 手机号前面加上
空格、86、086、0086、+86、0、00、/r、/n、?、#、!
- 手机号后面加上
+、++、,
-
添加XFF头,有的时候服务器是按照IP地址进行判定的,可以不断更好XFF,实现短信爆破
-
添加多个值或添加多个参数(类似上面的手机号字段可双写)
-
并发请求。可以使用burpsuite进行并发请求,能导致短信轰炸
关于验证码渗透可以移步到我的另一篇文章《验证码渗透总结》
凭证安全问题导致的任意用户登录
凭证泄露
页面缓存被搜索引擎抓取
页面缓存被搜索引擎抓取,搜索引擎直接搜索该域名或者搭配搜索引擎的其他语法。如果发现有登录后的页面被抓取,可以尝试直接访问登录目标账户。谷歌搜索语法:
- site:example.com.cn
httptrace/druid等组件中的凭证泄露
这里先介绍一下httptrace spring和druid
httptrace spring
spring的httptrace端点往往会记录用户的会话信息,若发现spring未授权访问且存在类似端点可以访问的话,可尝试获取用户凭证进行登录
durid
druid的session监控发现有效的会话信息时,可以通过此登录任意用户
httptrace/druid的等组件的凭据泄露,主要是泄露了会话密钥(即session_key、session_token这些),下面再举一个微信小程序官方的sessionkey泄露
微信小程序官方sessionkey泄露
微信小程序官方提供了一套微信快捷登录的登录逻辑:用户授权手机号快捷登录时,会将本地的手机号使用sessionkey和iv进行aes加密,后端解密后返回该手机号的登录凭证。当sessionkey发生泄露时,攻击者便可以伪造手机号登录任意手机号
修改任意手机号,利用sessionkey和iv重新加密数据
成功登录他人账号
其他接口中的信息泄露
这个一般发现于js或者api-docs中的某些特殊接口,例如getToken之类的,有没有取决于开发有没有开发类似的功能接口
凭证伪造
jwt未校验参数/使用弱密钥
当系统使用jwt作为认证字段,且其中关键用户信息字段可以遍历时,若未验参或者使用弱密钥时,便可以将用户信息字段进行更改,删除/爆破弱密钥重新生成签名,到达任意用户登录
jwt未校验参数
删除签名部分(或者更改头部中的alg为none再删除签名),访问登录后的接口成功访问,说明jwt未验参
jwt弱密钥
当jwt使用了弱密钥时,爆破到弱密钥后同样修改jwt中的用户信息字段,使用密钥重新生成签名即可获取到其他用户的jwt字段
弱cookie
系统使用cookie认证,且cookie字段过于简单(如明文、base64加密等),导致可伪造
凭证过早返回
一般正常的登录流程为服务端校验完用户身份后,返回用户凭证,但某些系统由于登录前会有很多的查询用户信息类的功能请求,经常导致在登录验证前就返回了用户凭证。
举例一个金融项目,功能是:输入手机号会先去查询手机号是否为已注册用户,是的话就会进入用户信息查询的逻辑,再跳转登录。在信息查询的阶段过早返回了sessionid,导致任意用户登录。如下:
逻辑漏洞导致的任意用户登录
更改登录type
部分系统有免密登录/快捷登录之类的功能,只要一个账号就能登录,当遇到登录数据包中含有type之类的字段时,可以尝试此方法
账号数据覆盖
常见于账号信息更新处,例如修改手机号、账户重新绑定、修改账号等功能点处
以修改手机号为例,此处修改需要输入新手机号与新手机号的验证码
若修改请求中的oldmobile字段为其他手机号,就能将其他用户的账户数据覆盖到新手机号中,达到任意用户登录