验证码不寻常对抗系列1: 双重验证的破解之法
前言
若阁下问我此文意欲何为?答曰: 记录下日常渗透中遇到一些特殊验证码绕过Cases并集成一个系列发布到公众号作分享,同时,非常欢迎师傅找我进行与验证码绕过相关的技术交流。
验证码场景分析
某天偶遇一套比较小众的业务网关系统,看到验证码那么简单,反手一波逻辑小漏洞无果(后端判断验证码参数不能为空且会对已使用验证码注销,即无法重用)
验证码请求和验证逻辑是非常明确的。
第一步/xxx/captcha
接口生成验证码,返回两个参数id
和captcha
, 其中id
是验证码的标识,captcha
是验证码的图片二进制Base64
第二步/xxx/login
验证登录逻辑,captchaId
和captcha
需要同时验证两个参数,并且captchaId
来源于上一个请求包。
绕过思路
利用: captcha-killer-modified 项目进行绕过
https://github.com/f0ng/captcha-killer-modified/releases/tag/0.24.4
1.将请求包发送到 captcha panel
点击获取程序会自动识别出验证码说明提取成功
接下来我们利用响应提取功能: "id":"(.*?)"
正则匹配id即可获取到标识:@captcha-killer-modified@
2.配置验证码结果
由于这个验证码比较简单,利用ddocr库就可以实现99%的识别率, 作者提供的codereg脚本在PY3存在问题,自己改了下。
requirements.txt
1
aiohttp==
3.8
.3
2
aiosignal==
1.3
.1
3
async
-timeout==
4.0
.3
4
attrs==
23.2
.0
5
certifi==
2024.2
.2
6
charset-normalizer==
2.1
.1
7
coloredlogs==
15.0
.1
8
ddddocr==
1.4
.11
9
flatbuffers==
23.5
.26
10
frozenlist==
1.4
.1
11
humanfriendly==
10.0
12
idna==
3.6
13
mpmath==
1.3
.0
14
multidict==
6.0
.5
15
numpy==
1.26
.4
16
onnxruntime==
1.17
.1
17
opencv-python-headless==
4.9
.0
.80
18
packaging==
23.2
19
Pillow==
9.5
.0
20
protobuf==
4.25
.3
21
requests==
2.31
.0
22
sympy==
1.12
23
urllib3==
2.2
.1
24
yarl==
1.9
.4
codereg.py
1
# -*- coding:utf-8 -*-
2
# author:f0ngf0ng
3
# @Date: 2022/3/11 下午1:44
4
import
argparse
5
import
ddddocr
# 导入 ddddocr
6
from
aiohttp
import
web
7
import
base64
8
9
print(
10
"欢迎使用captcha-killer-modified服务端脚本,项目地址:https://github.com/f0ng/captcha-killer-modifiedn谷歌reCaptcha验证码 / hCaptcha验证码 / funCaptcha验证码商业级识别接口:https://yescaptcha.com/i/bmHz3Cnn"
)
11
parser = argparse.ArgumentParser()
12
13
parser.add_argument(
"-p"
, help=
"http port"
, default=
"8888"
)
14
args = parser.parse_args()
15
ocr = ddddocr.DdddOcr()
16
port = int(args.p)
17
18
auth_base64 =
"f0ngauth"
# 可自定义auth认证
19
20
21
# 识别常规验证码
22
async
def
handle_cb2
(request)
:
23
if
request.headers.get(
'Authorization'
) !=
'Basic '
+ auth_base64:
24
return
web.Response(text=
'Forbidden'
, status=
'403'
)
25
# print(await request.text())
26
img_base64 =
await
request.text()
27
img_bytes = base64.b64decode(img_base64)
28
# return web.Response(text=ocr.classification(img_bytes)[0:4]) 验证码取前四位
29
# return web.Response(text=ocr.classification(img_bytes)[0:4].replace("0","o")) 验证码取前四位、验证码中的0替换为o
30
res = ocr.classification(img_bytes)
31
print(res)
32
33
return
web.Response(text=ocr.classification(img_bytes)[
0
:
10
])
34
35
36
# 识别算术验证码
37
async
def
handle_cb
(request)
:
38
zhi =
""
39
if
request.headers.get(
'Authorization'
) !=
'Basic '
+ auth_base64:
40
return
web.Response(text=
'Forbidden'
, status=
'403'
)
41
# print(await request.text())
42
img_base64 =
await
request.text()
43
img_bytes = base64.b64decode(img_base64)
44
res = ocr.classification(img_bytes).replace(
"="
,
""
).replace(
"?"
,
""
)
45
print(res)
46
if
'+'
in
res:
47
zhi = int(res.split(
'+'
)[
0
]) + int(res.split(
'+'
)[
1
][:
-1
])
48
print(zhi)
49
return
web.Response(text=str(zhi))
50
elif
'-'
in
res:
51
zhi = int(res.split(
'-'
)[
0
]) - int(res.split(
'-'
)[
1
][:
-1
])
52
print(zhi)
53
return
web.Response(text=str(zhi))
54
elif
'*'
in
res:
55
zhi = int(res.split(
'*'
)[
0
]) * int(res.split(
'*'
)[
1
][:
-1
])
56
print(zhi)
57
return
web.Response(text=str(zhi))
58
elif
'x'
in
res:
59
zhi = int(res.split(
'x'
)[
0
]) * int(res.split(
'x'
)[
1
][:
-1
])
60
print(zhi)
61
return
web.Response(text=str(zhi))
62
elif
'/'
in
res:
63
zhi = int(res.split(
'/'
)[
0
]) / int(res.split(
'/'
)[
1
][:
-1
])
64
return
web.Response(text=str(zhi))
65
else
:
66
return
web.Response(text=res)
67
68
69
app = web.Application()
70
app.add_routes([
71
web.post(
'/reg2'
, handle_cb),
# 识别算数验证码
72
web.post(
'/reg'
, handle_cb2),
# 识别常规验证码
73
])
74
75
if
__name__ ==
'__main__'
:
76
web.run_app(app, port=port)
安装执行
1
# 安装项目依赖
2
pip3
install -r requirement.txt
3
# 直接执行
4
python3 codereg.py -p
10010
3.配置验证码识别接口
导入模版库
修改模版为你正在运行的接口,可以配置Basic认证,但本地用不用考虑这些。
点击识别,如果出现正确识别结果,说明成功。
可以看到成功率很高。
灵活运用识别结果
1.在重放器Reapeater使用
@captcha-killer-modified@ -> 对应验证码的标识即正则从相应包提取的结果
@captcha@ -> 对应验证码识别的结果
1
username=admin&password=admin&captchaId=
@captcha
-killer-
modified@
&captcha=
@captcha
@
你可以多重放几次,看看有没有提示验证码错误,完全没有问题。
当然你也可以在Logger++看到请求最终发送的值。
2.在Intruder中进行爆破
无论在哪里使用如果需要用到识别和提取结果,都需要勾选是使用该插件,否则没办法hook关键字替换。
配置集束模式同时爆破用户名和密码
调整速率为1并发,防止过快,导致请求出错。
配置用户名字典
1
admin
2
test
配置密码字典
1
admin
2
test
3
123456
4
111111
5
admin@123
6
admin@111
7
admin888
这样设置尝试14个请求,只有一个验证码出错,效果还算可以。
一些问题
1.不支持较高并发,比如5并发就会出现全部错误的情况,可以改进的!
2.面对一些更加复杂的场景可能还是不够。
3.识别出错的情况,没有进行hook重试等比较准确的保底策略。
除了一些小问题,剩下都是数不尽的对项目作者和其他相关人员的赞美,正因为淋过雨所以想为别人撑伞。
原文始发于微信公众号(一个不正经的黑客):验证码不寻常对抗系列1: 双重验证的破解之法
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论