Take the 2-minute tour ×
Webmasters Stack Exchange is a question and answer site for pro webmasters. It's 100% free, no registration required.

I have a site that uses ajax calls to perform a number of functions. They have the webbrowser call back to a script - ajax.php. Though I use post data to transmit the data and limit the commands that the ajax script can call, there is really nothing preventing users from spoofing ajax calls to attempt to manipulate the site. Is there some blanket way to prevent users from spoofing the calls? Is there a way to ensure that an ajax call does in fact come from my website and not from some other script or site?

Or do I simply have to check the boundary conditions in the php script and prevent the users from spoofing things they wouldn't be allowed to do, but allow them to spoof where they would be allowed.

share|improve this question
    
Are the ajax calls completely unauthenticated? Do you create sessions for each? Are there patterns to the abuse? And is the problem specific manipulations or more the amount of load it adds to the site? –  artlung Jul 27 '10 at 14:32
    
Can you post more specifics please? What are the AJAX calls doing? What are they manipulating? What problems occur if the script is called outside of AJAX? –  DisgruntledGoat Jul 27 '10 at 15:49
    
I'm not really asking about a specific circumstance, but rather for a general solution applicable to many circumstances. If there is such a solution, which it doesn't seem like there is. –  Daniel Bingham Jul 28 '10 at 4:11
add comment

5 Answers

up vote 12 down vote accepted

I don't think there is any way to do this reliably, since any information you might send could be spoofed, depending how clever the user is.

If you just want a simple block of people calling not from your page, then you could check the referrer, use a cookie or add a random hidden field sent by the calling page which expires after a certain time. But these are easy to spoof if the user is really determined.

share|improve this answer
2  
+1 .. just like it is impossible to keep people from saving local copies of anything that their browser displays. Its more of a contest to see if you can make them give up and move on to something else before they figure it out. –  Tim Post Jul 27 '10 at 13:53
add comment

In short, no. Any request made to a URL through GET or POST can be made by anyone using any software. Actually, an AJAX request is really no different from loading the URL directly, except with the latter the returned data is displayed in the browser like a web page.

This is exactly the reason why you should always validate submitted data on the server, whether or not you do any Javascript validation.

It's not clear exactly what the server-side script is doing and what might go wrong, but if users are able to "manipulate the site" by calling your script with bad data then You Are Doing It Wrong.

Probably the best solution will be to introduce some form of authentication.

share|improve this answer
add comment

So you basically want to limit ajax.php to only responding to AJAX requests?

I'm no php expert, but it seems like its possible to determine if a given request is coming from AJAX or a "regular" browser request by checking the value of $_SERVER['HTTP_X_REQUESTED_WITH'].

Source

share|improve this answer
2  
good point, assuming the abuser does not use ajax or forge that HTTP header –  Adam Jul 28 '10 at 0:13
add comment

As someone else pointed out... ajax calls are just receivers of $_GET or $_POST, so my approach has always been to just treat them as I would any action page and filter/sanitize the input. If you have a small variation of what you expect like a month for example, and you know it's always in "Jan, Feb, Mar..." format, you could set an array of the expected values and filter against it. Trap anything that doesn't match and optionally throw something back like "Bzzt... thanks for playing..."

I can't think of an example where my Ajax script would need to be any more secure than a form submission.

HTH

share|improve this answer
    
+1 for "Bzzt" - which becomes that much funnier in the context of "Bzzt - thanks for playing!" followed by a slow fade to black accompanied with a three hour ban enforced by a cookie set on the user's machine (I'm sure they'd get the message) –  danlefree Nov 19 '10 at 3:00
add comment

I think a major chunk of your solution will be rate limiting traffic from a specific user fingerprint. Maybe a hash of IP address, User Agent string and the data being sent.

Also, binding the page that calls the ajax to the ajax returned data closer can be of help. So on the page in question, at page load send down a session key that is good for X sessions, for each ajax request your JavaScript will need to pass that key back or the ajax will return a failure. Once your page hits X+1 ajax calls, force the user to do some action (maybe captcha? maybe even something like a mousemove or tap event depending on the UA) before sending a new session key down the wire (out of band from the original ajax) then restart the process.

Though as I think about it, it's possible that maybe part of your problem is lax validation of the parameters sent. If people can just play with the parameters sent and get back valid data then make that harder to do. How to do that depends on what kind of values are being sent by the client, and what kind of mischief a bad actor can make by sending bad values.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.