Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>OWASP has a good guide to preventing CSRF attacks <a href="https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet" rel="nofollow">here</a>:</p> <p>Checking the Referer header is certainly the easiest, and its a good idea to at least log instances where the Referer is a 3rd party or empty. There are however several drawbacks which make using the referer alone unreliable:</p> <ul> <li>Corporate firewalls might strip the referer header for privacy reasons</li> <li>The referer is not sent when moving from HTTPS to HTTP</li> <li>In CFRF attacks, it is generally difficult to 'forge' the referer, but it can be <a href="http://www.blackhatworld.com/blackhat-seo/black-hat-seo/28627-how-easily-fake-referrer-when-using-double-meta-refresh.html" rel="nofollow">done</a> using meta-refresh tags.</li> </ul> <p>Fortunately WebFlow makes it easy to implement a custom unique token-per-flow-invocation CSRF filter (you might not have to modify any views/forms)! </p> <p>First, use a FlowExectionListener to create a new random token whenever a flow starts and store it in the flowScope. Then, whenever an event is signalled, verify that the submitted token (submitted as a parameter in the request) is equal to the value stored in the flowScope. </p> <p>Then, configure a custom FlowUrlHandler which appends the "_token" parameter to generated URLs, so if you have been using ${flowExecutionUrl} to reference your flows, the token will appended whenever you POST/GET back to your flow automatically. To fetch the token from the flowScope from inside the FlowUrlHandler, I had to resort to using RequestContextHolder </p> <pre><code> private String retrieveToken() { RequestContext requestContext = RequestContextHolder.getRequestContext(); if (requestContext == null) { return null; } return (String) requestContext.getFlowScope().get(CsrfTokenFlowListener.TOKEN_NAME); } ... </code></pre> <p>This method will include the CSRF token whenever you output ${flowExecutionUrl} - for both GETs and POSTs, and if you are using post-redirect-get, you can ensure ensure that the CSRF token doesn't appear in the URL bar.</p> <p>I would caution against only checking CSRF tokens for POSTs:</p> <p>WebFlow and many other web frameworks don't distinguish between GET and POST - by default you generally can use a GET to do whatever you do with a POST, unless you verify the request method yourself (which would be a good idea anyway). So an attacker wanting to bypass your CSRF filter would just do a GET instead of a POST.</p> <p><strong>Edit:</strong> One disadvantage to be aware of in including CSRF tokens in the ${flowExecutionUrl} is that the CSRF token will likely always be sent as part of the request URL (because it would be part of the HTML form's 'action' attribute), and never in a POST body. Including sensitive information in the request URL isn't great, as it is more likely to be logged in server/ISP logs. The alternative is to add a hidden input in each form containing the CSRF token, and only enforce its presence for POST requests.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload