基于图像验证码的安全漏洞

平时测试时,看到下面图片验证码你能够想到什么漏洞测试思路?

image-20230527102353837

验证码的安全问题一直都是逻辑漏洞领域的一大话题,当前的验证码主要分为两类,一是“短信验证码”,一个是”图片验证码“,当然还有谷歌的图片点击等各种各样的验证码,但目前主流的验证码还是这两个。

目前,图片验证码的安全包含了下面的这几个方面,这也是我测短信验证码漏洞的主要方向

  • 图形验证码失效漏洞
  • 图形验证码可被OCR识别漏洞
  • 图形验证码Dos漏洞

这里就是我能想到的常规的短信验证码漏洞,也可能还有其他姿势

本篇文章我们就用这几个漏洞来讨论短信验证码的安全性问题

一、图形验证码失效漏洞

这个是我自己取的一个名字,大概指的就是因为各种原因而造成的图片识别验证码失效的漏洞,因为细说下来太多了,所以在这里就举几个例子让大家感受一下

先来说说图形验证码的验证流程

image-20230531233347774

首先服务器生成图形验证码,下发验证码图片的同时也下发了一段 esion,此时图形验正码正确的文本内容与 Sesion是绑定的。当用户完成验证码填写并提交表单时,服务器校验当能用户提交的验证码文本和用户 Cookie所对应的Session信息。二者如果一致,则验证码验正道过,如果不一致则返回验证码错误。

例1:前端校验失效

有些网站不使用Session而使用JavaScript在用户前端校验码填写是否正确。此时,交互过程会有一个明显的特征,用户填写好验证码之后不需要与服务器端交互即可得到验证码是否填写正确的提示。这说明验证码的验证逻辑在前端,参照前端校验漏洞一节,可以通过修改JavaScript来轻易绕过此类图形验证码。

例2:验证流程不当信息泄露

有些网站在验证用户提交的表单时,并没有首先进行验证码校验,而是先校验用户id是否存在,若不存在返回“用户名不存在”的提示信息。此时,可随意填写图片验证码,来批量遍历出系统中已注册的用户名列表。

例3:验证码刷新配置不当

有些网站的下发验证码接口,仅当用户请求验证码生成接口时才会动态刷新。攻击者可以通过Burp抓包的方法,使用drop阻断请求验证码生成接口的请求,使用固定验证码进行批量破解,这种问题是很常见的

例4:旧接口兼容问题

有些网站之前的登录验证接口是没有验证码的,而后面由于功能需求增加了验证码验证功能。但为了兼容旧按口,就判断用户提交表单是否提交了verifycode 参数,如果没有提交则不进行校验码检验。这种场景下,只需要通过BupSuitc修改请求包,将verifycode参数去掉即可实现绕过。

例5:用户登录次数绕过

一些对用户体验有要求的网站,在登录接口设计时,会首先不弹出验证码。此时,用户登录不需要输入图形验证码,而当用户登录失败超过3次以后,则强制要求用户填写图形验证码。这样做无疑会极大提升用户体验。

但是,有一些网站判断用户登录失败次数,采用 session计数的方式,当用户登录失败超过3次时,攻击者可以清空自己的cookie,要求服务器下发新的 Session以继续登录,此时,仍然是不需要填写验证码的。因而,可以通过自动化工具尝试登录,每次请求都要求服务器生成新的Session,错误次数永远为1,则绕过了图形验证码机制。

以上几种场景,均属于图形验证码失效,希望读师傅们在进行网站安全测试时能够举一反三。

二、图形验证码可被OCR识别漏洞

早期,一些较为清晰的图形验证码是可以使用OCR工具自动化识别的。这也是为什么验证码发展历程中,先后出现了数字验证码、数字加字母验证码、汉字验证码、数学计算公式验证码、滑块拼图验证码、通过旋转使图形满足正确方向的验证码、根据描述从给定图片中拣选图片中包含对应描述物品的验证码(图像拣选验证码)等一系列连入类都难以通过验证的验证码识别技术。

Python脚本

以Python为例,可以利用tesseract进行识别。首先需要下载和编译tesseract,

Tesseract是github上的OCR开源库,今天我将使用Tesseract来进行文字识别。

windows下载可以直接到Github

tesseract-ocr/tesseract: Tesseract Open Source OCR Engine (main repository) (github.com)

对于macOS系统的用户来说,可以使用如下命令来轻松完成安装。

brew install tesseract

然后利用以下Python脚本,在运行前,需要使用pip安装两个库:Pillow、pytesseract,使用如下命令。

pip install Pillow
pip install pytesseract

接下来,将需要识别的验证码图片保存为targetjpg,运行以下脚本。

from PIL import Image
import pytesseract

text = pytesseract.image_to_string(Image.open(r'./target.jpg'),lang='eng') 
print(text)

识别效果如下

Burp插件

Burp中也有很多的插件来实现图片验证码识别的功能,有的是调用的收费接口,也有的是用的免费的,我给大家找了一个免费的Burp验证码识别插件,有兴趣的也可以去看看

插件链接如下

https://github.com/f0ng/captcha-killer-modified

具体的使用也可以咋github上看到

image-20230601151804482

基本上简单的验证码识别还是没问题

随着技术的更新OCR可识别这种情况出现的越来越少了,但并不是没有办法解决,例如人工打码平台,这后面的可是实实在在的人,只是成本较高,但如果受攻击的是一个注册接口,而商家又有“新用户赠送20元新人红包”,那么使用人工打码平台实现批量注册,所获得的利润就是几十倍,几百倍

image-20230601113247355

站在防御者的角度,能做的就是提高攻击成本,当攻击成本大于受益时,就很少人去攻击了。具体的做法还需要多研究。

image-20230601152714508

三、图形验证码Dos漏洞

这个测着最简单,而且遇到的频率也不算很低

当你遇到目标站点使用的是图形验证码时,如果它的url,接口,或者生成请求中存在类似“weight=110&height=70”这种生成图像的设定参数可控(一般右键选择“在新标签页中打开图像”看看验证码的url就行),也就是你能控制图像的大小,那么就很可能存在这个漏洞,例如下面这样

https://www.xxxx.cn/verifyCode.do?width=110&height=40&random=1685175156944

image-20230527161321962

此时如果你将生成图像的参数设置的很大,而生成之后的图像也随之变大(也就是真正可控),例如我们把height参数的值40改为1000,那么效果如下

https://www.xxxx.cn/verifyCode.do?width=110&height=1000&random=1685175156944

image-20230527161636902

注意此时肉眼可见的会发现服务器响应变慢,如果更直观的话就是拿到bp的repeater模块发包,观察response的响应时间和数据量,也就是下面这个位置

image-20230527162556516

而图形验证码的生成大多都基于复杂的图像生成算法,本来就很消耗CPU,GPU性能,此时攻击者再把尺寸增大,就会成倍消耗性能,如果大到一定程度再结合高并发,服务器很有可能瞬间崩溃,也就造成了Dos攻击

SS