thentos-cookie-session-0.9.0: All-in-one session handling for servant-based frontends

Safe HaskellNone
LanguageHaskell2010

Thentos.CookieSession.CSRF

Synopsis

Documentation

newtype CsrfSecret Source

Constructors

CsrfSecret SBS 

newtype CsrfToken Source

This token is used to prevent CSRF (Cross Site Request Forgery). This token is part of FrontendSessionData since it is required by the views which generate the forms with a special hidden field containing the value of this token. However, this token is cleared before being serialized as a cookie. Indeed we have no need yet to have it on the client side nor to make it persistent. When processing requests, this token is freshly generated from the CsrfSecret and the ThentosSessionToken. This token is only used by requests that yield an HTML form. Upon POST requests on such forms, the handlers will check the validity of the CSRF token. Verification of this token can be done solely from the CsrfSecret and the ThentosSessionToken.

This all means that if the attacker could get access to one of these tokens it would be enough to validate any form. Changing the token on every request even inside the session helps to counter an attack based on entropy leakage through TLS plaintext compression. TLS compression should be disabled for the exact reason that it is vulnerable to this attack, but this code does not rely on it.

  • The idea of the attack:* When combining encryption (which hides the contents but not the length) and compression (which makes the length depend on the content). If you compress after encryption its safe but useless; if you compress then encrypt (which is often done), then some data leaks through the length of the ciphertext. The BEAST attack exploited this by guessing the CSRF token by sending request to the server pretending to be the client injecting in the request the guess of the token in a parameter which is echoed back by the server to the real client encrypted for the client. Assuming the CSRF token is given as an attribute such as csrf:SOMESECRET to keep it simple, then the guess is going to be csrf:XYZ with all combination of XYZ then you look at which answer was the shortest it is highly likely that XYZ=SOM will compress better than the rest because of the repetition with the real secret also part of the response. You then proceed with your guess being csrf:SOMXYZ. On a test setup, it was possible to recover the full token in 30 secs.

Constructors

CsrfToken 

Fields

fromCsrfToken :: ST
 

newtype CsrfNonce Source

Constructors

CsrfNonce SBS 

class GetCsrfSecret a where Source

Methods

csrfSecret :: Getter a (Maybe CsrfSecret) Source

Instances

type MonadHasSessionCsrfToken s m = (MonadState s m, HasSessionCsrfToken s) Source

type MonadViewCsrfSecret e m = (MonadReader e m, GetCsrfSecret e) Source

genCsrfSecret :: MonadRandom m => m CsrfSecret Source

Generates a random CsrfSecret.

validFormatCsrfSecretField :: Maybe ST -> Bool Source

This ONLY checks the format of a given CSRF secret, not if it has been randomly choosen (duh!).

validFormatCsrfToken :: CsrfToken -> Bool Source

This ONLY checks the format of a given CSRF token, not if it has been tampered with.

checkCsrfToken :: (MonadError500 err m, MonadViewCsrfSecret e m, MonadUseThentosSessionToken s m) => CsrfToken -> m () Source

Verify the authenticity of a given CsrfToken. This token should come from the form data of the POST request, NOT from FrontendSessionData.

refreshCsrfToken :: (MonadError500 err m, MonadHasSessionCsrfToken s m, MonadRandom m, MonadViewCsrfSecret e m, MonadUseThentosSessionToken s m) => m () Source

See CsrfToken. This function assigns a newly generated CsrfToken to the FrontendSessionData.

clearCsrfToken :: MonadHasSessionCsrfToken s m => m () Source

See CsrfToken As long as we do not need to generate any forms on the client side it's better to clear the value of the CsrfToken, preventing it to be stored in the cookie. Still if we ever need to persist a CsrfToken it might be safer to refresh it with refreshCsrfToken first.