1
votes

I read from the web2py docs (http://web2py.com/books/default/chapter/29/01/introduction#Security) that

web2py prevents CSRF as well as accidental double submission of forms by assigning a one-time random token to each form. Moreover web2py uses UUID for session cookie.

Would someone be so kind as to explain to me how CSRF is prevented by the above, given that the random token is done for forms on web2py generated pages? Also the UUID in the cookie does not prevent CSRF as cookies get sent with the malicious request automatically, right?

Presumably a malicious site could perform the attack described on https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF) via external forms:

... the vulnerable request looks like this:

POST http://bank.com/transfer.do HTTP/1.1
acct=BOB&amount=100

Such a request cannot be delivered using standard A or IMG tags, but can be delivered using a FORM tag:

<form action="http://bank.com/transfer.do" method="POST">
  <input type="hidden" name="acct" value="MARIA"/>
  <input type="hidden" name="amount" value="100000"/>
  <input type="submit" value="View my pictures"/>
</form>

This form will require the user to click on the submit button, but this can be also executed automatically using JavaScript:

<body onload="document.forms[0].submit()">
<form...

These forms won't have the random token protection, or I have misunderstood this terribly?

In addition, won't standard GET requests (which don't change state but return sensitive information) also be vulnerable to CSRF attacks?

1

1 Answers

2
votes

Would someone be so kind as to explain to me how CSRF is prevented by the above, given that the random token is done for forms on web2py generated pages?

CSRF is prevented precisely because the random token is available only on web2py generated pages. Therefore, if an attacker attempts to initiate a form submission from a non-web2py-generated page (i.e., a page owned by the attacker), the form submission will not include the random token, and web2py will reject the form submission.

When web2py generates the token, it also stores a copy in the user session on the server (the user session is identified based on the session cookie). When the form is submitted, the submitted token must match the token stored in the session on the server. If there is no token or the token does not match, the submission is rejected.

Also the UUID in the cookie does not prevent CSRF as cookies get sent with the malicious request automatically, right?

Right, the UUID cookie alone does not prevent CSRF (it just makes it harder to hijack the session) -- protection requires the CSRF token.

Presumably a malicious site could perform the attack described on https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF) via external forms:

No, as noted above, an external form will not contain the CSRF token and will therefore be rejected by web2py. In other words, it is not the presence of the token that prevents CSRF, it is the absence of the token.

In addition, won't standard GET requests (which don't change state but return sensitive information) also be vulnerable to CSRF attacks?

No, as the attacker does not receive the response returned by the server -- the end user gets that response in the browser. This is why browsers do not allow cross-origin Ajax requests. You might be thinking of cross-site scripting (XSS) attacks (one way that web2py protects against that is by automatically escaping any content written into the view).