Protecting login and comment forms against CSRF

2019-06-19 21:23发布

问题:

I have read many articles about CSRF protection (this is a good one) and various questions here on SO, but none of them seem to be informative enough to answer my question.

I am developing my own CMS and I want to secure my login and comment forms. I am going to allow anonymous users to comment on my website.

All of the forms on my website are secured using tokens. I already know about that approach, but the problem is that it needs an active session (that is, after the user logs in). The problem with the login and comment forms is that they are accessible to just about anyone and do not require you to log in - what would be the best protection against CSRF in this case?

On the link above, I read that it could be possible to create a "pre-session" when the user tries to log in and then proceed to the usual anti-CSRF methods (like assigning a token to the user's session), but I have no insight on how to achieve this.

The referrer header is a weak solution, so I guess I shouldn't bother. The Origin header, is, as far as I have tested, only supported in Google Chrome. What about custom headers? XMLHTTPRequest seems like a possibility, however, I have spent literally more than three hours on Google looking up some information about how should one implement such a security measure on their website. But even if I could use a custom header, doesn't it make it useless since the HTTP headers can be faked completely?

So, the question: how should I protect my login and comment forms against CSRF?

Edit: here's some additional information from the link that I provided above:

We recommend strict Referer validation to protect against login CSRF because login forms typically submit over HTTPS, where the Referer header is reliably present for legitimate requests. If a login request lacks a Referer header, the site should reject the request to defend against malicious suppression.

and

Secret validation tokens can defend against login CSRF, but developers often forget to implement the defense because, before login, there is no session to which to bind the CSRF token. To use secret validation tokens to protect against login CSRF, the site must first create a “presession,” implement token-based CSRF protection, and then transition to a real session after successful authentication.

I just cannot put an end to this argument after reading the above quotes. One of them mentions using the referrer header, but I'm not quite sure whether it really adds much to the security of the webapp.

Edit 2: What about using CAPTCHAs?

回答1:

The CSRF problem relates to someone using logged in user credentials to submit something. This is highly problematic as a malicious site can do stuff as anyone who's just browsed into your site. If you're talking about forms that can be used as anonymous, without logging in, there is lot less CSRF risk as there is considerably less to gain from posting to the form from another site - as anyone can do it directly also with same permissions.

So I don't get why protecting against CSRF for non-logged-in forms is needed.

If you do want this, a pre-session token could be technically similar to real session, but just a more light-weight one. It wouldn't really contain anything else than a generated token.


EDIT: about using the $_SESSION provided by PHP for the pre-session token, that's PHPs standard session mechanism. If you want to use that, then yes, that's about it.

However you're not forced to do it that way, and I personally wouldn't do it like that as it consumes server memory for all visitors, and that's not really needed. For a more efficient mechanism, basically you need a) a cookie identifying the user and b) something stored on the server side telling that the cookie is valid (and if needed, who is it valid for, meaning the ip). For a more light-weighted approach you can just create a token, store it in a cookie, and generate something matching that token in the form as hidden field, and match those on submit (like explained by Devesh). The latter would prevent submit of forms from another site, the former would prevent even the case where a malicious site does a lookup on your site and tries to set any cookies to the end user, too. So three approaches that I can think of:

  • just prevent image requests from other sites - using POSTs prevents this
  • prevent form submits from another site - form hidden field matching a cookie prevents this
  • prevent form submits from another site that do pre-lookup on your site - this would need IP verification, something stored on the server side, like ip in the database matched to the cookie

EDIT2: On captchas, their main use case is to prevent automated (brute force) login attempts. They would fix the issue with CSRF requests on login forms, too, but are an overkill for that. For preventing brute force login attacks they might be needed in some cases, although something more user friendly might be in order to not degrade usability too much. Maybe something like KittenAuth :)



回答2:

You cannot realy protect an anonymous form against CSRF. Simply because the other site can act as a regular user. I can just create a site that does a curl request to the anonymous form and store the cookies and tokens in variables. And then make a second request to post the form. The script isnt realy forging a request, but is just posting automatically.

The point of CSRF is to prevent a script/person to perform actions on behalf of another user. So that would be me trying to post as you. To prevent that the session/cookie with token approach is a good a solution. Because I have no way to get your session and token, unless your site is flawed in other areas. I would suggest to read the OWASP guidelines to get some idea on what you should be on the lookout for.

Another thing you should always do is make sure "actions" are always with POST request so I cannot simple put on image on your forum that links to 'http://www.yoursite.com/delete.php?id=10'. If you allow GET request and you open the page that contains this image, I would have forged a request. If you only allow POST it would have no result.



回答3:

I think you can tackle the CSRF kind of problem by combining the hidden field added to your form and at the same time add the same value in the cookies and attach with the user response. When user post back the form try to match the hidden field value and the cookie value coming from the request , if both are matching you are good to go...



回答4:

he CSRF problem relates to someone using logged in user credentials to submit something. This is highly problematic as a malicious site can do stuff as anyone who's just browsed into your site. If you're talking about forms that can be used as anonymous, without logging in, there is lot less CSRF risk as there is considerably less to gain from posting to the form from another site - as anyone can do it directly also with same permissions.

So I don't get why protecting against CSRF for non-logged-in forms is needed.

If you do want this, a pre-session token could be technically similar to real session, but just a more light-weight one. It wouldn't really contain anything else than a generated token.