8

After reading many documents regarding CSRF, I'm still a little bit confused. So I hope someone can please explain it to me:

  1. Lets say if I have a profile page which is for authenticated users only, say abc.com/profile which shows me all my private info. If I logged in, then go to a "bad" site, can this site somehow get and parse my profile page? (I did a little experience by opening up the firebug console on a different site, then request my profile page, and it seems like at least I can see the whole content in "response" of the "Net" tab, haven't figured out how to get this content and parse it yet though. But perhaps it's possible?)

  2. Now assume that I have on my profile page a form, which of course has csrf token. Now if an attacker could get my profule page, he could just parse that content, get the token then submit a fake form?

  3. Now assume that 1 and 2 are correct, what should I do to prevent such cases from happening?

mr1031011
  • 2,926
  • 4
  • 38
  • 55

3 Answers3

9

Your points aren't quite right... But take this scenario.

Example Attack


Imagine that a user is logged into The Official Bank of Fake Country - GoodBank.com and has a balance of 1,000,000 gold.

On MaliciousSite.com, there is an <img> or some other generic JavaScript that causes you to make a request to GoodBank.com.

The <img> has a src of http://www.goodbank.com/account/transfer.php?amount=10000&sentTo=malicioususer.


Now this site has made a request under your user account and has caused you to invoke a page which you would not have otherwise.

Now, you might be thinking that you can protect against this by using only POST, but these are not secure either. The correct way is to use CSRF tokens in your forms, and when a form is submitted, you should check that the CSRF token that you receive is the same as with what was issued.

Do not use these measures to protect yourself:

  • Secret Cookies
  • Only accepting POST requests
  • Multi-page forms
  • URL rewriting

Instead use a token like this:

<form action="/transfer.do" method="post">
  <input type="hidden" name="CSRFToken" value="OWY4NmQwODE4ODRjN2Q2NTlhMmZlYWEwYzU1YWQwMTVhM2JmNGYxYjJiMGI4MjJjZDE1ZDZjMTVi
  MGYwMGEwOA==">
  …
  </form>

View here for great explaination: CSRF Cheat Sheet

Layke
  • 45,997
  • 10
  • 79
  • 109
  • Thank you for a very detailed post, do you suggest referrer checking as an additional safety check as well? It seems like people are concerned with the case where some proxy or browsers do not send referrer. – mr1031011 Sep 02 '11 at 01:57
6

Your first point is not correct.
You cannot read content from a different domain on the client.

Therefore, a hostile site cannot read the CSRF token.

You can send requests to a different domain (which is what CSRF attacks do), but you can't read the responses.

SLaks
  • 800,742
  • 167
  • 1,811
  • 1,896
  • This particular point is very useful, I wanted to know if it's possible to read the response. If it's not then I'm very happy. – mr1031011 Sep 02 '11 at 01:56
  • You *cannot read* from a different domain, but you *can always write*. Because you can write, you have CSRF. Because you cannot read, you can prevent CSRF by mandating a token. – Sripathi Krishnan Sep 02 '11 at 09:15
  • I have another question regarding csrf: I'm writing restful webapp, and for user to delete a "resource" abc.com/article/1 a request must be sent to the server with method DELETE to abc.com/article/1 (instead of GET). However, since DELETE does not have a body, how do I pass a token into it to prevent csrf attacks? It seems like I cannt use DELETE abc.com/article/1?csrf=12wsdsadsadasda for example because the uri is supposed to be the identifier of the resource, thus no extra parameter should be there? – mr1031011 Sep 02 '11 at 12:00
  • @user: You should just add a query string parameter; there's nothing wrong with that. – SLaks Sep 02 '11 at 12:57
  • Can you explain me it again, please? Why can't I read the response? There are a lot of on example.com and I can see them all. So what do you mean that "I can't read?" – Павел Тявин Oct 23 '13 at 18:09
  • 1
    @ПавелТявин: Your Javascript code running on origin X cannot read content from origin Y without explicit permission / cooperation from Y. The _user_ can see the content, but your JS code can't. – SLaks Oct 23 '13 at 18:18
  • @SLaks oh, now i see. This page doesn't work http://pastebin.com/LfJ9nxvV , but firebug (or chrome console) works as well with another domains. That was misunderstanding. – Павел Тявин Oct 23 '13 at 18:34
1

This may not be directly related to the question asked but need to point out that cross site scripting attacks can open doors for CSRF. Even token based solutions used to prevent CSRF can be compromised by XSS.

Take the following scenario.

Form used to update user info.

<script>
...
var userID=getUserId();//method makes AJAX call to get user ID
...
</script>
...
<form name="UpdateUserProfile">
   <input type='hidden' id='userId' value='userID_attacker_cannot_guess'>
   <input type='hidden' id='userName' value='goodUser'>
   <input type='hidden' id='email' value='goodUser@goodsite.com'>
    ...
 </form>

Assuming that the user Id is unique and can not be guessed easily, we can prevent CRSF without a token.(Attacker request will not be able to have the right user ID).

But if the attacker can read the value of userID using XSS attack, he can then craft the forged request to include the correct user ID.

Although XSS is not needed for CSRF attacks, it will make it easier.

Check the following resources.

Cross-Site Request Forgery (CSRF)-OWASP

Cross-site Scripting (XSS)-OWASP

user624558
  • 519
  • 2
  • 8
  • 19