fix: regenerate session on login to prevent session fixation (CWE-384) - #1005
fix: regenerate session on login to prevent session fixation (CWE-384)#1005poliakarmai wants to merge 2 commits into
Conversation
Both demo handlers (database_auth and dictionary_auth) call remember() without first calling forget(), leaving the session ID unchanged after authentication. This enables session fixation attacks: 1. Attacker obtains a valid session ID 2. Attacker tricks victim into logging in with that session ID 3. Victim authenticates → session is now authorized 4. Attacker uses the same session ID → hijacks victim's session Fix: call forget() before remember() to regenerate the session identifier upon successful authentication. Found by GSC — Git Security Checker (https://github.com/poliakarmai/gsc)
Sorry, can you walk me through what is happening here? From what I can see of reading the code, the flow looks like:
How does forget() change the end result here? It looks to me like regardless of whether it's called or not, we still have the same key/value pair in the same session cookie... |
|
You are absolutely right. Correct approach with session.invalidate() # new session ID
await remember(request, response, identity)This matches OWASP ASVS V3.2.1. I will update the PR with |
…fixation prevention Replace forget() with session.invalidate() in login handlers: - database_auth/handlers.py - dictionary_auth/handlers.py session.invalidate() generates a new session ID, properly preventing session fixation (CWE-384) per OWASP ASVS V3.2.1. forget() alone only clears the auth key but leaves the session ID unchanged.
I'm still not clear what this session ID is or how it's relevant to authenticating? Please describe step-by-step what is actually happening. Your description just says the attacker reuses the session ID and hijacks the user's session. There is no explanation of the mechanism there or how the session ID is relevant, or even what the session ID is... |
|
Here's the step-by-step attack:
Why
The existing As for how the attacker gets the cookie to the victim in practice: the most common real-world scenario is when a site accepts session tokens from URL query parameters. aiohttp_session's default Reference: OWASP ASVS V3.2.1 — "Verify the application generates a new session token on authentication." |
This isn't making any sense. How can it be inserting the identity into the SAME cookie? Now you're telling me that the user's browser is mirroring the updated cookie back to the attacker? If that's the case there's nothing we could possibly do to for the user, their browser is compromised. |
|
You're right — I need to correct my explanation. With Session fixation is a genuine concern for the server-side storages ( That said, I'd still argue
So I'd propose keeping the one-line |
🔍 Found by GSC — Git Security Checker
The demo handlers (
database_authanddictionary_auth) don't rotate the session identifier on login —login()callsremember()without invalidating the existing session first.Why this matters
With server-side session storage (
RedisStorage,MemcachedStorage), the session ID is unchanged after authentication — the classic session fixation precondition (CWE-384). The demo itself usesSimpleCookieStorage, where this is less critical, but these handlers are copy-paste templates and developers routinely swap in a server-side storage in production.Rotating the session identifier on privilege change is standard OWASP guidance (Session Management).
Fix (defense-in-depth / best practice)
Call
session.invalidate()beforeremember()to regenerate the session identifier upon successful authentication.Files Changed
demo/database_auth/handlers.py— invalidate session beforeremember()demo/dictionary_auth/handlers.py— invalidate session beforeremember()🐛 Found by GSC — self-learning security scanner with PoC generation