Session fixation prevention on login
The session identifier survived authentication, allowing a pre-set identifier to become an authenticated session. Fixed by regenerating on privilege change and hardening cookie attributes.
Context
Authentication review of a PHP application that managed sessions manually rather than through a framework guard.
Scope
Login, logout, privilege elevation and session cookie configuration.
Vulnerability
The session identifier issued before login remained unchanged after successful authentication, and the application accepted a session identifier supplied in the URL by a legacy compatibility setting.
Root cause
session_regenerate_id() was never called on privilege change, and session.use_trans_sid had been left enabled to
support a long-retired client.
Impact
An attacker who could set or observe a victim's pre-authentication session identifier could use that identifier after the victim logged in, obtaining an authenticated session without credentials.
Remediation
- Regenerated the session identifier on login, on logout and on any privilege change, deleting the old session data.
- Disabled
session.use_trans_sidandsession.use_only_cookies=0, so identifiers travel only in cookies. - Set
HttpOnly,SecureandSameSite=Laxon the session cookie, with an absolute and idle timeout. - Bound sessions to a coarse client fingerprint and invalidated all other sessions on password change.
Retesting
Retesting pre-set an identifier, completed a legitimate login in a second browser and confirmed the original identifier was rejected. URL-borne identifiers were ignored. Session expiry and logout invalidation behaved as configured.
Lessons
- Any change of privilege deserves a new session identifier, not only login.
- Compatibility settings outlive the clients that needed them; audit the runtime configuration, not just the code.
Authorisation
This work was carried out under written authorisation or inside an authorised training environment. All evidence has been sanitised.
Continue reading
Related case studies
IDOR: missing server-side authorisation in an invoice workflow
An authenticated user could modify an invoice identifier and attempt to access another customer's resource. The remediation enforced ownership at the database query layer and was verified with positive and negative authorisation tests.
5 min read
Secure payment webhooks: validating PayPal, Stripe and Flutterwave callbacks
A secure payment integration case study covering server-side verification, webhook authenticity, payment-state validation, duplicate processing, secrets management and safe failure handling.
8 min read
SSRF in a server-side document import feature
An authorised security lab examining how a user-controlled URL can cause a web server to make unintended requests to internal or restricted destinations, followed by layered remediation and retesting.
9 min read