Ludicrous Session Security
Not too long ago we blogged about our (mis)adventures in finding new vulnerabilities in popular software. We briefly mentioned how cookies and WebStorage come with their own set of security benefits and challenges. By combining them, we envision a session handling solution with ludicrous security properties.
CSRF and XSS
Let’s talk briefly about two commonly found vulnerabilities of web applications:
- Cross-Site Request Forgery (CSRF)
- Cross-Site Scripting (XSS)
CSRF attacks work by tricking victims into submitting malicious requests to the application. These requests are submitted from the victim’s browser with the cookies of the victim. The attacker cannot receive the server response. The attack triggers state-changing behaviour on the server however (since the user is authenticated), such as creating a new user, assiging a role or changing a password, which is what the attacker is after.
The Web is rife with methods to prevent these attacks:
- security headers
- anti-CSRF tokens
- sanitizing input
- scaping output
The proposed solution is not a replacement to existing solutions, but rather an additional defense mechanism. This ‘defense-in-depth’ measure leverages the best of cookies and WebStorage in order to:
- prevent CSRF
- make stealing sensitive information such as session-tokens/JWT unattractive.
Cookies vs. WebStorage
So what are the strengths and weaknesses of Cookies and WebStorage, and how do we use them to create something that is better than the sum of its parts?
Cookies are sent along with the HTTP headers with each browser request to their origin. If you are not using the relatively new ‘SameSite’ directive (and most applications aren’t) your browser attaches cookies to any requests to the server, regardless of request origin. Attackers can abuse this feature for CSRF attacks.
Note: setting the ‘SameSite’ directive to ‘strict’ protects your cookies from being attached to cross-origin requests. Your cookies can now no longer be abused for CSRF. The only browser that doesn’t support the ‘SameSite’ directive is Internet Explorer which is to be avoided anyway.
So let’s say there is a hypothetical web app that works with a session token (or a JWT for stateless auth) after user authentication. Where are you going to store this sensitive data? Are you going to choose to be more vulnerable to CSRF (cookies), or are you going to choose to increase the impact off a successfull XSS-attack (WebStorage)?
Luckily we can apply the inverse of this dilemma to achieve something secure; if CSRF can’t touch WebStorage, and XSS can’t touch cookies, why not use both?
Best of both worlds
After authentication, generate a random string (securely) and include this in the authentication token sent to the client. Take a hash (HMAC-SHA2) of the random string and a (secret) key and sent this hash to the client as well. Store the token in a cookie and the hash in LocalStorage (or vice versa).
Send both the hash and the token with each request to the server, and check the associaton between the two. The server must reject any request requiring authentication that doesn’t have the association between the two values.
This approach can be considered as a ‘defense-in-depth’ technique, meaning that the gain in security might not be worth the effort needed to implement it. Especially when considering that using modern cookie directives can achieve the same protections. Applications should be protected from CSRF and XSS attacks in the first place.