Hi, hope to find someone here with a good understanding of CSRF handling
in Rails and willing to answer my questions :)
I've read the security guide and couldn't find this kind of information
so maybe this is something we could improve in the guides and I could
send a PR once I confirm I understood the reasoning behind each
implementation details.
So, what are my problems with CSRF tokens? They add complexity, prevent
caching and seem unnecessary for my application. I know Rails is not
designed for serving only my application but if we could improve the
security guides I would be able to opt out from having a token if I
could be sure my application would remain safe. Or, if I should keep
using CSRF to be safe, then it would help if Rails wouldn't mask the
token generating a new one on each request because that would allow the
application to provide better caching.
So, while researching about CSRF it seems like enough protection to
simply verify the ORIGIN or REFERER headers unless there's a security
breach in the browser itself or in some browser plugin, like Flash or
Java. Sometimes those headers may not be present for legit requests, but
this does not seem to be the case with the main browsers if your
application runs over HTTPS in a single domain. I mean, Rails won't try
to protect against GET requests to HTML pages as it doesn't make sense
anyway, so in that case it would be fine if those headers would be
missing or coming from a separate domain.
So, as far as I can tell, checking the headers would be enough if the
following conditions can be met:
- the application doesn't change any data on GET requests, following the
web semantics;
- it's served over HTTPS for all requests (so that a request wouldn't be
made to HTTP in the same domain which could hide the referer in some
browser implementations);
- it forbids non GET requests where those headers are both missing or
when they don't match a whitelist;
- the application restricts access to supported browsers;
- the supported browsers and their plugins do not allow changing those
headers for cross-domain requests;
I understand the last two conditions are out of our control but the
company would be able to decide whether or not they are responsible for
buggy browsers or plugins. For example, if such an exploit is possible,
then maybe it would also be possible that it could be used to issue a
regular GET request from the other domain and extract the token from it
anyway, right?
Now, even if the company decides that they want to add extra protection
anyway to make it harder for such bugged browsers/plugins exploits to be
successfully used, maybe it would be enough to provide the unmasked CSRF
token in the original GET request. It used to be the case in Rails but
it was changed to mitigate BREACH attacks. Accordingly to
http://breachattack.com/ the following conditions must be met for the
application to be vulnerable:
"If you have an HTTP response body that meets all the following
conditions, you might be vulnerable:
1 - Your page is served with HTTP compression enabled (GZIP / DEFLATE)
2 - Your page reflects user data via query string parameters, POST...
3 - Your application page serves PII, a CSRF token, sensitive data..."
While 1 and 3 would hold true for our SPA, we serve a single page which
I'd want to be cacheable with ETag. We don't reflect query string
parameters in that page, so I guess we would be safe from the BREACH
attack. In that case we would be able to use the unmasked CSRF token
stored in session, while remaining safe, right?
I know Rails will try to add default protection that is suited to most
applications but it would be helpful if it could explain better the
measures it takes against the attacks in the security guide as well as
explaining how to allow safe caching by telling in which conditions the
CSRF token wouldn't have to be masked. I wouldn't be bothering you if
the token masking didn't come with some caveat, but we actually have a
trade-off here, as masking the token could affect the client-side
performance by preventing proper caching (or by forcing the client to
perform another XHR request to get the masked token).
I'd love to understand if there are any other reasons why the CSRF token
is being masked as well as confirming it would be okay to not mask it
provided the page doesn't reflect any user input. If you know those
answers I'll be pretty thankful for your feedback.
Thanks,
Rodrigo.
--
You received this message because you are subscribed to the Google Groups "Ruby on
Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to rubyonrails-core+unsubscr...@googlegroups.com.
To post to this group, send email to rubyonrails-core@googlegroups.com.
Visit this group at https://groups.google.com/group/rubyonrails-core.
For more options, visit https://groups.google.com/d/optout.