
Dimostra una vulnerabilità critica di prevedibilità della chiave di firma JWT in PowerJob Server, consentendo la derivazione offline della chiave e la falsificazione dei token per l'acquisizione dei privilegi di amministratore e il bypass dell'autenticazione OpenAPI.
La chiave di firma JWT (HS256) del server PowerJob è derivata decodificando in BASE64 una costante hardcoded concatenata con l'MD5 dell'URL JDBC predefinito (DefaultSecretProvider / JwtServiceImpl). L'URL JDBC è pubblico nella distribuzione predefinita (docker-compose / application-daily.properties), quindi un attaccante può derivare la chiave completamente offline e falsificare un JWT valido per qualsiasi utente (incluso l'amministratore); l'App Token OpenAPI può essere ugualmente falsificato per bypassare l'autenticazione OpenAPI.
application-daily.properties espone in chiarojdbc: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: costante BASE_SECURITY hardcoded; genSecretKey(secret) = Decoders.BASE64.decode(BASE_SECURITY.concat(secret)) → Keys.hmacShaKeyForusername/encryptedToken) ha un controllo secondario per gli account PWJB (DigestUtils.rePassword(password, username)), ma:
appId/password/encryptType) può essere falsificato direttamente per bypassare l'autenticazione (OpenApiSecurityServiceImpl:87-105);Ambiente: server PowerJob locale (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). L'attaccante deriva tutto offline solo da informazioni pubbliche:
# ① Deriva encryptedToken (= rePassword(password, username)); calcolabile con la password predefinita
rePassword("powerjob_admin", "ADMIN")
= ADMIN_b82a450701f6a71723fb99931fe35e18_b # byte per byte uguale a DB user_info.token_login_verify_info ✅
# ② Deriva la chiave di firma HS256 = BASE64(BASE_SECURITY + MD5(JDBC_URL))
secret = BASE_SECURITY + md5(jdbc_url) # chiave da 101 byte
# ③ Falsifica un JWT web ADMIN (claims: username=PWJB_ADMIN, encryptedToken=risultato di ①, sub=PowerJob)
Risultato effettivo (il token falsificato supera l'autenticazione):
[*] /namespace/list senza token :
{"success":false,"data":null,"message":"PowerJobAuthException: UserNotLoggedIn","code":"-100"}
[*] /namespace/list JWT falsificato :
{"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}
→ il token falsificato autentica come amministratore e restituisce dati reali (la baseline viene rifiutata con UserNotLoggedIn).
Punti chiave:
encryptedToken derivato offline corrisponde al valore memorizzato nel DB byte per byte (ADMIN_b82a450701f6a71723fb99931fe35e18_b).BASE_SECURITY + MD5 dell'URL JDBC predefinito pubblico → derivabile offline senza credenziali.encryptedToken PWJB è ricalcolabile offline con la password predefinita (powerjob_admin, finding PJ-02) → compromissione totale dell'amministratore.encryptedToken, ma il percorso dell'App Token OpenAPI (claims appId/password/encryptType, OpenApiSecurityServiceImpl:87-105) può comunque essere falsificato in modo indipendente per bypassare l'autenticazione OpenAPI.Anche se la password predefinita viene cambiata, la vulnerabilità persiste attraverso altri vettori di attacco:
encryptedToken di qualsiasi utente valido con altri mezzi (ad es., SQL injection, esposizione di backup del database, perdita di log o divulgazione di informazioni da altri endpoint) può combinare quel token con la chiave di firma prevedibile per falsificare un JWT per quell'utente specifico.encryptedToken, perché il token falsificato ora contiene un encryptedToken legittimo derivato dal record effettivo del database.PoC: powerjob_jwt_key.py 192.168.49.128:7700


encryptedToken per tutti gli account.CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N = 9.1 Critico (combinato con la password predefinita / OpenAPI)