# Kimai: Pre-2FA KIMAI_SESSION cookie grants full authenticated REST API access, bypassing TOTP

Kimai's pre-TOTP KIMAI_SESSION cookie from the password-only login response was accepted by /api/* endpoints, letting password-only attackers bypass 2FA entirely.

- Payout: Research
- Severity: high
- Program: Kimai
- Found by: shafiqaimanx
- Disclosed: 2026-07-14
- CVE: CVE-2026-52827
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-v8hx-4vx8-wc96
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-v8hx-4vx8-wc96
- Tags: area:web domain:api domain:web impact:ato kind:research platform:ghsa sev:high tech:php technique:source-review vuln:access-control vuln:auth-bypass vuln:mfa-bypass

**Target:** REST API firewall / session authentication (Symfony security, Scheb 2FA)
**Root cause:** The /api firewall required only IS_AUTHENTICATED, which the Scheb TwoFactorToken already satisfies mid-2FA; ApiRequestMatcher's !hasPreviousSession() check routed cookie-bearing requests to the main session firewall, and ApiVoter granted API to any token with a User.
**Steps:**
1. Enable 2FA on a Kimai account; POST credentials to the login endpoint with only username/password (no TOTP).
2. Capture the `KIMAI_SESSION` cookie from that login response (web UI stays at `/en/auth/2fa`).
3. Replay the cookie against any `/api/*` endpoint, e.g. `curl -b 'KIMAI_SESSION=<cookie>' https://target/api/users` — no Bearer token or CSRF token needed.
4. Receive full authenticated API responses as the victim user without ever submitting the TOTP code.
**How found:** Reporter noticed the login response issues a session cookie before the TOTP step completes, then traced security.yaml's `^/api` rule (IS_AUTHENTICATED), ApiRequestMatcher's `!hasPreviousSession()` bypass of the stateless firewall, and ApiVoter's blanket API grant to any User token — confirming the mid-2FA TwoFactorToken satisfies all three.
**Exploitation:** Attacker who obtains the password (phishing, stuffing, reuse, breach) submits it once, grabs the KIMAI_SESSION cookie from the login response, and uses it directly against the REST API — no second factor, API token, or CSRF token required.
**Insight:** In Symfony/Scheb 2FA apps, IS_AUTHENTICATED is true for the intermediate TwoFactorToken; any firewall or voter keyed on it (rather than IS_AUTHENTICATED_REMEMBERED or an explicit 2FA-in-progress check) is bypassable with the pre-TOTP session cookie — check every path matcher and voter for this.

