1. 项目概述与核心目标
最近在研究一些主流消费类小程序的接口安全机制,瑞幸咖啡的小程序自然成了重点观察对象。作为高频使用的应用,其背后的数据交互逻辑,尤其是签名(sign)和加密算法,对于理解现代前端安全实践很有参考价值。这次的目标很明确,就是深入分析其网络请求中那个关键的 d/sign 参数(根据常见实践,可能是 d 和 sign 两个独立参数,也可能是组合形式),搞清楚它的生成算法、作用机制以及在整个请求验证链路中的角色。这不是为了“破解”或干扰正常服务,而是从一个开发者和安全研究者的角度,去学习一套在千万级日活应用中经过实战检验的签名方案是如何设计的。
你会发现,这类小程序为了兼顾性能、安全与开发效率,通常会采用一套相对标准但又有自身业务特色的前后端交互验证模型。核心往往围绕“防篡改”和“身份/请求合法性验证”展开。通过抓包分析,我们能够清晰地看到,关键的业务请求,比如下单、查询订单、获取优惠券列表等,其请求体或URL参数中总会携带一个或一组经过计算的签名值。这个签名就像是这单次请求的“数字指纹”,服务器收到后会用同样的逻辑再算一遍进行比对,任何对请求数据的篡改都会导致指纹对不上,从而被服务器拒绝。理解这个“指纹”的生成过程,能帮助我们更好地设计自己的API接口安全策略,尤其是在面对重放攻击、参数篡改等常见威胁时。
整个分析过程会涉及几个关键环节:首先是环境准备与抓包,拿到最原始的一手数据;然后是逆向分析小程序的前端代码,定位签名函数的具体实现;接着是算法还原,将混淆的代码逻辑梳理成清晰的算法步骤;最后是验证与复现,确保我们还原的算法能够生成与真实请求一致的签名。这个过程不仅需要耐心,更需要一套清晰的逆向工程方法论。下面,我就结合这次对瑞幸咖啡小程序的具体实践,把每个环节的细节、工具使用心得以及踩过的坑,毫无保留地分享出来。
2. 分析环境搭建与数据捕获
工欲善其事,必先利其器。分析小程序的第一步,是创造一个能让我们“看见”所有网络请求的环境。由于微信小程序的网络请求默认走的是微信客户端的内置通道,直接在电脑上抓包可能会遇到证书校验或协议加密的问题。因此,最稳妥高效的方式是在安卓模拟器或真机上进行抓包,并配合合适的代理工具。
2.1 工具选型与配置
我选择的是 安卓模拟器(如夜神、雷电) 配合 Proxifier 和 Charles/Fiddler 的组合。为什么不直接用电脑版微信?因为电脑版微信的小程序环境与手机版存在差异,且网络栈可能不同,为了分析最真实的手机端行为,模拟器是更好的选择。
- 模拟器设置 :安装好模拟器后,首先确保其可以正常访问网络。接着,需要将模拟器的网络代理指向我们运行在宿主机(你的电脑)上的抓包工具。以Charles为例,你需要知道电脑在局域网内的IP地址(如
192.168.1.100)以及Charles监听的端口(默认8888)。在模拟器的WIFI设置中,手动配置代理为这个IP和端口。 - 代理工具配置 :Charles或Fiddler需要安装并信任其根证书到模拟器中。这一步至关重要,否则无法解密HTTPS流量。在Charles中,你可以通过
Help -> SSL Proxying -> Install Charles Root Certificate on a Mobile Device来获取安装指引。在模拟器的浏览器中访问chls.pro/ssl即可下载并安装证书。 注意 :在安卓高版本(7.0以上)中,用户安装的证书默认不被系统应用信任,你需要将证书移至系统证书目录,或者使用已Root的模拟器/手机。为了方便,我直接使用了允许轻松安装系统证书的模拟器版本。 - Proxifier的作用 :微信小程序的部分请求可能不走系统代理设置。Proxifier是一个全局代理工具,可以强制将指定进程(如模拟器内的微信)的所有网络流量都导向Charles,确保无一遗漏。在Proxifier中,你需要创建一条规则,将模拟器进程(例如
Nox.exe或微信的进程名)的所有流量,指向Charles代理(127.0.0.1:8888)。
实操心得 :证书安装失败是最常见的拦路虎。如果遇到HTTPS请求显示为
unknown,十有八九是证书问题。可以尝试:1) 确认证书已成功安装到“系统信任的凭据”中;2) 重启模拟器和Charles;3) 检查Charles的SSL Proxying Settings中是否添加了需要解密的域名(如*.luckincoffee.com)的通配符。
2.2 关键请求捕获与特征识别
环境配置好后,启动模拟器里的微信,打开瑞幸咖啡小程序,进行一些典型操作:浏览商品、加入购物车、尝试下单(可以不支付)。此时,Charles的会话列表中会刷出大量请求。
我们的目标是找到携带 d 和 sign 参数(或类似签名参数)的 业务接口请求 。通常,这些请求会有以下特征:
- URL路径 :包含明显的API路径,如
/api/v3/order/create,/api/v3/product/list等,而不是静态资源(.js,.png)或WebSocket连接。 - 请求方法 :多为
POST,因为涉及业务数据提交。 - 请求参数 :
POST请求的请求体(Request Body)通常是JSON格式,里面可能包含一个加密字段(如q)和一个签名字段(如sign)。GET请求的签名则可能直接拼接在URL的查询字符串(Query String)中。
通过仔细筛选,我很快定位到了目标接口。例如,一个创建订单的请求,其请求体结构大致如下:
{
“q”: “eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...(很长的一段密文)”,
“sign”: “a1b2c3d4e5f678901234567890123456”
}
这里的 q 字段内容很长,且看起来是Base64编码的(可能包含 . 分隔符,类似JWT),这很可能就是经过AES加密后的实际业务参数。而 sign 字段是一个32位的十六进制字符串,这非常符合MD5哈希结果的格式(128位,32个十六进制字符)。这初步验证了之前搜索信息中提到的“AES加密业务参数,MD5生成签名”的模式。
捕获到足够多的样本请求是关键。你需要针对同一个接口(如加购),用不同的数据(如不同商品、不同门店)多次触发请求,并保存下所有的请求数据。这些样本将用于后续分析签名算法的输入参数,因为一个固定的算法,对于不同的输入,会产生不同的输出。通过对比这些输入输出的变化规律,可以反推出算法逻辑。
3. 小程序逆向与代码定位
拿到了网络请求的数据,下一步就是去小程序的前端代码里寻找生成这些数据的“发动机”。微信小程序的前端代码是运行在微信客户端内的,其核心文件 .wxapkg 包可以从客户端缓存中提取并反编译。


281

被折叠的 条评论
为什么被折叠?



