Jump to content

php, ajax, sessions and security


ajoo
Go to solution Solved by requinix,

Recommended Posts

Hi all !

 

In my previous question asked today I said that I am using dropdown lists for selecting country, state, city and pin.

 

The initial lists are blank and use the selection of country to trigger the loading of states and choosing a state triggers the loading of cities and so I am using ajax for this purpose - more specifically the $ajax() function of jquery.

 

In a normal call to a php page, the integrity is maintained via sessions, and csrf is prevented via tokens embedded in the form, but how do I take care of these when data is being passed through the ajax call ? Any other security measures that need to be looked into while using this method or special security mechanisms that I need to apply? 

 

I would of-course check the data received this way, by using all the normal data validation methods on the server side.

 

Thanks all !

Edited by ajoo
Link to comment
Share on other sites

  • Solution

Sessions are managed with cookies and the browser will make that all work automatically with the AJAX.

 

I wouldn't expect that you'd need to worry about CSRFs for this. It's not like the queries are performing any actions - what CSRFs are really about. But if you still need to have it then pass the token in the AJAX request; how you do that varies but probably means putting the token into the page with your PHP and appending it to the AJAX URL or including it in the request data.

Link to comment
Share on other sites

Hi requinix, 

 

Thanks for the reply and sorry for the delayed response from me. As advised, I am thinking of not passing the CSRF token along with the data in Ajax. Even though you have described how it could be done,I am not sure how to go about it. However I would like to still ask / reconfirm if there could be a big risk in doing it without that protection? 

 

Thanks !

Link to comment
Share on other sites

If the AJAX call does not perform any lasting action (eg, change the database, make a log entry) then you probably don't need CSRF protection... but if you're not sure then use it.

 

What I'm talking about goes like

$.ajax("url", {
	whatever: stuff,
	data: {
		key: value,
		csrf: <?=json_encode(whatever_thing_gets_you_the_csrf_token())?>
	}
});
PHP puts the CSRF token right into the $.ajax call's data. If you can't do it that way (like the AJAX work is external) then you can put it into a variable on the page

<script type="text/javascript">window.CSRFTOKEN = <?=json_encode(whatever_thing_gets_you_the_csrf_token())?>;</script>
and reference that in the code.
  • Like 1
Link to comment
Share on other sites

What kind of attack are you trying to prevent? So an attacker forges a GET request to your loading script -- and then what? If they're on a different domain, they cannot read the response, because the same-origin policy prevents this. If they're on the same domain and managed to find a vulnerability which allows them to make requests and read the responses, then what prevents them from simply stealing your CSRF token? You would have to assume that the attacker can access the Ajax target script but somehow cannot access any other script. This doesn't make much sense.

 

CSRF affects requests which have side effects (POST, PUT, DELETE, ...). That's when you need an anti-CSRF token. Not when loading data.

 

How to safely include the token in your JavaScript code is described here.

  • Like 1
Link to comment
Share on other sites

Hi Requinix & Guru Jacques !!

 

Thanks for the replies ! I have read and re-read them and If anything I am a little more confused.  :confused:

 

Anyways I'll try and clear some of my doubts. Please forgive if they are really noob !

 

 

If the AJAX call does not perform any lasting action (eg, change the database, make a log entry) then you probably don't need CSRF protection... but if you're not sure then use it.

 
Sure this data would eventually go to a database after the regular validation on the server side.
 
 
What kind of attack are you trying to prevent?

 

To begin with I am not sure if this question by Guru Jacques is directed at me or at Requinix's reply !?  

 

As I understand it, you are saying that if an attacker is able to exploit a vulnerability to get the response, then he/she has access to the data being sent as well as the CSRF token which is a part of that data and so it's pointless???

 

 

 

CSRF affects requests which have side effects (POST, PUT, DELETE, ...). 

 

But I am using the $ajax function with type POST to send data to the server as below 

	$.ajax({
		type: "POST",
		url: "loadData.php",
		data: dataString,
		cache: false,
                ...

So that would means that I should use CSRF protection. :confused:  which contradicts the earlier statement where it says that if the data is vulnerable then so is the token?

 

Please explain what am I reading wrong if not everything !! :o

 

Thanks !

Link to comment
Share on other sites

Okay, let's take a step back and talk about CSRF first.

 

CSRF is about preventing an external bad user from tricking your good user into doing Bad Things on your site. Let's say a user has the ability to delete their account, and you do that with a simple GET URL:

<a href="/delete-my-account.php">Delete my account</a>
That script checks that the user is logged in, naturally, but then otherwise goes right into the deletion.

 

Now I come along, register on your site, look around, and see that the Delete button is just a link. I'm evil, so what I do is craft a bit of HTML to your site

<img src="https://www.example.com/delete-my-account.php" width="1" height="1">
I then embed this image all over the internet.

 

Jacques is a good user who has the misfortune of (1) being a member of your site, (2) being logged in, and (3) finding that image somewhere. He doesn't know it but the browser requested that image when it loaded the page he's on, causing your site to delete his account. He doesn't know this until he eventually returns to your site and sees that he can't log in anymore.

 

"Okay, so don't use GET."

GET isn't the problem. It's a very easy way of doing CSRFs but isn't a requirement. If you required POST but still didn't have any checks then my attack would be a bit more complicated,

<form id="loldeletetheiraccount" action="https://www.example.com/delete-my-account.php" method="post">
</form>
<script type="text/javascript">document.getElementById("loldeletetheiraccount").submit();</script>
and a bit harder to pull off because I'd have to embed runnable HTML somewhere (so this technique is generally combined with XSS) but it's still totally possible.

 

"Add a confirmation checkbox and/or button."

Then I'll just put that information into my form.

 

"Check the referrer?"

Better, but still not foolproof: it's also quite possible that a browser won't send any referrer at all, so you'd have to allow your own site and an empty referrer, and that empty referrer is how I break your site.

 

The only way to prevent this kind of attack is with a CSRF token. It's a piece of data that the attacker can't know ahead of time so they can't put into the image or form. You also have to make sure that's not possible for them to find it, so that means Javascript cannot have a way of automatically getting the CSRF token from your site. Therefore it has to be inserted directly into the page that needs it.

 

 

Following so far? Can you piece together the rest of it by yourself?

  • Like 1
Link to comment
Share on other sites

Hi requinix, 

 

Thanks for the reply and in quite some detail.  

 

I hope my questions are valid too. In the following code snippet,

 

<img src="https://www.example.com/delete-my-account.php" width="1" height="1">

 

where does the delete-my-account.php file lie ? On www.example.com ? which cannot be my site but a site of the attacker. If that's correct and I use CSP and allow scripts only from my site alone, would not that bit of Js be foiled anyways irrespective of the GET or POST ?

 

 

 

"Check the referrer?"

 

I think I was warned by Guru Jacques, a long time ago, that that is not a very reliable check since the headers can easily be manipulated. 

 

 

 

Therefore it has to be inserted directly into the page that needs it.

 

hmm all the forms on all the pages, that I have on my site use the CSRF tokens generated afresh and sent along as POST data, hidden of-course.  It's the first time I have used ajax and have no prior experience with it. 

 

Guru Jacques' link demonstrates how to append a token to a jason object, however I am using a simple dataString and am trying to figure if it is possible to append to that the CSRF token securely.

 

I hope that my logic above makes sense.

 

Thanks loads ! 

Edited by ajoo
Link to comment
Share on other sites

where does the delete-my-account.php file lie ? On www.example.com ? which cannot be my site but a site of the attacker. If that's correct and I use CSP and allow scripts only from my site alone, would not that bit of Js be foiled anyways irrespective of the GET or POST ?

delete-my-account.php is a page on "your" site that lets the person delete their account. It is a PHP script and therefore not subject to CSP.

 

hmm all the forms on all the pages, that I have on my site use the CSRF tokens generated afresh and sent along as POST data, hidden of-course.

Then you can grab the token from the hidden input. Just like how you're doing with all the other data being submitted in the request.
Link to comment
Share on other sites

Appearently there's a lot of confusion about almost every aspect.

 

You (ajoo) said you're using the POST method to load data. This is wrong. Every method has a specific purpose: GET is meant to get a resource (hence the name), POST is meant to change a resource. When you mix that up, you'll create a lot of misunderstandings and potentially problems, so before you do anything, make sure you understand the basics of HTTP and then fix your application accordingly.

 

Then you're appearently still worried that an attacker can somehow read the data of another user. This is wrong. First off, domains are isolated from each other (see the same-origin policy), so another site cannot simply load user-specific content on your site. If this was possible, we'd all be in deep trouble, because every website could read our e-mails, access our PayPal accounts etc. The browser vendors have thought of that and prevent it. Of course there could be an attack within your own site, but only if there's a specific (XSS) vulnerability. As long as you prevent XSS, users cannot access data of others users. And if you fail to prevent XSS, it's too late anyway; your tokens won't help you.

 

In addition to that, you seem to think that CSP makes you immune to all JavaScript-related attacks. No. CSP only prevents specific attacks, and it only works in some browsers. It's not a magical security tool, not even against XSS. It's just a second line of defense in case your primary protection (escaping etc.) has failed.

 

Last but not least, there still seems to be confusion about CSRF attacks. As requinix already said, CSRF is about taking an action on behalf of another user (buy an article with their account, transfer their money, whatever). Your city list doesn't fall into this category. It's simply not possibly to talk about CSRF attacks in this context in any meaningful way.

 

CSRF becomes relevant when you change data. That's when you need an anti-CSRF token, and you can get additional protection with the new SameSite cookie attribute.

  • Like 1
Link to comment
Share on other sites

Hi Requinix and Guru Jacques !

 

Thank you both for being so patient with me on this. The good thing is that it helped me to come out with so many of my doubts and misconceptions and clear them. 

 

 

 

GJ : Your city list doesn't fall into this category. It's simply not possibly to talk about CSRF attacks in this context in any meaningful way.

 

I have spent a day reading up on the CSRF and XSS attacks. I have also read this thread a few times and realise that requinix had at the very outset mentioned that for this case a CSRF token is probably  not needed but I could use it if I was not sure of my AJAX calls actions.

 

 

 

 

GJ: When you mix that up, you'll create a lot of misunderstandings and potentially problems, so before you do anything, make sure you understand the basics of HTTP and then fix your application accordingly.

 

I will scan the application again for this. I think I am not using get anywhere. I was using it wrong, as a logoff link, and you cautioned me to use a button instead with post and which I did. Still, i'll scan the application again. Thanks.  

 

 

 

In addition to that, you seem to think that CSP makes you immune to all JavaScript-related attacks.

 

Well yes, I thought of it as something like that. 

 

 

 

 

Last but not least, there still seems to be confusion about CSRF attacks

 

I think that's cleared now.

 

 

 

CSRF becomes relevant when you change data. That's when you need an anti-CSRF token, and you can get additional protection with the new SameSite cookie attribute.

 

Ouch !! Yet another method of prevention !!  :o

 

:happy-04:  :happy-04: Thanks for this. Will read about it.

  

 

So I won't be using the CSRF token for the drop-down menu data that is sent via Ajax for this particular case of mine.

 

Thanks loads !!

Edited by ajoo
Link to comment
Share on other sites

I think I am not using get anywhere.

 

I was talking about the incorrect use of POST to load data. This should be GET.

 

If you've literally replaced GET with POST in all forms and Ajax requests, that's a mistake. You need to choose the right method: GET loads data, POST changes data.

  • Like 1
Link to comment
Share on other sites

Hi Guru Jacques, 

 

Thanks for the reply.

 

 

 

I was talking about the incorrect use of POST to load data.

 

I made a mistake, which i subsequently rectified, in my choice of the word "load" data. AJAX is sending the data to the server. The data.php then creates a response which is used to populate the next dropdown with the name of the states or cities or values of pins. 

 

 

I meant If you've literally replaced GET with POST in all forms and Ajax requests, that's a mistake.

 

I have not replaced GETs with POSTs blindly anywhere. I meant that I would scan the code to see if I have used post or get in a wrong manner anywhere.

 

Thanks again for cautioning me !

Link to comment
Share on other sites

You do load data, namely states, cities etc. It doesn't matter that you also send data to the server. The criterion for choosing between GET and POST is whether the request merely retrieves data from the server or permanently changes data.

 

Retrieving a list of cities for a dropdown menu shouldn't change anything, so this is a classical example for a GET request.

Link to comment
Share on other sites

hmmm I see. So I should change the type: POST to GET in the AJAX function and that would be technically more correct ! So calls to the server where the data passed is used in SELECT statements to retrieve a set of values are good candidates to use GET i suppose.

$.ajax({
        type: "GET",
        url: "loadData.php",
        data: dataString,
        cache: false,
...

Changed along with corresponding changes in loadData.php and it works just the same as it should. 

 

Thanks loads !

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.