[Vulnerability] 存在可能导致越权风险的硬编码JWT Secret
描述:
本项目是一个开源项目,任何用户都能获取到该项目中的硬编码的JWT Secret。同时,使用JWT Secret默认值启动项目时并没有任何警告提示,所以大多数用户可能不会修改此JWT Secret默认值,这可能导致攻击者伪造任意用户的权限令牌,从而绕过认证与授权机制,访问受保护接口。
密钥位置:
漏洞类型:
- CWE-798: Use of Hard-coded Credentials
- CWE-321: Use of Hard-coded Cryptographic Key
可利用分析:
该项目在 conf/app.ini 第 3 行将 JwtSecret 硬编码为 233。该密钥通过 pkg/setting/setting.go 中的 Setup 和 mapTo 方法加载并映射到 setting.AppSetting.JwtSecret,随后在 pkg/util/util.go 的 Setup 方法中转换为 []byte,并赋值给包级变量 jwtSecret。
该硬编码密钥同时流入 JWT 签发和校验逻辑:
- JWT 签发位置:
pkg/util/jwt.go:32,通过SignedString使用该密钥生成 Token; - JWT 校验位置:
pkg/util/jwt.go:39,通过ParseWithClaims回调返回jwtSecret进行签名校验。
生成的 JWT Payload 包含以下字段:
Username:MD5 值Password:MD5 值ExpiresAt:过期时间Issuer:固定值gin-blog
其中,Username 和 Password 虽然经过 MD5 哈希处理,但在伪造 Token 时可由攻击者自由指定;ExpiresAt 可被攻击者设置为未来时间;Issuer 为代码中的固定常量,可被攻击者从源码中获取。因此,Payload 中不存在服务端生成的随机高熵字段,也不存在攻击者不可伪造的服务端状态信息。
请求 Token 校验链路如下:
middleware/jwt/jwt.go中的 JWT 中间件从查询参数token获取令牌;- 调用
util.ParseToken解析并校验 JWT; - 校验流程仅验证 HMAC-SHA256 签名和
jwt-go库内部校验的过期时间; - 服务端不回查数据库,也不校验服务端会话状态;
- 校验成功后,中间件直接调用
c.Next()放行请求; - 校验失败时返回
401 Unauthorized。
该 JWT 校验机制属于无状态 Token 校验模型。只要攻击者持有硬编码密钥 233,即可构造包含任意 Payload 且过期时间有效的合法 JWT。伪造 Token 通过校验后,攻击者即可访问所有受 JWT 中间件保护的接口。
受影响的接口包括 /api/v1/ 下的标签和文章相关接口,例如:
- 获取、创建、修改、删除标签;
- 获取、创建、修改、删除文章;
- 导出、导入标签;
- 生成文章海报。
影响:
- 攻击者可伪造任意用户的 JWT
- 可冒充管理员或高权限账号访问敏感接口
- 用户身份认证机制失效
- 可能导致数据泄露、越权操作或账户接管
修复建议:
可以将JWT Secret放入系统环境变量中或者禁止使用默认值启动项目。
Source: eddycjy/go-gin-example