1

I have recently been working with a way to stop CSRF attacks happening by using a token. To my understanding:

1) User logs in, set session cookie to logged in and generate CSRF token and save it to the session

2) User submits form (with token) and it should match the token in session

Hypothetically lets say I have page1.php which has a sql SELECT to get all the users account information and then within the same page I also have an ajax button to page2.php which changes the account information. Obviously I protect page2.php from CSRF (because this is a post request) but how do I protect against page1.php? If this page was to get called from a remote source by ajax or putting an iframe on an attackers website, surely this would print all of the victims account information?

If this is the case how come I can't seem to find anything on protecting all pages from CSRF attacks and I only find resources for protecting against CSRF attacks in ajax?

A Friend
  • 1,420
  • 17
  • 22
  • hypothetically, you should worry more about the SQL injection for this query. – ArtisticPhoenix Nov 10 '17 at 11:17
  • Besides that, you should never expose the users data without first confirming they are logged into the session. Sessions still work on Ajax. – ArtisticPhoenix Nov 10 '17 at 11:19
  • thanks for your point however I wanted to keep the code clean and concise for what the question is actually about - sql injection is not the topic of this discussion – A Friend Nov 10 '17 at 11:20
  • Security is, and when there is a blatant violation of basic best practices you can hardly fault me for pointing it out. – ArtisticPhoenix Nov 10 '17 at 11:21
  • there are also checks in place that make sure the user is logged in but still if both sessions and cookies are still on the victims browser then the attacker can still use that information right? – A Friend Nov 10 '17 at 11:22

3 Answers3

1

Suppose you have a page at http://application.com/mypage with some data and a CSRF token generated. Attacker creates http://attacker.com/attack, and when a valid user of application.com visits, makes a request (either via ajax or in an iframe, doesn't matter) to application.com in order to get hold of application data. Standard csrf.

The reason this won't work for the attacker is the same origin policy. When the victim user is on attacker.com, the request to application.com will be cross-domain. If it's an iframe, data will be displayed, but attacker.com will have no access to it, it will only be displayed for the user that could have a look on application.com anyway. If it's an ajax call, the same applies, javascript on attacker.com will have no access to the response, ensured by the browser.

For ajax calls, access to cross-domain responses can be explicitly enabled by the access-control-allow-origin and related response headers (CORS) sent by application.com in the response.

Note that despite being cross-domain, the call will still be made (preflight requests come into play in some cases, but let's not go into that now). It's only the response that will be inaccessible for the attacker, and that is enough to prevent csrf.

(Also as a sidenote, application.com should prevent being displayed in an iframe by for example sending an x-frame-options: sameorigin header to prevent clickjacking and similar attacks, but that was not the question.)

Gabor Lengyel
  • 14,129
  • 4
  • 32
  • 59
  • Thank you for you answer! Very descriptive and I appreciate the reference to X-frame-options :) I have reworded the example on my original question so does what you have said protect against what I have described? – A Friend Nov 11 '17 at 08:53
  • Yes in that scenario you would be protected. You have the token check for POST requests that actually change stuff. For the GET on page1, you don't need protection against CSRF, because of the same origin policy. If the attacker makes a request from a different domain, he will not be able to access the response, and the request itself is not a problem, because nothing changes. (Note that should the GET change something, it would indeed be a problem.) – Gabor Lengyel Nov 11 '17 at 09:44
  • Thanks for your help :) That would seem to have answered my question then! – A Friend Nov 11 '17 at 10:13
0

I am not sure I get the point but the token for CSRF should be a nonce, which changes on each call.

Regarding a call coming from some other place, the ajax request should also check that the call comes from a valid user with the correct entitlments as you would do with any "regular" call to the site.

If this is the case how come I can't seem to find anything on protecting all pages from CSRF attacks and I only find resources for protecting against CSRF attacks in ajax?

What you ussually do is to set a nonce in a hidden input of the forms you use in "regular" pages.

Juan
  • 5,525
  • 2
  • 15
  • 26
  • not necessarily, it is more secure to generate one every request but not always needed. In most cases its perfectly secure to just use one token for the duration of the session as pointed out here: https://stackoverflow.com/a/31683058/3722330 – A Friend Nov 10 '17 at 11:24
  • I didn't find any statement about it being "perfectly secure" nor what "most cases" would refer to in the link. – Juan Nov 10 '17 at 11:45
  • I've also added a line to your last question I had missed before. – Juan Nov 10 '17 at 11:47
  • 1) I pasted the wrong link, I will try find the right one shortly 2) I think you misunderstood my question - I meant lets say a page automatically pulls through the users dashboard data without a post being initiated there would be nothing in place to stop that CSRF happening... – A Friend Nov 10 '17 at 11:51
  • the page by default loads the logged in users data with a sql select. – A Friend Nov 10 '17 at 12:25
  • If the request is not coming from the logged in user, how does the server know what user data to show? – Juan Nov 10 '17 at 12:49
  • but it would have the user logged in if its done through an iframe for example? look into clickjacking – A Friend Nov 10 '17 at 12:57
  • 1
    If you change the CSRF token in every form you prevent the back functionality of the browser as well as prevent multiple windows being open in different parts of your website for the same user. If you feel the need to try to prevent CSRF where the attacker might have stolen the CSRF token, you probably are better off with shortening the lifespan of a session (as the session is a much more valuable target to the attacker than the CSRF token) –  Nov 11 '17 at 01:54
  • @swa66 well said – A Friend Nov 11 '17 at 09:26
0

Hypothetically lets say the page has a sql select on it and does not request post. Now if this page was to get called from a remote source by ajax or putting an iframe on their website, surely this would print all of the victims data?

Make sure that all requests that hand out "confidential" information (either as a webpage or as data for an ajax call (or whatever in the future) do validate that there is a valid session active. If it's not, make sure the server side portion does not hand out anything confidential but instead throw an error and make sure your ajax client understands it and does the right thing for normal users (like telling them they're not logged in and offering them to fix that).

If this is the case how come I can't seem to find anything on protecting all pages from CSRF attacks and I only find resources for protecting against CSRF attacks in ajax?

For regular post requests typically the form is output with a hidden input field that holds the CSRF token. That's all.

BUT do make sure the code processing the request validates that the hidden field is present and filled in with the right value.

Also make sure that any request that modifies things is CSRF protected. E.g. that delete button in a non-ajax context should be protected with sending and validation of the CSRF token (hence the button ends up as a form with a hidden field for the CSRF.

  • Thank you for you answer :) I'm very close to marking it as right although I have another question refering to the hypothetical situation. So I have a.php with a sql select on it that pulls all of the users account information for example and a button to initiate b.php. It does have a script that checks the user is logged in on page a.php (from here: https://stackoverflow.com/a/244907/3722330) so obviously I protect page b.php from CSRF but how do I protect someone calling a.php initiating the select if that makes sense? surely the select would still work because the user would be logged in – A Friend Nov 11 '17 at 08:44
  • CSRF = cross site: the attacker's link might get the client to visit and retrieve information but it is not sent to the attacker, it is sent to the victim. So in your example the results of the select on page a would show up with the victim, potentially tipping them off to unwarranted actions, but it would not end up with the attacker. In other words: The CSRF problem only arises if there's a way for the attacker to create a change (e.g. delete, add, or change a record) that the victim is authorised to perform, but unwilling to do and tricks them into doing. –  Nov 11 '17 at 20:26