Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Device-Bound Session Tokens in JavaScript (keyri.com)
23 points by thekeyper 5 months ago | hide | past | favorite | 11 comments
Google’s recent announcement of a proposed ‘Device Bound Session Credentials’ feature[1] for Chrome reminded me of a project we worked on last year at my company. We focus on fraud prevention at signup and login (preventing multi-accounting and account theft), but some customers were concerned about post-login security and asked us to add a session hijacking prevention feature to our fraud prevention API. In the end, we decided to just implement a solution in Javascript. We call it session-lock, and it can be used today across all browsers[2] and, theoretically, native mobile apps.

For a more comprehensive writeup and quick demo, you can visit the link. In short, the library adds a device-bound signature to the session token each time it’s used. At login, it creates a signing key pair on the browser using SubtleCrypto, with the private key set as “unextractable” and stored in IndexedDB (this forms the basis of its device-binding). Also at login, the public key is sent to the server along with the user’s credentials. If the credentials are valid, the server adds the public key to the payload of the JWT it returns to the client. When the client uses the JWT to access a protected resource, session-lock adds a signature to the end of it, along with a timestamp to mitigate replay attack risk. The server then validates the signature using the public key embedded in the JWT. The private key must be removed from IndexedDB upon logout.

While Chrome’s DBSC would be a nice solution when it gets around to being deployed in Chrome and Edge, I think session-lock would help a lot today across all browsers in countering common attacks like malicious browser extensions that rip LocalStorage and cookies. Also, implementing the general flow in native mobile apps[3] would have the same key advantages as DBSC - compiled code already on the device and utilization of hardware TPMs.

Aside from JS tampering and extracting “unextractable” CryptoKeys from IndexedDB, please let me know if you can think of any other potential attacks. Happy to answer any questions.

[1] https://blog.chromium.org/2024/04/fighting-cookie-theft-usin... [2] Other than Firefox private browsing mode due to its blocking of IndexedDB [3] Using CryptoKit / KeyStore for ECDSA




Thanks for this, it's very timely given what I'm working on right now. Google's proposal seems wildly overcomplicated for the use cases I've ever run across.


Glad to hear it. I feel the library could be improved, and if your server runs on something other than Node.js, you'll have to put together some straightforward crypto code, so feel free to file an issue on the repo[1] if you have any questions or requests. The point of it is not at all to compete with Google, but it could serve as a reasonable stopgap that's easy to implement (no new endpoints, no roundtrips) and should protect against all of today's cookie stealers, which would have to become a lot more sophisticated to beat it. I created a discussion on DBSC's spec repo yesterday that has a more direct comparison vs. Google's proposal[2] that you can check out.

[1]https://github.com/zainazeem/session-lock [2]https://github.com/WICG/dbsc/discussions


How do you handle scenarios where the user’s device environment changes significantly? For example, if they clear their IndexedDB or switch devices? Does session-lock manage to maintain security in these cases?


If the browser loses the private key from IndexedDB, the session token will become invalid because it would no longer be able to be verified on the server. Basically, the user would get logged out in the same way as they would if they cleared out the session token by clearing cookies or LocalStorage.


How is this better then an httponly cookie?


httponly cookies are meant to prevent attacks like XSS by preventing access to them from client-side JS. However, they can still be stolen by malware on the device (there's a whole class of them called "cookie stealers"). Generally, they search through the infected machine's filesystem and pull out any cookies they find, or at least cookies that the attacker would be interested in. No client-side JS is required for this, so the httponly attribute doesn't help. There have also some browser extension-based cookie stealers that may work along similar principles. Take a look at this old open source stealer to get a sense of how they work: https://github.com/Alexuiop1337/SoranoStealer/tree/master/So...

Session-Lock and Chrome's DBSC are designed to combat these cookie stealers specifically. The premise is that even if an attacker exfiltrates the token itself, it would not be able to be used because the server would reject it if it is not signed by the correct private key when the network request is made. This private key can (or should) only exist on the legitimate device, not the attacker's machine. There may or may not be ways to extract the private key as well, but in any event, it would be a much more complicated attack.


This would have been cool for hardware wallets when Ethereum was relevant.


doesn't this only protect against MITM attacks?


Actually, Session-Lock does offer some protection against some MITM attacks in the form of a timeout that would be triggered with most MITM attacks, but its purpose (and that of Chrome's DBSC proposal) is to protect against cookie stealer malware, not MITM. This is malware that steals session tokens from the device's filesystem. Take a look here to understand the threat: https://blog.google/threat-analysis-group/phishing-campaign-...

The premise of Session-Lock and DBSC is that even if the token gets stolen, it would not be useful to the attacker because the server would reject it if it doesn't have the correct signature that's generated using a private key that should only exist on the legitimate device. This private key has to be difficult or borderline impossible for the attacker to exfiltrate, unlike the session token.


If the user has malware can't that steal the private key as well? Why is it hard to exfil if the attacker has full access?


In an ideal world, the private key should be stored in an HSM, preventing exfiltration. However, even assuming an HSM, the current scheme doesn't protect against malicious actors pre-signing requests on the client and exfiltrating those requests.

This library adds more defense-in-depth, making it harder to attack sessions, but not impossible.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: