Author

Topic: Encrypted cookie signs GET requests through HTTP to avoid XSRF (Read 1500 times)

legendary
Activity: 980
Merit: 1003
I'm not just any shaman, I'm a Sha256man

Still, as long as ... you know what you're doing

Thats what i meant actually. that I've seen some php programmers rely completely on the safety of php sessions not realizing that its just really a cookie session and nothing more.
hero member
Activity: 504
Merit: 502
Thank you for taking the time to address my concerns with great detail. Finally someone who is a better communicator can explain why I don't like PHP sessions. Also I refuse to use sessions as when I merge my code with open source library becuase there are possibilites that a Cheaperinbitcoins library might be shared on the same VPS (2 diff websites on the same box) and i know php sessions are guessable to some extent with multiple websites running as the more users take up the total unique php session ids the eaiser it becomes to generate/guess a php session. Atleast with homegrown cookie sessions they are less guessable if done correctly.

I don't think I was saying sessions are bad (PHP or your own implementation); in fact they are they most secure way of making stateless HTTP stateful.  PHP sessions aren't (to my mind) any less secure than any other method -- it's a long random number stored client side; how many ways are there of doing that?

Still, as long as you're happy you know what you're doing and have a method that works for you, you go right to it.  He who codes, decides.
legendary
Activity: 980
Merit: 1003
I'm not just any shaman, I'm a Sha256man
I'm not sure it's been made very clear from the above argument (both parties obviously know what they're talking about, but it doesn't help Xenland if you're not familiar with the ideas already); PHP sessions are not sufficient on their own to prevent CSRF... in fact, PHP sessions are the thing that makes CSRF possible.

Let's say in tab1 I'm logged into bitcointalk.  "Logged in" means I have a session cookie on my browser that is sent with every request to the the server, allowing the server to access my server-side "state".  The stateless HTTP has become stateful.  The session cookie is usually some long, random number that can't be guessed and is known only to your browser and the server.

Now, in tab2, some malicious site runs javascript that sends a carefully crafted POST message to bitcointalk that makes the currently logged in account send a PM to the attackers bitcointalk account and a second POST to change the logged in account's password.  My browser, quite correctly, includes my PHP session cookie with both of these requests, which makes bitcointalk run them exactly as if I had intentionally performed those actions.  Now imagine that it's your bank account open in tab1.  (also note that the CSRF doesn't require the tab to be open, only that the session cookie is still valid, I've used tabs just to illustrate)

The solution is to make a session cookie necessary but insufficient to perform these actions.  In the server-side session you make up a random number, a session nonce.  You then include that nonce as an variable in any POST form.  If that number is not present in the POST request, then the request should be denied.

So, legitimate pages in tab1 will include this nonce because the server knows it and includes it in the
s it sends.  tab2's javascript is sandboxed away from tab1 and cannot read it's DOM and hence cannot read the nonce.  Any malicious POST requests it makes will be ignored.

Depending on what information is fetchable via a GET request, you may also consider adding that nonce to every URL your serverside code generates as well. For example, I wouldn't be surprised to find a web site that has "https://insecuresite.com/accountdetails.php" pre-load the account details form with your password.  tab2's javascript would then just read that page to get your password.

You see then that it isn't true that simply using PHP sessions stops CSRF (it's more true to say that your PHP session is what is being attacked in CSRF); but CSRF protection is definitely implemented using PHP sessions.
Thank you for taking the time to address my concerns with great detail. Finally someone who is a better communicator can explain why I don't like PHP sessions. Also I refuse to use sessions as when I merge my code with open source library becuase there are possibilites that a Cheaperinbitcoins library might be shared on the same VPS (2 diff websites on the same box) and i know php sessions are guessable to some extent with multiple websites running as the more users take up the total unique php session ids the eaiser it becomes to generate/guess a php session. Atleast with homegrown cookie sessions they are less guessable if done correctly.
hero member
Activity: 504
Merit: 502
I'm not sure it's been made very clear from the above argument (both parties obviously know what they're talking about, but it doesn't help Xenland if you're not familiar with the ideas already); PHP sessions are not sufficient on their own to prevent CSRF... in fact, PHP sessions are the thing that makes CSRF possible.

Let's say in tab1 I'm logged into bitcointalk.  "Logged in" means I have a session cookie on my browser that is sent with every request to the the server, allowing the server to access my server-side "state".  The stateless HTTP has become stateful.  The session cookie is usually some long, random number that can't be guessed and is known only to your browser and the server.

Now, in tab2, some malicious site runs javascript that sends a carefully crafted POST message to bitcointalk that makes the currently logged in account send a PM to the attackers bitcointalk account and a second POST to change the logged in account's password.  My browser, quite correctly, includes my PHP session cookie with both of these requests, which makes bitcointalk run them exactly as if I had intentionally performed those actions.  Now imagine that it's your bank account open in tab1.  (also note that the CSRF doesn't require the tab to be open, only that the session cookie is still valid, I've used tabs just to illustrate)

The solution is to make a session cookie necessary but insufficient to perform these actions.  In the server-side session you make up a random number, a session nonce.  You then include that nonce as an variable in any POST form.  If that number is not present in the POST request, then the request should be denied.

So, legitimate pages in tab1 will include this nonce because the server knows it and includes it in the s it sends.  tab2's javascript is sandboxed away from tab1 and cannot read it's DOM and hence cannot read the nonce.  Any malicious POST requests it makes will be ignored.

Depending on what information is fetchable via a GET request, you may also consider adding that nonce to every URL your serverside code generates as well. For example, I wouldn't be surprised to find a web site that has "https://insecuresite.com/accountdetails.php" pre-load the account details form with your password.  tab2's javascript would then just read that page to get your password.

You see then that it isn't true that simply using PHP sessions stops CSRF (it's more true to say that your PHP session is what is being attacked in CSRF); but CSRF protection is definitely implemented using PHP sessions.
mrb
legendary
Activity: 1512
Merit: 1028
See http://en.wikipedia.org/wiki/Csrf#Prevention for how to prevent CSRF. Most often, web frameworks provides anti-CSRF mechanisms.
legendary
Activity: 980
Merit: 1003
I'm not just any shaman, I'm a Sha256man
Thanks for the information mates! now I feel more confident implementing this.
member
Activity: 109
Merit: 10
Are you serious? You call yourself a PHP programmer for hire and you swear by PHP sessions that they are the silver bullet to this problem?

PHP session make the stateless HTTP protocol stateful. There is no CSRF protection. All it does is attach a cookie to the client that contains a hash that can be used to store temporary variables on the server.

LMAO I never claimed I swear by them, but in this situation they would work. I am not going to get into a flame war with someone that has not clue about how to uses sessions, I can see you don't.


Clearly the attacker would be able to use the victim's browser to request a URL such as 'example.com/shred_and_rm_root_directory.php'. And PHP sessions would not do a single damn thing about it.

I'm curious to know how you can prevent CSRF attacks only with PHP sessions. (serious question). Maybe its you or me misunderstanding the OP's situation.

First off you assume I say all this stuff and I don't I never calmed anything you have said. All i said was in the situation of OP's you can use php sessions. While you are correct that sessions with no other coding will not prevent CSRF attacks from happening. I use them more of an aid to make sure the user is who they say they are, after login. And NO I will not write out my php code or psuedo code on how to do it. Your a great PHP programmer you can figure it out.  Wink


Thanks, but I was trying to figure out if we were both on the same page. If you could prevent CSRF attacks only with PHP sessions that would be something I did not know. I'm glad we resolved the issue and delivered to the OP.
legendary
Activity: 1498
Merit: 1000
Are you serious? You call yourself a PHP programmer for hire and you swear by PHP sessions that they are the silver bullet to this problem?

PHP session make the stateless HTTP protocol stateful. There is no CSRF protection. All it does is attach a cookie to the client that contains a hash that can be used to store temporary variables on the server.

LMAO I never claimed I swear by them, but in this situation they would work. I am not going to get into a flame war with someone that has not clue about how to uses sessions, I can see you don't.


Clearly the attacker would be able to use the victim's browser to request a URL such as 'example.com/shred_and_rm_root_directory.php'. And PHP sessions would not do a single damn thing about it.

I'm curious to know how you can prevent CSRF attacks only with PHP sessions. (serious question). Maybe its you or me misunderstanding the OP's situation.

First off you assume I say all this stuff and I don't I never calmed anything you have said. All i said was in the situation of OP's you can use php sessions. While you are correct that sessions with no other coding will not prevent CSRF attacks from happening. I use them more of an aid to make sure the user is who they say they are, after login. And NO I will not write out my php code or psuedo code on how to do it. Your a great PHP programmer you can figure it out.  Wink
member
Activity: 109
Merit: 10
Are you serious? You call yourself a PHP programmer for hire and you swear by PHP sessions that they are the silver bullet to this problem?

PHP session make the stateless HTTP protocol stateful. There is no CSRF protection. All it does is attach a cookie to the client that contains a hash that can be used to store temporary variables on the server.

LMAO I never claimed I swear by them, but in this situation they would work. I am not going to get into a flame war with someone that has not clue about how to uses sessions, I can see you don't.


Clearly the attacker would be able to use the victim's browser to request a URL such as 'example.com/shred_and_rm_root_directory.php'. And PHP sessions would not do a single damn thing about it.

I'm curious to know how you can prevent CSRF attacks only with PHP sessions. (serious question). Maybe its you or me misunderstanding the OP's situation.
legendary
Activity: 1498
Merit: 1000
Are you serious? You call yourself a PHP programmer for hire and you swear by PHP sessions that they are the silver bullet to this problem?

PHP session make the stateless HTTP protocol stateful. There is no CSRF protection. All it does is attach a cookie to the client that contains a hash that can be used to store temporary variables on the server.

LMAO I never claimed I swear by them, but in this situation they would work. I am not going to get into a flame war with someone that has not clue about how to uses sessions, I can see you don't.
member
Activity: 109
Merit: 10
This is why I would Use php sessions then you can make sure the correct user is logged in and make the XSRF almost impossible to do.

Are you serious? You call yourself a PHP programmer for hire and you swear by PHP sessions that they are the silver bullet to this problem?

PHP session make the stateless HTTP protocol stateful. There is no CSRF protection. All it does is attach a cookie to the client that contains a hash that can be used to store temporary variables on the server.

1) Client visits website
2) PHP responds with 'Set-Cookie: '
3) Client sends 'Cookie: ' on future requests
4) PHP receives client's cookie value, and can set temporary variables that references to this hash.

As you can see, CSRF attacks are still possible. The browser still attaches the hash it received on the initial request. An attacker could manipulate the browser to request a resource from the server and the browser will send the appropriate cookies for the website.

Quote
For example lets say this is a legitimate request from the merchant....
http://cheaperinbitcoins.com/api/update_product.php?product_id=1&price=0.00&cookievalue=123456

Yes, that would work fine. The attacker can not access the browser's cookies that was assigned from a different domain. You would have to make sure your website is not vulnerable to XSS though.
legendary
Activity: 980
Merit: 1003
I'm not just any shaman, I'm a Sha256man
This is why I would Use php sessions then you can make sure the correct user is logged in and make the XSRF almost impossible to do.
I feel I'd have to rewrite my entire code to facilitate that on top of many of the negative experiences I've heard from php sessions.
legendary
Activity: 1498
Merit: 1000
This is why I would Use php sessions then you can make sure the correct user is logged in and make the XSRF almost impossible to do.
legendary
Activity: 980
Merit: 1003
I'm not just any shaman, I'm a Sha256man
legendary
Activity: 980
Merit: 1003
I'm not just any shaman, I'm a Sha256man
As a common and practical practice, destructive actions should always be handled through POST requests. This is to make sure the user doesn't accidentally do something destructive (updating the price, deleting something) by entering the url through the browser.

Quote
The product wouldn't update because the cookie isn't included in the request and thus wouldn't ever successfully work.
No, your browser is making the GET request, not the attacker. Therefore your browser will supply the cookie to the website. The operation will succeed.

I realise that fact that the cookie is sent with the request. I mean tho that the XSRF attacker would have to "know" the cookie value as well by requiring the cookie value to be placed in each request

For example lets say this is a legitimate request from the merchant....
http://cheaperinbitcoins.com/api/update_product.php?product_id=1&price=0.00&cookievalue=123456

My script would then check that the cookie request it self was valid and that it matches the value included in the GET request and see that the cookie value and the string query value(named cookievalue) are in fact 123456.

Now lets say an attacker did the following
http://cheaperinbitcoins.com/api/update_product.php?product_id=1&price=0.00

My script would then check that the cookie request it self was valid and that it matches the value included in the GET request, how ever this time it sees that the cookie value is " blank " and dosen't match the users cookie value.

--------------------
Some thoughts on my mind, the only way an attacker could spoof a request is if they knew the cookie value exactly.

This would require for an attacker to either
*Have control of my website to inject javascripts to auto send the correct value(which is pointless if you already have control you might as well just start changing stuff like you own the place)

*Found a way around my satiation inputs to inject JavaScript to acquire the merchants cookie value and later send it to a program that will run the script to deface the product page.
member
Activity: 109
Merit: 10
As a common and practical practice, destructive actions should always be handled through POST requests. This is to make sure the user doesn't accidentally do something destructive (updating the price, deleting something) by entering the url through the browser.

Quote
The product wouldn't update because the cookie isn't included in the request and thus wouldn't ever successfully work.
No, your browser is making the GET request, not the attacker. Therefore your browser will supply the cookie to the website. The operation will succeed.
legendary
Activity: 1498
Merit: 1000
Use php sessions I think they would work the best right here for you
legendary
Activity: 980
Merit: 1003
I'm not just any shaman, I'm a Sha256man
Forgot to include my solution exactly... basically my solution is this


http://cheaperinbitcoins.com/api/update_product.php?product_id=1&price=0.00&cookie=
legendary
Activity: 980
Merit: 1003
I'm not just any shaman, I'm a Sha256man
I'm working on a WYSIWYG "product page editor" for Cheaper In Bitcoins so my merchants can look at their product page and edit it by clicking on specific elements(like price, title, description) instead of using a monolithic form to fill out but I'm using Ajax get requests and would like to avoid XSRF attacks on peoples products. I'm thinking maybe to prevent this I could have a javascript load the already encrypted cookie session to sign the request. Does this sound like a solution to prevent XSRF attacks?

For instance my website cookies should only be loaded on my website "CheaperInBitcoins.com" so I'm assuming that in order for some one to do a XSRF attack it would at least be limited to my own website. So if someone where to have an image on bitcointalk.org that really linked to http://cheaperinbitcoins.com/api/update_product.php?product_id=1&price=0.00
an attempt to make the merchants products free (or even worse deface the products description from a competing seller)

The product wouldn't update because the cookie isn't included in the request and thus wouldn't ever successfully work.
The cookie would never be included unless your using a hacky browser which sends cookie data to websites with out regard to the domain(which almost no normal user would be using so thats not the case)
My website would check the cookie of course and make sure that it validates with the logged in merchant.

Am i missing anything?
comments suggestions?
Jump to: