在最近的一次渗透测试项目中,笔者遇到了一个安全机制较为完善的小程序。初步分析发现,其通信协议采用了国密算法进行请求与响应的加密,同时集成了时间戳防重放、HASH校验防篡改等多重防护。此外,登录环节依赖wx.login接口获取的一次性code,进一步增加了安全复杂度。
加解密机制分析
首要任务是厘清其加密算法。通过对比多次请求的加密数据,发现密文每次均不相同,这提示加密过程中存在动态变量。
通过搜索SM4、encrypt等关键词,可以快速在js代码中定位到加密函数。在加密函数处设置断点,观察多次请求时传入的参数变化,发现加密密钥是固定的,但待加密的明文数据本身每次都在变化。
因此,解决问题的关键在于还原完整的加密流程。值得注意的是,此处实现的似乎并非标准的SM4算法,使用标准密码库进行加解密尝试均告失败。为了后续测试的自动化,需要将该算法完整还原。借助大语言模型的辅助,可以快速理解算法逻辑并将其转化为Python实现。
在工具选择上,笔者采用了mitmproxy脚本来实现请求/响应的自动加解密。这主要是为了避免Burp Suite插件环境中可能遇到的Jython脚本编码等兼容性问题。
正当准备进行自动化测试时,发现重放请求仍然失败。对比两次正常请求的明文数据,发现其中有三个参数始终在变:code、yhb_stamp和origin_stamp。下一步自然是追踪这些参数的生成逻辑。
HASH防篡改校验分析
针对origin_stamp参数进行全局搜索,其出现的代码位置不多,可全部设置断点进行跟踪。分析调用堆栈后发现,origin_stamp的值来源于一个MD5哈希运算,其输入是待加密的JSON数据中除origin_stamp自身之外的所有字段内容。这实际上构成了一种数据完整性校验机制。
时间戳防重放分析
接着分析yhb_stamp参数。同样通过全局搜索和断点跟踪,结合代码调用栈分析,可以定位到其生成逻辑。该参数由一个时间戳和一个随机字符串拼接后,再经过MD5哈希得出。随机字符串的生成函数在之前的前端代码逆向分析中已经遇到过。其核心逻辑可概括为:
function generateYHBStamp() {
const timestamp = Date.now().toString();
const nonce = randomString(8);
return md5(timestamp + nonce);
}
关于一次性code的挑战
登录请求中的code参数追踪起来更为复杂,无法直接通过关键词搜索定位。需要顺着函数调用栈逐步向上回溯,最终发现它来源于微信官方的wx.login()接口。此code具有一次性特性,使用后立即失效,这为批量自动化测试登录功能带来了挑战。
目前来看,该code主要影响登录接口的测试。一种可能的思路是尝试修改请求中的某些字段,使服务端绕过对微信验证接口的校验。另一种更深入的方法是通过Hook技术主动调用相关函数来获取有效的code。这个问题可以作为后续深入研究的课题。
流程梳理与实现效果
整个通信流程的加解密与校验机制如下图所示:

最终,通过编写mitmproxy脚本成功实现了对通信链路的自动加解密,使后续的安全测试工作得以顺利进行。

|