I am working on a web application that will be hosted on a server that is "on the internet", not a LAN.
The app uses quite a bit of AJAX calls and has about 12 ajax handler files for the functions.
My question is instead of asking anybody here to write a tutorial on AJAX security, does anybody know of any good resources (website, book, whatever) that can help me with securing these files.
Right now, as long as you know the variable name its looking for you can freely get data from the database.
I was thinking maybe session validation, or something along those lines for the logged in user.
Anyways if you have any good resources I'll do the homework myself.
Thanks
AJAX calls are generally used to access web services, which is what it seems you are using them for here. If that is the case then what you need to be concerned about is the security layer that you have provided in the server-side scripting language you are using (looks like you are using PHP as per your question's tags).
The same way that you do authentication and protection for other pages on your site that aren't accessed via AJAX calls you can implement for your web services. For instance, if you require authentication for your application then you can store the user's ID in $_SESSION. From there you can check to make sure the user is logged in via $_SESSION whenever one of your web services is requested.
I've often seen AJAX calls that check the X-REQUESTED-WITH HTTP header to "verify" that the request originated from AJAX. Depending on how you're sending your AJAX calls (with XmlHttpRequest or a JS library), you can either use the standard value for this header, or set it to a custom value. That way, you can do something similar to this in PHP to check if the page was requested with AJAX:
http://davidwalsh.name/detect-ajax
if( !empty($_SERVER['HTTP_X_REQUESTED_WITH']) &&
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
It is important to note that since it's an HTTP header, it can be spoofed, so it is by no means full-proof.
Here is a good resource. Securing Ajax Applications: Ensuring the Safety of the Dynamic Web
However a very simple method is to use a MD5 hash with a private key. e.g. USER_NAME+PRIVATE_KEY. If you know the users name on the website/login you can provide that key in an MD5 hash set to a javascript variable. Then simply pass the users name in your AJAX request and the REST service can just take the same private key plus the users name and compare the two hashes. You're simply sending across a hash, and the user name then. It's simple and effective. Virtually impossible to reverse too unless you have a simple private key.
So in your javascript you might have this set:
var user='username';
var hash='925c35bae29a5d18124ead6fd0771756'
Then, when you send your request you send something like this:
myService.php?user=username&hash=925c35bae29a5d18124ead6fd0771756&morerequests=goodthings
When you check it, in the service you would do something like this
<?php
if(md5($_REQUEST['user']."_privatekey")==$_REQUEST['hash']){
echo 'passed validation';
}else{
echo 'sorry charlie';
}?>
Obviously you would need to use PHP or something else to generate the hash with the private key, but I think you get the general idea. _privatekey should be something complex in the event you do have a troll that tries to hack it.
Related
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.
Is it possible to have a secure piece of Javascript code in a web application? By secure I mean that we can do things like query the server for permissions, and do operations that cannot be altered by the client?
Example:
var flag = 0;
$.ajax({
async: false,
url: "/check_permission_script.php",
success: function(data){
flag = parseInt(data);
}
});
if (flag != 1){
display_normal_content();
}else{
display_secure_content();
}
Here I want to make a query to the server to check if the user has permission to see the secure content. If they have the permissions, then we use display_secure_content() to show them the secure content, if not, we use display_normal_content() to display normal content. The problem is, that via a debugging terminal, it is easy to set the flag variable == 1 on the client computer, or just call the display_secure_content() function directly.
My motivation for doing things this way is to have nice web app that uses ajax to get new content, without having to reload the page. I like this instead of having to reload the page.
So the question is, can we have JS scripts that are secure against client manipulation? Or is this simply impossible by the nature of the web infrastructure?
Thanks!!
By the very nature of JavaScript, this is not possible.
Anything you want to not be seen by the client cannot be sent to the client at all. All authentication/authorization should happen server-side.
You can still use AJAX for loading data in your interface, but make sure the checks are in place server-side to keep sensitive data from leaking out.
Short answer, no - not with JavaScript alone. JavaScript executes on the client-side, so anything you put in it is accessible and by extension modifiable by the client.
Several tools exist to help with "security through obscurity" such as obfuscating the code, but this will not help you for your end goal.
What could help, given your current setup, is through Ajax you contact a server-side PHP page that handles all security/validation and returns what content to display. Doing this, the client-facing JavaScript only has the ability to "request", not to validate or choose what to display.
You could query the session id against your internal database and return a secure public/private key encrypted token which contains a key for decrypting a blob of data. Then use this as a parameter of the javascript function, which uses this returned key to decrypt the blob.
This solution does not require reloading the page, and whilst it works in theory, you would have to return the page with the secure content encrypted with a different key each time. I wouldn't recommend actually trying this.
The server should know what the user can and can not see. If the flag is changed on the client, the server should not trust it, it should do a validation when it gets the request. Security 101 stuff
JavaScript is a client side scripting language. It's meant to be this way.
If you need a secure script, use PHP.
I'm trying to create a login process. But it seems impossible to create one process that will work with a desktop app and a standard website.
Instead I have the login function in Usermanagement.php (which is a class, icyntk) but then in another php file (api/login.php) I have:
<?php
require_once '../usermanagement.php';
$m = new usermanage();
echo $m->login($_POST['username'], $_POST['password']);
?>
And then I will still need to make another login.php just to be used with the login form on the website. As I can't see anyway to get the result (the echo) of the api/login.php script from the index.php file (where the login form is, it only has HTML in though).
Is there anyway I can simplify this so I only need one login.php?
As I understand you, what you want is:
a website/webapp having a login
a desktop app (not in PHP!) logging in using the same login method
One way is to export the login method using the same API in both your website and the remote application, so you would be using JavaScript on client-side to access the API from there (AJAX/JSON). You will want to use some framework for that like jQuery for client-side simplification of AJAX (among many other uses) and maybe the JSON module in PHP (to use json_encode; beware that the module may not be available on some webspaces so if that's out of control don't use it). Of course you do not need to use XML or JSON in your API responses but it's easier to open the API to other (including desktop) applications without the need to manually implement a lot of parsing functions to process the response in your interface classes.
Keep in mind that your website/webapp will not work without JavaScript if you do it this way! On non-public parts of a website that's okay, as is for a webapp used by a known user group, but you should not depend on client-side scripting for public parts of a website.
Another solution to simplify that is by using a PHP framework, so you can write the server-side frontend easier. This will basically enable you to give a button a serverside function which is simply calling your login method and acting accordingly by setting a redirect or replace some panel or whatever you like to continue with after the login.
Of course you can do all that by yourself but this will usually result in either a lot of messy code or an implementation of your own framework. If you want to do it on your own, start by posting the form to the same PHP file instead of an extra login.php and add a hidden field like:
<input type="hidden" name="action" value="login"></input>
In PHP, check $_POST['action']=='login' and call the login method.
Edit: While your website will work with a PHP session or a cookie, you may want to track login status with an own session token which you can pass to your desktop app so it can be used for consecutive calls to the API, so you don't need to handle cookies. These tokens should also be bound to the IP and maybe other "individual" information of the client; that information should ideally be hashed into the token or the token encrypted (client-side won't have to "decrypt" that, just return it for authentication). Tokens should also time out after inactivity.
Also, having read your older question, I fear you could be trying to do something bad like sending a hash over the network and simply check that hash with your user table because JS side encoding was discussed there. If you like to implement some encryption algorithm on client-side, either make sure it's secure (difficult to do that unless you are into cryptography) or resort to SSL.
As the data from your Desktop App is unlikely to be sent via the $_POST array, I would say no. Websites and Desktop Apps are two completely different types of applications, and it would be unrealistic to think you could share much of the front-end code between the two.
I would try to abstract as much of the functionality as you can into core classes, and then create two separate front-end implementations that utilize the core, each in their own way.
I'm going to get really "limby" and go out on a freaking huge limb and say that this is what you're trying to do:
<?php
if(isset($_POST['username'])) {
require_once '../usermanagement.php';
$m = new usermanage();
echo $m->login($_POST['username'], $_POST['password']);
}else{
?>Put your login form HTML here<?php
}
This way you only need one login.php file.
I'm not sure how to describe this, but basically I have a PHP class file:
class HelloHello {
public function getSomeData($input_parameter){
// code to retrieve data from the database
}
public function deleteSomeData($input_parameter){
// code to delete data from the database
}
}
This class is on the server and is part of the backend that connects with a database, and it's meant to be accessed by the frontend SWF only (not to be directly accessed). I've setup Flex to read this class and access it. But how do I make sure that someone doesn't develop a script that can call this php file directly and access its methods? For example using a script to add data in a fast automated way, or use the delete method directly, ouch.
Is this a legitimate concern, or this can't be done?
If a user can view it through your flash application, the user can view it with his application. You could go through the [ugly] mess of trying to "secure" your script by introducing cookies and authentication and the like, but thats messy, and of course, it can be gone around.
Instead of trying to stop others from accessing your php file, focus on making it more secure.
If you know the url where swf runs, can't you just in PHP limit the requests to that url? Disregard all other requests.
You can secure your file by adding security and authentication. If you cannot do that (it is a public application) you should implement some techniques which can prevent specific situations: do not allow calling your script too many times per second from the same IP, add CAPTHCA in order to check that the entered data were from a human and not a machine and maybe another ones.
You could also implement a challenge-reponse security system that makes sure the client you use is actually the intended recpipient of the data. That way, you would embed a secret key into the SWF. The PHP app sends a one-time string, the client does something to it according to its secret and then sends the answer back -- which your server can validate and then continue to run.
For some basic mathematical foundations to this, there's quite some documentation online.
This question already has answers here:
How to prevent direct access to my JSON service?
(7 answers)
Closed 3 years ago.
I'm calling the php code from ajax like this:
ajaxRequest.open("GET", "func.php" + queryString, true);
Since it's a get request anyone can see it by simply examining the headers. The data being passed is not sensitive, but it could potentially be abused since it is also trivial to get the parameter names.
How do I prevent direct access to http://mysite/func.php yet allow my ajax page access to it?
Also I have tried the solution posted here but its doesn't work for me - always get the 'Direct access not premitted' message.
Most Ajax requests/frameworks should set this particular header that you can use to filter Ajax v Non-ajax requests. I use this to help determine response type (json/html) in plenty of projects:
if( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && ( $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' ) )
{
// allow access....
} else {
// ignore....
}
edit:
You can add this yourself in your own Ajax requests with the following in your javascript code:
var xhrobj = new XMLHttpRequest();
xhrobj.setRequestHeader("X-Requested-With", "XMLHttpRequest");
what I use is: PHP sessions + a hash that is sent each time I do a request. This hash is generated using some algorithm in the server side
Mmm... you could generate a one-time password on session start, which you could store in the _SESSION, and add a parameter to your ajax call which would re-transmit this (something like a captcha). It would be valid for that session only.
This would shield you from automated attacks, but a human who has access to your site could still do this manually, but it could be the base to devise something more complicated.
Anyone in this thread who suggested looking at headers is wrong in some way or other. Anything in the request (HTTP_REFERER, HTTP_X_REQUESTED_WITH) can be spoofed by an attacker who isn't entirely incompetent, including shared secrets [1].
You cannot prevent people from making an HTTP request to your site. What you want to do is make sure that users must authenticate before they make a request to some sensitive part of your site, by way of a session cookie. If a user makes unauthenticated requests, stop right there and give them a HTTP 403.
Your example makes a GET request, so I guess you are concerned with the resource requirements of the request [2]. You can do some simple sanity checks on HTTP_REFERER or HTTP_X_REQUESTED_WITH headers in your .htaccess rules to stop new processes from being spawned for obviously fake requests (or dumb search-crawlers that won't listen to robots.txt), but if the attacker fakes those, you'll want to make sure your PHP process quits as early as possible for non-authenticated requests.
[1] It's one of the fundamental problems with client/server applications. Here's why it doesn't work: Say you had a way for your client app to authenticate itself to the server - whether it's a secret password or some other method. The information that the app needs is necessarily accessible to the app (the password is hidden in there somewhere, or whatever). But because it runs on the user's computer, that means they also have access to this information: All they need is to look at the source, or the binary, or the network traffic between your app and the server, and eventually they will figure out the mechanism by which your app authenticates, and replicate it. Maybe they'll even copy it. Maybe they'll write a clever hack to make your app do the heavy lifting (You can always just send fake user input to the app). But no matter how, they've got all the information required, and there is no way to stop them from having it that wouldn't also stop your app from having it.
[2] GET requests in a well-designed application have no side-effects, so nobody making them will be able to make a change on the server. Your POST requests should always be authenticated with session plus CSRF token, to let only authenticated users call them. If someone attacks this, it means they have an account with you, and you want to close that account.
Put the following code at the very top of your php file that is called by ajax. It will execute ajax requests, but will "die" if is called directly from browser.
define('AJAX_REQUEST', isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');
if(!AJAX_REQUEST) {die();}
Personally, I choose not to output anything after "die()", as an extra security measure. Meaning that I prefer to show just a blank page to the "intruder", rather than giving out hints such as "if" or "why" this page is protected.
I would question why you are so convinced that no-one should be able to visit that file directly. Your first action really should be to assume that people may visit the page directly and act around this eventuality. If you are still convinced you want to close access to this file then you should know that you cannot trust $_SERVER variables for this as the origins of $_SERVER can be difficult to determine and the values of the headers can be spoofed. In some testing I did I found those headers ($_SERVER['HTTP_X_REQUESTED_WITH'] & $_SERVER['HTTP_X_REQUESTED_WITH']) to be unreliable as well.
I solved this problem preparing a check function that make three things
check referer $_SERVER['HTTP_REFERER'];
check http x request $_SERVER['HTTP_X_REQUESTED_WITH'];
check the origin via a bridge file
if all three pass, you success in seeing php file called by ajax, if just one fails you don't get it
The points 1 and 2 were already explained, the bridge file solution works so:
Bridge File
immagine the following scenario:
A.php page call via ajax B.php and you want prevent direct access to B.php
1) when A.php page is loaded it generates a complicated random code
2) the code is copied in a file C.txt not directly accessible from
web (httpd secured)
3) at the same time this code is in clear sculpted in the rendered
html of the A.php page (for example as an attribute of body,
es:
data-bridge="ehfwiehfe5435ubf37bf3834i"
4) this sculpted code is retrived from javascript and sent via ajax
post request to B.php
5) B.php page get the code and check if it exists in the C.txt file
6) if code match the code is popped out from C.txt and the page B.php
is accessible
7) if code is not sent (in case you try to access directly the B
page) or not matches at all (in case you supply an old code trapped
or trick with a custom code), B.php page die.
In this way you can access the B page only via an ajax call generated from the father page A.
The key for pageB.php is given only and ever from pageA.php
There is no point in doing this. It doesn't add any actual security.
All the headers that indicate that a request is being made via Ajax (like HTTP_X_REQUESTED_WITH) can be forged on client side.
If your Ajax is serving sensitive data, or allowing access to sensitive operations, you need to add proper security, like a login system.
I tried this
1) in main php file (from which send ajax request) create session with some random value, like $_SESSION['random_value'] = 'code_that_creates_something_random'; Must be sure, that session is created above $.post.
2) then
$.post( "process_request.php",
{
input_data:$(':input').serializeArray(),
random_value_to_check:'<?php echo htmlspecialchars( $_SESSION['random value'], ENT_QUOTES, "UTF-8"); ?>'
}, function(result_of_processing) {
//do something with result (if necessary)
});
3) and in process_request.php
if( isset($_POST['random_value_to_check']) and
trim($_POST['random_value_to_check']) == trim($_SESSION['random value']) ){
//do what necessary
}
Before i defined session, then hidden input field with session value, then value of the hidden input field send with ajax. But then decided that the hidden input field not necessary, because can send without it
I have a simplified version of Edoardo's solution.
Web page A creates a random string, a [token], and saves a file with that name on disk in a protected folder (eg. with .htaccess with Deny from all on Apache).
Page A passes the [token] along with the AJAX request to the script B (in OP's queryString).
Script B checks if the [token] filename exists and if so it carries on with the rest of the script, otherwise exits.
You will also need to set-up some cleaning script eg. with Cron so the old tokens don't cumulate on disk.
It is also good to delete the [token] file right away with the script B to limit multiple requests.
I don't think that HTTP headers check is necessary since it can be easily spoofed.
Based on your description, I assume you're trying to prevent outright rampant abuse, but don't need a rock-solid solution.
From that, I would suggest using cookies:
Just setcookie() on the page that is using the AJAX, and check $_COOKIE for the correct values on func.php. This will give you some reasonable assurance that anyone calling func.php has visited your site recently.
If you want to get fancier, you could set and verify unique session ids (you might do this already) for assurance that the cookie isn't being forged or abused.
I tried many suggestions, no one solved the problem. Finally I protected the php target file's parameters and it was the only way to limit direct access to the php file.
** Puting php file and set limitation by.htaccess caused fail Ajax connection in the main Html page.