Hi Rodrigo,

It sounds like you're fairly across this problem domain. I wouldn't 
consider myself an expert at this stuff, but everything you've said matches 
my understanding of when and why CSRF protection is required.

It's worth noting that browser extensions, malicious or not, can modify the 
Origin and Referer headers (and CORS related headers). We do this at 
Paydirt to allow us to insert our time-tracker iframe into sites that 
normally disallow that in their CSP header.

I think probably there's enough that outside your control (browser 
versions, Flash/Java vulnerabilities, browser extensions) that it would be 
unwise to turn off CSRF protection and just use the Origin header.

Would it be possible to cache the SPA entry point page, and return CSRF 
tokens when the client makes a GET request for the data payload? Or can 
they send a POST/PUT requests before they necessarily fetch data from the 
server?

Cheers,
Nick

On Friday, July 22, 2016 at 12:18:42 PM UTC+10, Rodrigo Rosenfeld Rosas 
wrote:
>
> Em 21-07-2016 13:54, am...@pepo.com <javascript:> escreveu:
>
> Hi Rodrigo, 
>
> CSRF tokens would prevent any malicious POST or PUT requests which are not 
> made by the user knowingly.CSRF doesnot work for get requests at all.You 
> can turn off CSRF if there aren't any POST request or those request wont do 
> any  damage to your application or database.
>
>
> Yes, I understand, but that doesn't answer my 2 questions. To make it 
> short, given the scenario I described, I'd like to know:
>
> 1 - Why wouldn't checking Origin and Referer headers be enough to prevent 
> CSRF?
> 2 - If the page containing the CSRF token does not reflect user input, 
> would sending the CSRF token unmodified from the session be enough 
> protection?
>
> Thanks,
> Rodrigo.
>
> P.S.: Rails doesn't protect GET requests because such requests shouldn't 
> perform any state change in the server side, not because they are not 
> vulnerable to CSRF. But if for some reason someone decides to take such 
> actions on GET requests, there's nothing preventing them to use CSRF tokens 
> on such requests as well. But for some GET request at least CSRF must be 
> disabled so that one would be able to get the token before issues the next 
> requests... Also, even if Rails would check for CSRF in GET requests it 
> wouldn't be able to know which ones should be protected automatically...
>
>
>
> On Thursday, July 21, 2016 at 9:22:06 PM UTC+5:30, Rodrigo Rosenfeld Rosas 
> wrote: 
>>
>> A few extra comments to better explain it. 
>>
>> Em 21-07-2016 11:54, Rodrigo Rosenfeld Rosas escreveu: 
>> > 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); 
>>
>> Using HTTPS also means it wouldn't be possible for a proxy server to 
>> change such headers. 
>>
>> > 
>> > - 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). 
>>
>> Actually it would be possible to cache using other techniques like 
>> if-modified-since, getting a hash of the content with the token 
>> extracted and so on, but I'd prefer to keep it simple and just use the 
>> regular ETag middleware. 
>>
>> > 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-co...@googlegroups.com <javascript:>.
> To post to this group, send email to rubyonra...@googlegroups.com 
> <javascript:>.
> Visit this group at https://groups.google.com/group/rubyonrails-core.
> For more options, visit https://groups.google.com/d/optout.
>
>
>

-- 
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.

Reply via email to