phpsecuritysessioncookiescsrf-protection

Secure CSRF protection without sessions or database?


i'm trying to implement secure CSRF protection to HTML login form, i know the best way to implement CSRF protection is storing random csrf_key in a session, but i want to add CSRF to my login & register forms... and i do not want to store many sessions for any anonymous unregistered users...

so i want to create the best secure posibble without using sessions or database, with only form hidden field /& a cookie, and after the login i will use sessions csrf protection.

my idea of secured user_storage only csrf:

csrf_token= AES(ip+useragent+timestamp+random_data, csrf_aes_site_key)

when csrf_aes_site_key is hard-coded in config file. and after every login/register i will decrypt the AES string + velidate that the ip&ua is matching the request ip&ua, and timestamp is not too match ahead, let say 5 min (if csrf_timestamp + 18000>=current_ts), and random_data is just randomness (and make sure that the same user will not get the same csrf_token if requested multiple times in the same ts)...

so ... is it secure enough, is it good solution? if not, any other suggestions to solve this dilemma? thank!

EDIT: the implementation i just created, and it's working fine, but is it good enough?

full example: https://github.com/itaiarbel/aes_based_csrf_protection

issue 1: user may take the csrf_token and submit to the form successfuly using the same token for the next 5min bug? what do i care if the user submit many times? as long as it not csrf attack...

issue 2: if the page is left open for 5min, the user will faild login, (refrash login page automaticaly every 5 min? maby change it to 1h?)

can you spot any specific security risk with this implementation? or can i assume this is a secure way of doing CSRF protection?


Solution

  • The method with storing the CSRF token in cookie is quite widely used (AngularJS, Django) but it works a bit differently. The server sends the token in cookie, the client uses JavaScript to read the cookie and reflect the token in a HTTP header. The server should only verify the value from the HTTP header, even though the cookie will be sent automatically as well.

    The actual cookie and header names are not important as soon as both JavaScript frontend and backend are aware of them.

    This prevents CSRF because only JavaScript running from the authentic origin will be able to read the cookie (see detailed discussion on Wikipedia). The token can be a HMAC of the session cookie, which avoids the need to remember token state on the server side.

    The main advantage is that this approach (unlike the one with token in form fields) works with single-page, JavaScript based applications where you don't generate the HTML on the server and can't really embed the CSRF token in their code.