作者 | 一线卑微安服仔

本篇是对今年渗透测试遇到的验证码问题进行一下总结,各位师傅共同学习,若有不足或建议,也望大家及时提出。
下面总结大部分照片实例,均已进行脱敏处理,可放心食用。

验证码介绍

本质上是为了区分用户是计算机还是人的一种全自动工具(此处需要注意是全自动,因此有部分的验证码不符合这种定义),并且还可以证明目标的身份。

现在的很多大厂,普通漏洞的数量已经减少了很多,但是逻辑漏洞是很难避免,因此我们在测试过程中应该要更加注重这一方面的检查。

通常通过设置验证码,解决以下几种问题:

账户暴力破解、刷票等。

防止爬虫(访问频率或者频次超限后需要输入验证码)。

避免垃圾邮件、短信轰炸。

防止DDOS攻击。

敏感操作的二次确认

验证码问题分类

可粗略分为一下几类:

常见验证码类型

1. 文本验证码与题库验证码

以上两种验证码其实不符合验证码的设定,只有自动生成的问题才能称之为验证码。
文本验证码中的纯文本验证码通常可以在html网页源代码中找到,再或者是这种文本验证码出现的是固定格式的问句,例如:今天星期几或者是一些数字运算,这种文字验证码都是从题库里选择出来的,数量有限。破解方式也很简单,多刷新几次,建立题库和对应的答案。
题库验证码整体相同,但是题量相较于文本验证码大很多,有的还存在一定运算量,但是处理方式基本相同,除了上面介绍的方式,也可以通过正则的方式从网页爬取问题,才寻找匹配的答案进行破解。
现在这两种验证码已经基本绝迹了,很少人继续使用。

2. 语音验证码

语音验证码或呼叫转移的方式,成本过高,采用此方式的企业较少。

3. 新一代验证码

例如Google reCaptcha、点选验证码、滑动验证码,都可以使用Python Selenium 用户行为模拟的方式来进行绕过。这一块绕过难度较大,本篇先不进行讲解。
部分的滑动验证码由于设定的缺陷可以通过“session参数重复校验“的漏洞进行绕过。

4. 图形验证码与短信/邮箱验证码

图形验证码和短信/邮箱验证码为本篇重点,也是在平日渗透测试过程中遇到最多的验证码类型,因此本篇会着重对这两种验证码的安全问题进行介绍。

常规的验证码安全问题

在常规的渗透测试中通常会出现以下14种类型的问题

1.简单的图文识别

案例说明:

漏洞说明:

由于这两处的验证码过于简单可以轻易的被识别工具直接识别。

从标准来说,由于此处采用的是纯色背景,并且背景不存在无规律的点或线条,因此可以直接判断为存在问题。

攻击手法:

常规可以使用工具:PKAV HTTP Fuzzer进行识别,也可以使用Burp插件进行识别(部分需收费),详情可参考backlin师傅的文章:
https://www.cnblogs.com/backlion/p/14736151.html

下为识别工具的部分截图:

修复方式:

鉴于现在图形识别的能力越发强大,建议图形验证码也应该要同步进行升级。

尽量多采用扭曲、变形、干扰线条、干扰背景色、变换字体等方式来加大验证码的难度。(PS:尽管用户日常体验感很差)

2.验证码空值绕过

案例说明:

后台登陆请求:submit=%E6%8F%90%E4%BA%A4&username=admin&password=admin123§156§&expire=&verify=7v111e7&submit=+%E7%99%BB+%E9%99%86+
通过清空此处的验证码字段,服务端就不会验证验证码了,就可以继续进行常规的暴力破解。

攻击手法:

尝试删除验证码字段,观察服务端是否会提示报错

修复方式:

对验证码字段进行强校验,先进行验证码的核对,若出现字段缺失应及时报错。

3.前端校验+无效校验

案例说明:

案例1:这里是前端校验,因此可以直接进行爆破(密码字段采用的是MD5-32位小的方式进行加密,具体操作方式不再赘述)。
这种情况就是属于设置了但是没完全设置。

案例2:
获取短信验证码后,随意输入验证码,直接输入两次密码,可成功更改用户密码,没有对短信验证码进行验证,可能导致CSRF等问题。

案例3:
首先通过利用自己的手机号接收验证码进行验证,下一步跳转到一个设定密码的页面抓包,篡改手机号,使用任意手机号进行注册。

案例2.3的图片引用 https://cloud.tencent.com/developer/article/1459233

攻击手法:

若出现前端校验,可以直接通过抓包绕过。

一般在新上线的系统中,容易出现无效校验,也可以直接进行绕过。

与此同时,需要注意案例3的这种情况,若将身份验证与密码修改(账户注册等操作)的过程分开,就容易导致验证无效,例如:任意用户注册、任意账户密码修改等漏洞。

修复方式:

禁止前端校验或者无效校验。

验证码和用户名、密码需要一次性、同时提交给服务器验证,以此来保持业务一致性。

4.验证码可控

案例说明:

案例1:
在这里登录的过程中,会先发送含有明文验证码的数据包,因此可以直接利用。

数据包情况

案例2:
有时候会对报文的内容进行编码(弱加密)处理,也可视为明文。

案例3:
这里验证码直接出现在源码中。

案例4:
这个报文是通过结合时间戳的方式构造验证码,通常为时间戳的后4-6位。
但是不局限于时间戳,可能为数据包的其他参数。

攻击手法:

截取登录时全部的数据包,查找是否有验证码信息的违规泄露。
如果存在就可以通过创建脚本,从而来结合泄露验证码的位置,再进行暴力破解。

修复方式:

禁止验证码已明文或者编码(弱加密)的方式出现在响应包或者源码中。

5.验证码存在规律

漏洞说明:

例如5次后重复,或是等差数列等一系列可以直接预测到的验证码。

攻击手法:

请求10次观察验证码是否随机生成,查看是否存在一定的规律。

修复方式:

验证码一定要采用随机生成的方式。

6.验证码爆破

案例说明:

此处可以直接遍历,以此爆破验证码。

漏洞说明:

这个案例中需要注意的是,此漏洞利用难度较大,风险等级为低危。

具有一定局限性,仅仅适用验证码在成功后会销毁,但是验证码错误的情况下不会销毁。

但是有种情况可以直接利用,就是当短信验证码的服务端未对验证时间、次数进行限制的时候,并且验证码为4-6位数字组成,则存在被爆破的可能。

攻击手法:

标记验证码的字段以及需要爆破的字段(例如密码字段),一般会使用Cluster bomb模式进行爆破。

输入手机号获取验证码,输入任意短信验证码,发起请求,抓包,将短信验证码字段设置成payloads取值范围为000000-999999进行暴力破解,根据返回响应包长度判断是否爆破成功。

修复方式:

不管验证码是不是输入正确,都应该及时销毁验证码。

7.验证码复用

案例说明:

由于这里的验证码反复利用,因此可以直接进行暴力破解。

漏洞说明:

这是验证码安全里最常见的一类安全问题,也是最容易遗漏的一类。

一般来说,验证码是与Session绑定的,Session生成时,往往也伴随着验证码的生成和绑定。

在访问页面时,接口的请求和验证码的生成通常是异步进行的,这使得两个功能变得相对独立。也就意味着我们如果仅请求接口,而不触发验证码的生成,那么验证码就不会变化。

并且在考虑安全时,开发人员的关注点往往在 验证码校验 是否通过,通过则进入业务流程,不通过则重新填写,而忽视了 这个用户是否按照既定的业务流程在走(接口访问与验证码生成是否同时进行),验证码是否被多次使用了。

攻击手法:

观察验证码是否会变化,如果不变化可以直接进行爆破。

当这类漏洞出现在注册界面/忘记密码的时候,可以通过使用这类漏洞构成新的漏洞-用户枚举,从而获取到账号本。

修复方式:

不管验证码是不是输入正确,都应该及时销毁验证码

8.状态码绕过

案例说明:

这里将响应码修改至200,就可以直接绕过限制,获取验证码或者登录后台。

漏洞说明:

验证逻辑存在问题,只识别了响应码,响应包不局限于将500改为200/000,还包括将error改为ok等。

实际操作中建议查看js源码,查看响应码逻辑。

攻击手法:

通过抓包修改响应码

修复方式:

修改验证逻辑,如是否登录成功服务器端返回一个参数,但是到此就是最终验证,不需要再对返回的参数进行使用并作为登录是否成功的最终判断依据。

9.万能验证码

案例说明:

这里可以直接使用0000进行绕过登录。

案例图片引用 乌云

漏洞说明:

像案例中的万能验证码在当前环境下,基本绝迹,很难再遇到了,因此作为了解即可。

但是一些开发中或者是开放才结束的系统需要注意,有可能存在测试手机号,例如15688888888等类似测试、开发人员使用的账户,他们为了方便,仍然存在一定几率出现万能验证码。

攻击手法:

验证码可以使用0000/8888/000000/888888等一系列便于记忆的相同数字进行尝试。

修复方式:

禁止万能密码

10.未授权手机号绕过

案例说明:

大致步骤和上面的响应码绕过差不多,也是通过修改响应码来获取验证码。
(下图中的手机号为随机生成)

1636449576_618a3d2892f34d4289184.png!small?1636449577113

漏洞说明:

这个案例中同样为逻辑验证有问题,可以尝试绕过。

此外还需要注意以下几种情况:

那就是当验证码和手机号未绑定,号码1的验证码,号码2可以使用,这个时候就会导致任意用户密码重置。

此外当验证码一段时期内有效,号码1在一定时间间隔内接到两个验证码,都可以用。

攻击手法:

出现响应码的时候,尝试修改绕过。

当出现验证码和手机号未绑定,可以使用自己手机号收取验证码,并在下一步中将自己的验证码和对方的手机号填上,然后修改对方,并设置新密码。

修复方式:

修改验证逻辑,如是否登录成功服务器端返回一个参数,但是到此就是最终验证,不需要再对返回的参数进行使用并作为登录是否成功的最终判断依据。

在服务器进行有效验证,手机号和验证码在服务器进行唯一性绑定验证。

在服务端限制验证码发送周期,设置时效,限制次数。

11.加密报文绕过

案例说明:

这里可以看到此处的验证码字段已经被加密,但是此处是验证码功能设计缺陷,导致直接使用明文就同样可以通过验证。


转化为明文后发包,可以成功获取响应包

漏洞说明:

这种漏洞利用难度很大,很难直接通过这种漏洞进行暴力破解,属于验证码的功能缺陷类型的漏洞,漏洞定级为低危。

攻击手法:

尝试解密加密的报文数据,查看明文数据是否能被服务器识别。

修复方式:

检查验证码的验证码功能

12.邮件轰炸+短信轰炸

案例说明:

案例1:邮件轰炸
通过直接重放数据包


案例2:
直接重放数据包

1636449825_618a3e21f3cc24c2d4672.png!small?1636449826618
案例3:
这里通过遍历数据包中的其他参数,来构成轰炸

案例4:
此处单一手机号无法重放,但是可以通过遍历其他手机号,构成横向短信轰炸

漏洞说明:

短信轰炸和邮件轰炸具体操作方式基本相同,大体类型也分为轰炸和横向轰炸(特指短信)。

前者可以直接构成对用户的骚扰,而后者由于不能指定单一用户,因此横向轰炸的目的以消耗系统资源为主。(一条短信费用为3-6分钱,实际测试中需要通过客户身份来评估漏洞等级,一些小客户可以提升漏洞等级,但是一些财大气粗的客户可以忽略此项漏洞。)

攻击手法:

常规的利用手法就是直接通过对验证码接口进行重放。

这里有点需要注意,有些系统会限制短时间的大批量爆破,因此可以通过构造延时数据包,例如30秒发包一次。

当数据包中有其他校验参数的时候,就可以遍历其他参数,构造不同的数据包,来发送请求。
实例:
例1:当发送短信的接口为sendSMS4Mobile,尝试修改URL,是否存在其他发送接口,后面通过测试发现sendSMS同样可以发送;
例2:当系统对cookie进行校验的时候,可以先重复登陆获取大量的cookie表,再通过替换cookie进行轰炸
例3:同案例3,替换数据包中的其他参数
例4:当系统对ip进行校验的时候,可以通过代理池的方式进行轰炸,常规的渗透测试不建议使用,罪不至此。

其他骚操作
例1:mobile=13611111111,一天可以发送10次,超过10次今天将不再发送,第二天才可以继续发送。但是,可以通过在手机号前面或后面加上空格又可以发送10次。比如,mobile= 13211111111,前面加个空格,就可以再次发送成功。
例2:通过修改邮箱后面字母的大小写绕过限制。比如:[email protected],当次数达到限制时,将字母修改为大写:[email protected],即可绕过

修复方式:

限制请求频率,错误一定次数,锁定账号一段时间

这里需要注意的是,假如是永久封禁,当攻击者已经获得所有的账户号码(可通过用户名遍历的方式获取),那么可以直接构造数据包,将这些账号批量锁死,从而构成严重的拒绝服务攻击。

13.短信内容自定义

案例说明:
这里由于短信的内容可以直接通过短信进行编辑。

漏洞说明:

当短信内容可以直接编辑时,就会构成严重的钓鱼风险。尤其是出现在金融教育医疗等自身信誉比较高的行业,用户点开恶意链接从而被骗的机率很大。(钓鱼邮件等社工手法也会出一篇文章)

攻击手法:

常规的渗透测试中,不需要过多利用,发现就可以报告了。

攻防对抗中,可以构造通过这种钓鱼方式获取一定信息,有较高的实用价值。

修复方式:

限制邮件内容可以自定义。

14.session参数重复校验

案例说明:

通过遍历length的数值来通过验证码的校验

漏洞说明:

这种类型的漏洞出现几率比较低,属于滑动验证码设计缺陷。

从漏洞定义角度来讲,属于“验证码爆破”,同样是通过遍历数值,当达到正确的数值后就可以通过验证。

攻击手法:

需要抓取多个数据包,包括开头和结尾的数据包,从而来确定数据包范围,以及数据包数值。

通常为长度数值为0-200的整数。具体以实际数据包为准。

修复方式:

不管验证码是不是输入正确,都应该及时销毁验证码。

本文作者:charun