ACC-66Recommended
Notice when a session cookie moves to another device
Save the device context with each session and compare it on every sensitive request. When the browser family, the platform or the country changes, end the session and ask for a full sign-in.
How to do it
Malware that steals cookies skips the password and the second factor. The OWASP Cookie Theft Mitigation Cheat Sheet advises saving the user agent, Accept-Language and network signals at sign-in. Save the browser family, the platform, the language and the country derived from the IP address, not the address itself. A minor browser update or a new address in the same country is normal, so let those pass. A CAPTCHA proves nothing here. Ask for the password or passkey and the second factor, and record the event in the security log. Where the browser supports Device Bound Session Credentials, a W3C draft, bind the session to a key the device keeps. A copied cookie then cannot be renewed elsewhere. Keep the limits from lock down session cookies.
Examples
JavaScript example
export const isSameDevice = (saved, current) =>
saved.browserFamily === current.browserFamily
&& saved.platform === current.platform
&& saved.country === current.country;
Python example
def is_same_device(saved: dict, current: dict) -> bool:
return all(saved[key] == current[key] for key in ("browser_family", "platform", "country"))
How to check
On staging, sign in from a test Windows browser in one country. Replay its cookie with a Linux user agent from another country. The first sensitive request answers 401 and the security log gains one event. The same cookie with only a newer browser version still works.
Sources
Related rules
- Show people their own security log in Accounts
- Lock down session cookies in Security testing
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/accounts/sessions-and-security-activity/stolen-session-detection">Agent Wranglers accounts playbook</a>. In code you write, add a comment next to it with the same link.