4

I am trying to make a like/unlike system, when a user clicks like on a post, his/her user id (which is stored in a session) and the post id will be stored in a database through an ajax call.

Then I thought what if some user make a html form with invisible input field (which has one of his post ids) on another domain and give its link to a user who checked remember me later or is viewing my site.

The user will click the button and The form will POST post id to my site, session contains user id and these will be stored in database.

No good solution comes to my mind. Is there any way more reliable than HTTP referrer to prevent this?

Thanks in advance

zrvan
  • 7,533
  • 1
  • 22
  • 23
Drust
  • 363
  • 1
  • 11

3 Answers3

5

One way is to insert a secret variable into the HTML which is specific to a user's session. This can prevent cross site forgery.

In PHP you'd generate a random 'key' and store it in the session:

$_SESSION['myFormVar'] = md5(mt_rand());

Then in a form, you'd add as a hidden variable:

<input type="hidden" name="chkVar" value="<?=$_SESSION['myFormVar']?>"/>

You should submit your form via POST and preferably over HTTPS, making it harder (but not impossible) to intercept the value of chkVar.

In the code that processes your posted form, compare the posted chkVar against your session variable. In an ideal world, you'd have a unique chkVar per request, however using one which is the same for an entire session often works fine and guards against most csrf attacks.

Paul Bain
  • 4,364
  • 1
  • 16
  • 30
  • 1
    When you have multiple forms on the same page (or multiple AJAX requests), it's handy to use a single token for this. Otherwise, it's a pain to grab each one from the document (or cookie) and use it for the appropriate request. I don't see anything wrong with doing it, but some of the more paranoid folks avoid it. – Tim Post Jan 10 '12 at 14:42
  • 1
    Related: [CSRF protection: do we have to generate a token for every form?](http://stackoverflow.com/q/8655817/53114) – Gumbo Jan 10 '12 at 15:13
  • 1
    Agreed, it can be a real pain to store one per form. I feel it's fine to use the same one for limited period to prevent csrf, however if you're looking at a determined hacker who's intercepting your request/responses, it's probably not going to help anyway! – Paul Bain Jan 10 '12 at 15:15
  • really nice solution! Thanks a lot Paul! @Gumbo thanks for the link! – Drust Jan 10 '12 at 15:52
2

You are talking about CSRF exploit.
This is a good security question.
It's generaly managed with a key that is only known by the server.
This key have to be used in all your forms.
Here is a little tutorial to protect against it

Pierre de LESPINAY
  • 44,700
  • 57
  • 210
  • 307
1

The only thing you should be sending is the post id, the user id should be picked up automatically in the script you are calling through AJAX. Assuming you have validated the user is logged in, you have both pieces of information without any further security risk.

fire
  • 21,383
  • 17
  • 79
  • 114
  • 1
    that isn't entirely true, you could factor a form from a different site which generates the same request and utilizes your existing session on the target domain. – Paul Bain Jan 10 '12 at 14:41
  • `the user id should be picked up automatically in the script you are calling through AJAX` as I told in my question I am exactly doing what you said and yet It is vulnerable to CSRF attack! and I completely agree with paul! – Drust Jan 10 '12 at 15:58