OWASP CSRF Token Hijacking Fix - csrf

Could someone please help me understand why OWASP had to make this change to their reference implementation
https://github.com/aramrami/OWASP-CSRFGuard/commit/a494d4d7d7e9814fa0feaabf81f8264d10165ffb
The only hint in that commit is "The token is now removed and fetched using another POST request to solve,the token hijacking problem."
I would very much appreciate if someone could explain how this change prevents token hijacking.

There are several changes in this commit, mostly if you look like it honors the configuration to protect or not protect forms that use method="get" (which is the default if bot specified as post. There also appears to be some XHR(Ajax) related changes to populate the HTTP headers in the request differently from the config values.

Related

Having a body on a delete request as an additional layer of security

I'm developing an web API and I'm trying to follow the principles of REST. I'm now at the stage of creating the endpoint where a user can delete its own account. I have also implemented JWT functionality where the JWT is valid for 1 day.
I want to add an extra layer of security when the user is deleting its own account. My idea is that the user have to provide its current password in the body of the delete request. I did some googling which pointed to having a body in a delete request is a bad idea because some entities does not support it, e.g. the Angular HttpClient, some web services might strip the body, etc.
I know GitHub have a similar functionality when deleting a repository, you have to provide your password. I like this feature because it prevents unauthorized persons from spoofing the JWT on critical operations, right?
What are your recommendations
Proceed with using DELETE and deal with the potential problems that might come along with this approach?
Instead use POST, PUT or PATCH even though it would look semantically wrong?
Other solution?
I would not recommend to use other http methods like put or patch if you really want to delete it and not only disable it. That would not be intuitive for the API user and could lead to misunderstandings.
One solution for your use case is to introduce an additional resource (e. g. deletionRequest) to request (but not immediately execute) the deletion of the profile with a post call. Then you could do the actual deletion with a delay (preferably longer than the token life span). You could then inform the user via email about the deletion, so the real user has the chance to revoke the deletion. If the user does not react in time, the deletion is executed.

CSRF Clarification

I'm trying to determine whether the following can be classified as a CSRF (Cross-Site Request Forgery) vulnerability on a website:
If website-1.com contains the following code: <img src = "http://website-2.com/img.png"></img> and "http://website-2.com/img.png" performs a 302 redirect to some sensitive content on website-1.com, such as http://website-1.com/delete.php?file=test.jpg and "test.jpg" is deleted succesfully, is that a CSRF attack, even though the malicious content was embedded on website-1.com and not on a 3rd party site?
Thank you for your help
Deleting with a simple GET request is a pretty bad practice and makes CSRF attacks easy.
Does plain link from website-2 to http://website-1.com/delete.php?file=test.jpg cause file to be deleted? If not, then there must be some sort of CSRF protection. But there are a lot of other things to be watched for to ensure CSRF is not possible (like if/how CSRF token is exactly implemented or what sort of user content sites allow, how much admins of both sites trust each other, etc). From your limited info, I'd consider website-1 vulnerable.

When is this Rack::Protection::FormToken a security issue?

The header comment for Rack::Protection::FormToken says:
# This middleware is not used when using the Rack::Protection collection,
# since it might be a security issue, depending on your application
Can anyone describe an example of when this middleware becomes a security issue?
According to https://github.com/rkh/rack-protection/issues/38 "FormToken lets through xhr requests without token."
So if you were relying on form tokens and had not taken extra steps to protect against xhr requests, then this might be considered a security risk. You might assume a request was genuine (since it's protected by FormToken - right!?) when in fact it was a forgery. By forcing you install FormToken explicitly, the developers are hoping that you will examine what it does and take the necessary steps.

How to add CSRF token to login form?

I'm not sure whether this is necessary, but I don't see any csrf tokens in the login form. Usually when you create a form, you add form_rest(form) at the end, and that adds the csrf token. But the login form is handled differently, it's not really a form object, it's kind of automagic. You can see that in the docs.
So what's up with that? Why there is no csrf protection for the login form? I know CSRF attacks are for authenticated users, but anonymous users in Sf2 are technically authenticated (see the session cookie), and also I might want to have some kind of gradual engagement, like in stackoverflow, where you can perform some actions without being a confirmed member.
Any thoughts?
CSRF protection is not necessary on login forms.
CSRF definition: an attacker can force a victim to send an HTTP request to a server.
Typical school-book example: to initiate a money transfer.
The attacker can force a request like this: http://bank.example.com/withdraw?account=Alice&amount=1000000&for=Eve
As you see, the attacker must bake a URL beforehand.
In the case of a login request, it does not make sense, because the attacker must bake a URL like this: http://example.com/login?user=pierre.ernst&pwd=secret.
If the attacker has this information (credentials) already, chances are he will not try a CSRF :-)
Hoping it helps.
Actually, form_rest(form) does a lot more than throw in the CSRF token, this function prints out any form rows that have yet to be rendered, and is good to put in to ensure that any additional fields that have been neglected are sure to be rendered.
The reason you're not seeing a CSRF token is because the FOSUserBundle login form is not a Symfony form, it's just a regular HTML form that is then processed by the FOSUser form handler.
I'm not entirely sure why this decision was made but I am sure there was a technical reason behind it, and that if it is a problem you could add one in manually and extend the form handler to process and validate it in the response, I believe the service is parameterised so it should be relatively easy to swap out.
My big question though would be why you would bother doing this? Is it a massive deal? CSRF is a useful step but not the be-all-and-end-all solution for security, and personally, I'd have bigger priorities than this, if it's a big deal it'll get fixed in FOS at some point.
With your latter point, I'm not sure of the relevance, how does this stop you from achieving gradual engagement? A quick tip regardless, whilst I didn't architect this part of the system myself, on an ecommerce project I've been working on recently, the lead decided that to achieve gradual engagement (so people could checkout anonymously) but still persist a lot of their actions, very early on new users are persisted with a autogenerated username and a custom role such as ROLE_GUEST, with the default functionality in Symfony proving insufficient for our use case.

Keeping GWT History Hashes thru Spring Security Login

I'm retrofitting my application with GWT History support, and I've stumbled on a case where I'm not quite sure what to do. The answer to this question doesn't necessarily have to be GWT-related.
GWT's History support functions by passing around hash tags (i.e. index.html#token). Security restrictions require users be logged in prior to actually being able to access index.html, so they get sent over to a login page, retaining the token (login.html#token). So far, so good. Now the user becomes authenticated and Spring sends them over to index.html (the default target) and eliminates the #token part of the URL.
How can I force Spring Security to maintain the token and send my newly authenticated user to the page they requested (index.html#token)? Since I've already got Spring Security authentication working, I'd prefer to not restructure the way my app handles logins.
After a great deal of digging, I found my answer on Spring's Jira. As Colin Alworth stated, that token isn't actually part of the request, so Spring Security never sees it server-side, and thus can't use it to determine the final URL. So the approach I used was to append the hash (client-side) to j_spring_security_check, making it j_spring_security_check#token. Now the token gets passed along just fine, allowing me to have a well-secured app with working tokens.
Thanks for your help Colin, your answer got me thinking in the right direction.
The server doesn't get to see this token as part of the GET/POST request as you've noted, it is only seen by the browser. Best fix that I've seen for this in the past is for the login page to take note of the current window.location.hash, and pass that along, either along with the login form (assuming a redirect will take place that keeps the hash around), or to the server as a login param so it can redirect properly.
Here's what happens, it might help you solve the problem:
sending unauthenticated users from index.html to login.html is most
likely implemented as an HTTP 3xx redirect, and that's why the
browser keeps the hash fragment (#token).
Once they login, spring sends them from login.html to index.html not
via 3xx redirect so the browser doesn't keep the token.
One solution would be to inject the token into index.html, and pick it up with GWT. Another one is to make login.html -> index.html a 3xx redirect (if spring allows that).