How to make sure AJAX is called by JavaScript? - php

I asked a similar question before, and the answer was simply:
if JavaScript can do it, then any client can do it.
But I still want to find out a way do restrict AJAX calls to JavaScript.
The reason is :
I'm building a web application, when a user clicks on an image, tagged like this:
<img src='src.jpg' data-id='42'/>
JavaScript calls a PHP page like this:
$.ajax("action.php?action=click&id=42");
then action.php inserts rows in database.
But I'm afraid that some users can automate entries that "clicks" all the id's and such, by calling necessary url's, since they are visible in the source code.
How can I prevent such a thing, and make sure it works only on click, and not by calling the url from a browser tab?
p.s.
I think a possible solution would be using encryption, like generate a key on user visit, and call the action page with that key, or hash/md5sum/whatever of it. But I think it can be done without transforming it into a security problem. Am I right ? Moreover, I'm not sure this method is a solution, since I don't know anything about this kind of security, or it's implementation.

I'm not sure there is a 100% secure answer. A combination of a server generated token that is inserted into a hidden form element and anti-automation techniques like limiting the number of requests over a certain time period is the best thing I can come up with.
[EDIT]
Actually a good solution would be to use CAPTCHAS

Your question isn't really "How can I tell AJAX from non-AJAX?" It's "How do I stop someone inflating a score by repeated clicks and ballot stuffing?"
In answer to the question you asked, the answer you quoted was essentially right. There is no reliable way to determine whether a request is being made by AJAX, a particular browser, a CURL session or a guy typing raw HTTP commands into a telnet session. We might see a browser or a script or an app, but all PHP sees is:
GET /resource.html HTTP/1.1
host:www.example.com
If there's some convenience reason for wanting to know whether a request was AJAX, some javascript libraries such as jQuery add an additional HTTP header to AJAX requests that you can look for, or you could manually add a header or include a field to your payload such as AJAX=1. Then you can check for those server side and take whatever action you think should be made for an AJAX request.
Of course there's nothing stopping me using CURL to make the same request with the right headers set to make the server think it's an AJAX request. You should therefore only use such tricks where whether or not the request was AJAX is of interest so you can format the response properly (send a HTML page if it's not AJAX, or JSON if it is). The security of your application can't rely on such tricks, and if the design of your application requires the ability to tell AJAX from non-AJAX for security or reliability reasons then you need to rethink the design of your application.
In answer to what you're actually trying to achieve, there are a couple of approaches. None are completely reliable, though. The first approach is to deposit a cookie on the user's machine on first click, and to ignore any subsequent requests from that user agent if the cookie is in any subsequent requests. It's a fairly simple, lightweight approach, but it's also easily defeated by simply deleting the cookie, or refusing to accept it in the first place.
Alternatively, when the user makes the AJAX request, you can record some information about the requesting user agent along with the fact that a click was submitted. You can, for example store a hash (stored with something stronger than MD5!) of the client's IP and user agent string, along with a timestamp for the click. If you see a lot of the same hash, along with closely grouped timestamps, then there's possibly abuse being attempted. Again, this trick isn't 100% reliable because user agents can see any string they want as their user agent string.

Use post method instead of get.Read the documentation here http://api.jquery.com/jQuery.post/ to learn how to use post method in jquery

You could, for example, implement a check if the request is really done with AJAX, and not by just calling the URL.
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
// Yay, it is ajax!
} else {
// no AJAX, man..
}

This solution may need more reflexion but might do the trick
You could use tokens as stated in Slicedpan's answer. When serving your page, you would generate uuids for each images and store them in session / database.
Then serve your html as
<img src='src.jpg' data-id='42' data-uuid='uuidgenerated'/>
Your ajax request would become
$.ajax("action.php?action=click&uuid=uuidgenerated");
Then on php side, check for the uuid in your memory/database, and allow or not the transaction. (You can also check for custom headers sent on ajax as stated in other responses)
You would also need to purge uuids, on token lifetime, on window unload, on session expired...
This method won't allow you to know if the request comes from an xhr but you'll be able to limit their number.

Related

Why is id variable not passed to this file? [duplicate]

What's the difference when using GET or POST method? Which one is more secure? What are (dis)advantages of each of them?
(similar question)
It's not a matter of security. The HTTP protocol defines GET-type requests as being idempotent, while POSTs may have side effects. In plain English, that means that GET is used for viewing something, without changing it, while POST is used for changing something. For example, a search page should use GET, while a form that changes your password should use POST.
Also, note that PHP confuses the concepts a bit. A POST request gets input from the query string and through the request body. A GET request just gets input from the query string. So a POST request is a superset of a GET request; you can use $_GET in a POST request, and it may even make sense to have parameters with the same name in $_POST and $_GET that mean different things.
For example, let's say you have a form for editing an article. The article-id may be in the query string (and, so, available through $_GET['id']), but let's say that you want to change the article-id. The new id may then be present in the request body ($_POST['id']). OK, perhaps that's not the best example, but I hope it illustrates the difference between the two.
When the user enters information in a form and clicks Submit , there are two ways the information can be sent from the browser to the server: in the URL, or within the body of the HTTP request.
The GET method, which was used in the example earlier, appends name/value pairs to the URL. Unfortunately, the length of a URL is limited, so this method only works if there are only a few parameters. The URL could be truncated if the form uses a large number of parameters, or if the parameters contain large amounts of data. Also, parameters passed on the URL are visible in the address field of the browser not the best place for a password to be displayed.
The alternative to the GET method is the POST method. This method packages the name/value pairs inside the body of the HTTP request, which makes for a cleaner URL and imposes no size limitations on the forms output. It is also more secure.
The best answer was the first one.
You are using:
GET when you want to retrieve data (GET DATA).
POST when you want to send data (POST DATA).
There are two common "security" implications to using GET. Since data appears in the URL string its possible someone looking over your shoulder at Address Bar/URL may be able to view something they should not be privy to such as a session cookie that could potentially be used to hijack your session. Keep in mind everyone has camera phones.
The other security implication of GET has to do with GET variables being logged to most web servers access log as part of the requesting URL. Depending on the situation, regulatory climate and general sensitivity of the data this can potentially raise concerns.
Some clients/firewalls/IDS systems may frown upon GET requests containing an excessive amount of data and may therefore provide unreliable results.
POST supports advanced functionality such as support for multi-part binary input used for file uploads to web servers.
POST requires a content-length header which may increase the complexity of an application specific client implementation as the size of data submitted must be known in advance preventing a client request from being formed in an exclusively single-pass incremental mode. Perhaps a minor issue for those choosing to abuse HTTP by using it as an RPC (Remote Procedure Call) transport.
Others have already done a good job in covering the semantic differences and the "when" part of this question.
I use GET when I'm retrieving information from a URL and POST when I'm sending information to a URL.
You should use POST if there is a lot of data, or sort-of sensitive information (really sensitive stuff needs a secure connection as well).
Use GET if you want people to be able to bookmark your page, because all the data is included with the bookmark.
Just be careful of people hitting REFRESH with the GET method, because the data will be sent again every time without warning the user (POST sometimes warns the user about resending data).
This W3C document explains the use of HTTP GET and POST.
I think it is an authoritative source.
The summary is (section 1.3 of the document):
Use GET if the interaction is more like a question (i.e., it is a safe operation such as a query, read operation, or lookup).
Use POST if:
The interaction is more like an order, or
The interaction changes the state of the resource in a way that the
user would perceive (e.g., a subscription to a service), or
The user be held accountable for the results of the interaction.
Get and Post methods have nothing to do with the server technology you are using, it works the same in php, asp.net or ruby. GET and POST are part of HTTP protocol.
As mark noted, POST is more secure. POST forms are also not cached by the browser.
POST is also used to transfer large quantities of data.
The reason for using POST when making changes to data:
A web accelerator like Google Web Accelerator will click all (GET) links on a page and cache them. This is very bad if the links make changes to things.
A browser caches GET requests so even if the user clicks the link it may not send a request to the server to execute the change.
To protect your site/application against CSRF you must use POST. To completely secure your app you must then also generate a unique identifier on the server and send that along in the request.
Also, don't put sensitive information in the query string (only option with GET) because it shows up in the address bar, bookmarks and server logs.
Hopefully this explains why people say POST is 'secure'. If you are transmitting sensitive data you must use SSL.
GET and POST are HTTP methods which can achieve similar goals
GET is basically for just getting (retrieving) data, A GET should not have a body, so aside from cookies, the only place to pass info is in the URL and URLs are limited in length , GET is less secure compared to POST because data sent is part of the URL
Never use GET when sending passwords, credit card or other sensitive information!, Data is visible to everyone in the URL, Can be cached data .
GET is harmless when we are reloading or calling back button, it will be book marked, parameters remain in browser history, only ASCII characters allowed.
POST may involve anything, like storing or updating data, or ordering a product, or sending e-mail. POST method has a body.
POST method is secured for passing sensitive and confidential information to server it will not visible in query parameters in URL and parameters are not saved in browser history. There are no restrictions on data length. When we are reloading the browser should alert the user that the data are about to be re-submitted. POST method cannot be bookmarked
All or perhaps most of the answers in this question and in other questions on SO relating to GET and POST are misguided. They are technically correct and they explain the standards correctly, but in practice it's completely different. Let me explain:
GET is considered to be idempotent, but it doesn't have to be. You can pass parameters in a GET to a server script that makes permanent changes to data. Conversely, POST is considered not idempotent, but you can POST to a script that makes no changes to the server. So this is a false dichotomy and irrelevant in practice.
Further, it is a mistake to say that GET cannot harm anything if reloaded - of course it can if the script it calls and the parameters it passes are making a permanent change (like deleting data for example). And so can POST!
Now, we know that POST is (by far) more secure because it doesn't expose the parameters being passed, and it is not cached. Plus you can pass more data with POST and it also gives you a clean, non-confusing URL. And it does everything that GET can do. So it is simply better. At least in production.
So in practice, when should you use GET vs. POST? I use GET during development so I can see and tweak the parameters I am passing. I use it to quickly try different values (to test conditions for example) or even different parameters. I can do that without having to build a form and having to modify it if I need a different set of parameters. I simply edit the URL in my browser as needed.
Once development is done, or at least stable, I switch everything to POST.
If you can think of any technical reason that this is incorrect, I would be very happy to learn.
GET method is use to send the less sensitive data whereas POST method is use to send the sensitive data.
Using the POST method you can send large amount of data compared to GET method.
Data sent by GET method is visible in browser header bar whereas data send by POST method is invisible.
Use GET method if you want to retrieve the resources from URL. You could always see the last page if you hit the back button of your browser, and it could be bookmarked, so it is not as secure as POST method.
Use POST method if you want to 'submit' something to the URL. For example you want to create a google account and you may need to fill in all the detailed information, then you hit 'submit' button (POST method is called here), once you submit successfully, and try to hit back button of your browser, you will get error or a new blank form, instead of last page with filled form.
I find this list pretty helpful
GET
GET requests can be cached
GET requests remain in the browser history
GET requests can be bookmarked
GET requests should (almost) never be used when dealing with sensitive data
GET requests have length restrictions
GET requests should be used only to retrieve data
POST
POST requests are not cached
POST requests do not remain in the browser history
POST requests cannot be bookmarked
POST requests have no restrictions on data length
The GET method:
It is used only for sending 256 character date
When using this method, the information can be seen on the browser
It is the default method used by forms
It is not so secured.
The POST method:
It is used for sending unlimited data.
With this method, the information cannot be seen on the browser
You can explicitly mention the POST method
It is more secured than the GET method
It provides more advanced features

Prevent external access to PHP scripts but allow AJAX

I've read a lot about .htaccess rules, checking headers, using encryption etc.. but I haven't found exactly the answer I'm after. I know that assuming the server is set up right, you can't access my precious PHP scripts with AJAX. I tried checking if an access variable was defined which disallowed address bar access but also blocked my AJAX requests.
If I have some PHP scripts that I use for AJAX calls, is there a way that I can prevent address bar access, PHP POST (cURL etc) as well as AJAX from outside my domain (assumed via cross-domain access restrictions) ?
There is NO way absolutely to safely/reliably identify which part of the browser the request comes from -- address bar, AJAX. There's a way to identify what is sending though browser/curl/etc via User-Agent header (but not reliably)
A quick but a lot less reliable solution would be to check for the following header. Most browsers attach it with AJAX calls. Be sure to thoroughly look into it, and implement.
X-Requested-With: XMLHttpRequest
NOTE: Do not trust the client if the resource is cruicial. You are better off implementing some other means of access filtering. Remember, any one can fake headers!
You can check whether the request isn't an Ajax request and forbid it, but it's not really safe due to the fact that the headers can be manipulated.
What you can do is to block every IP except the IP which is allowed to access those files.
What can do either is do implement a kind of authentication, where external applications have to send credentials to your script and the scripts checks if the client is valid.
Many ways, but they're all not really the best ways to achieve maximum security.
I do not know definitely. However – indirectly, you can do this. Pass a unique and constantly changing parameter (GET or POST) that only you have access to as proof of the origin. If the request lacks this unique variable, then its not from you. Think outside the box on this one. Could be anything you want, here are some ideas.
1) pass the result of a mathematical equation as proof of origin. Something that you can programmatically predict, yet not obvious to prying header hackers. i.e cos($dayOfYear) or even better base64_encode(base64_encode(cos($dayOfYear))).
2) store a unique key in a database that changes every time someone access the page. Then pass that key along with the request, and do some checks on the end page, if they dont match up to the database key, you've found the peeping tom. (note there will be logic involved for making sure the key hasn't changed in between transmission of requests)
etc..
Try to catch if isset SERVER['HTTP_ORIGIN'] from the POST access, it must be identical to your domain. If so, then the POST is generated by yourselft website and it's safe to process it.

how to prevent 'manual execution' of external PHP script

In simplest terms, I utilize external PHP scripts throughout my client's website for various purposes such as getting search results, updating content, etc.
I keep these scripts in a directory:
www.domain.com/scripts/scriptname01.php
www.domain.com/scripts/scriptname02.php
www.domain.com/scripts/scriptname03.php
etc..
I usually execute them using jQuery AJAX calls.
What I'm trying to do is find is a piece of code that will detect (from within) whether these scripts are being executed from a file via AJAX or MANUALLY via URL by the user.
IS THIS POSSIBLE??
I've have searched absolutely everywhere and tried various methods to do with the $_SERVER[] array but still no success.
What I'm trying to do is find is a piece of code that will detect (from within) whether these scripts are being executed from a file via AJAX or MANUALLY via URL by the user.
IS THIS POSSIBLE??
No, not with 100% reliability. There's nothing you can do to stop the client from simulating an Ajax call.
There are some headers you can test for, though, namely X-Requested-With. They would prevent an unsophisticated user from calling your Ajax URLs directly. See Detect Ajax calling URL
Most AJAX frameworks will send an X-Requested-With: header. Assuming you are running on Apache, you can use the apache_request_headers() function to retrieve the headers and check for it/parse it.
Even so, there is nothing preventing someone from manually setting this header - there is no real 100% foolproof way to detect this, but checking for this header is probably about as close as you will get.
Depending on what you need to protect and why, you might consider requiring some form of authentication, and/or using a unique hash/PHP sessions, but this can still be reverse engineered by anyone who knows a bit about Javascript.
As an idea of things that you can verify, if you verify all of these before servicing you request it will afford a degree of certainty (although not much, none if someone is deliberately trying to cirumvent your system):
Store unique hash in a session value, and require it to be sent back to you by the AJAX call (in a cookie or a request parameter) so can compare them at the server side to verify that they match
Check the X-Requested-With: header is set and the value is sensible
Check that the User-Agent: header is the same as the one that started the session
The more things you check, the more chance an attacker will get bored and give up before they get it right. Equally, the longer/more system resources it will take to service each request...
There is no 100% reliable way to prevent a user, if he knows the address of your request, from invoking your script.
This is why you have to authenticate every request to your script. If your script is only to be called by authenticated users, check for the authentication again in your script. Treat it as you will treat incoming user input - validate and sanitize everything.
On Edit: The same could be said for any script which the user can access through the URL. For example, consider profile.php?userid=3

how can i know if a php file was only called from js on the client side?

I have a javascript on my webpage which makes a call to a php file and passes some values to the php file. How can i know for sure that the call to the php file was from the js on my webpage and not directly entering the php url from the browsers address bar?
You'll want to use check if $_SERVER['HTTP_X_REQUESTED_WITH'] is XMLHttpRequest. That will prevent people from directly typing the URL in their browsers while allowing Ajax requests.
if ( ! empty($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' )
{
// Do something useful
}
You might want to see Do all browsers support PHP's $_SERVER['HTTP_X_REQUESTED_WITH']? for an explanation of what browsers/JavaScript libraries send the HTTP_X_REQUESTED_WITH header.
you can use the following info:
The headers that are being sent (usually Ajax calls adds special headers)
X-Requested-With: XMLHttpRequest
refering URL in the $_SERVER
Both can be hacked though.
If you need a very safe solution, you need to create a unique code for each request and send it to the server from your JS. This code needs to change after each time it is used.
You can't. Anything you expose to ajax you expose to the world. What's more is that someone wanting to get into that page could just run their own javascript on the page anyway and spoof any HTTP headers they want. These are the people you presumably want to keep out anyway. You shouldn't use measures that will limit non-malicious users but provide relatively little, if any, trouble to malicious users.
That said, I have never heard of HTTP_X_REQUESTED_WITH and based on preliminary reading it's not a good idea to use. I usually use POST and check that the _SERVER[REQUEST_METHOD] is POST because most modern browsers will use GET for any requests made by the url bar (that's my experience anyway). Again, this is not to keep bad people out, it's just to prevent accidents.
Another measure you should take is to check that a flag is sent to the page to help signal it's coming from a verified source. Depending upon how secure the ajax page is supposed to be, you may also want to verify session, etc. A somewhat safe way is to create a unique hash (e.g. md5) and store it in the DB with a timestamp. That hash indicates the page can be visited, say, up to three times. When the user clicks your ajax link, it sends the hash. The hash is flagged as consumed and cannot be reused. The hash should also go stale some time after creation (5 minutes? It depends and it's up to you).
Finally, make sure that this page is ignored by friendly robots (robots.txt, meta if possible, etc.). This will prevent people reaching it accidentally via search engines.

How to deny direct access to files in AJAX directory

I have several pages that call in content via jQuery .ajax. I dont want the content visible on the page so thats why I went with .ajax and not showing/hiding the content. I want to protect the files inside the AJAX directory from being directly accessible through the browser url. I know that PHP headers can be spoofed and dont know if it is better to use an "access" key or try doing it via htaccess.
My question is what is the more reliable method? There is no logged on/non logged user status, and the main pages need to be able to pull in content from the pages in the AJAX directories.
thx
Make a temporary time-coded session variable. Check the variable in the php output file before echoing the data.
OR, if you don't want to use sessions.. do this:
$key = base64encode(time().'abcd');
in the read file:
base64decode
explode by abcd
read the time. Allow 5 seconds buffer. If the time falls within 5 seconds of the stamped request. You are legit.
To make it more secure, you can change your encrypting / decrypting mechanism.
I would drop this idea because there is no secure way to do it.
Your server will never be able to tell apart a "real" Ajax request from a "faked" one, as every aspect of the request can be forged on client side. An attacker will just have to look into a packet filter to see what requests your page makes. It is trivial to replicate the requests.
Any solution you work out will do nothing but provide a false sense of security. If you have data you need to keep secret, you will need to employ some more efficient protection like authentication.
Why not have the content be outside the webserver directory, and then have a php script that can validate if the person should see it, and then send it to them.
So, you have getcontent.php, and you can look at a cookie, or a token that was given to the javascript page and it uses to do the request, and then it will just fetch the real content, set the mime types and stream it to the user.
This way you can change your logic as to who should have access, without changing any of the rest of your application.
There is no real difference to having http://someorg.net/myimage.gif and http://someorg.net/myscript.php?token=887799&img_id=ddtw88 to the browser, but obviously it will need to work with GET so a time limited value is necessary as the user can see reuse it.

Categories