contentdb
contentdb copied to clipboard
CSRF swallows form submissions
If you take a long time to write a review, thread, or comment, the content can be swallowed by CSRF. (Apparently submitting a form invalidates all CSRF tokens?)
Instead, the user should be returned to the form with an error saying to resubmit
I investigated the topic and here what I found.
In the current state of the project, all CSRF protection is managed by flask_wtf.csrf.CSRFProtect.
flask_wtf.csrf.CSRFProtect sets up the template function csrf_token which is an alias for flask_wtf.csrf.generate_csrf.
flask_wtf.csrf.CSRFProtect also sets up a middleware (with @app.before_request), which extracts CSRF token from the request (from form data or HTTP header) and calls flask_wtf.csrf.validate_csrf.
flask_wtf.csrf.generate_csrf does the following:
-
create a random value and save it as
session["csrf_token"], if the value was not previously set -
sign this value with
WTF_CSRF_SECRET_KEYand current time and return the result from the function
flask_wtf.csrf.validate_csrf does the following:
-
check if the token from the request is not empty and
session["csrf_token"]is set -
check if the token signed with correct signature and the signature is not older than
WTF_CSRF_TIME_LIMIT -
check if the token and
session["csrf_token"]are equal
This means that there is no such thing as invalidation of CSRF tokens. Tokens when created are signed with current time, and when checked can be considered expired if the signature is too old.
In fact flask_wtf.csrf implements Signed Double Submit Cookie technique with HMAC CSRF Token, recommended by OWASP Cheat Sheet Series (link). This cheat sheet also states that including timestamps in CSRF token is a common misconception, and CSRF tokens do not need to expire.
WTF_CSRF_TIME_LIMIT = None config parameter can be used to disable CSRF token expiration. documentation