How to protect controller against direct access? - php

I'm using codeigniter with jquery and it would be nice if you explain me how to protect the controller from direct access.
For example,
I have view with that standard jquery line:
$('#handler').load('tools/get_stats');
Tools it is my controller with function for loading statistics. If I write direct in browser full address of script http://site.com/tools/get_stats, browser open, of course, that data.
How to protect direct controller access from browser ? I want my data were loaded only in view, not on controller direct access.

The CodeIgniter Input Class has a method called is_ajax_request() for this purpose.
if ($this->input->is_ajax_request())
{
//do something
}
else
{
show_error("No direct access allowed");
//or redirect
}
If you have a dedicated Ajax Controller, you can of course include this logic in the __construct() method, otherwise it may be implemented on a method by method basis within your controllers.
See:
http://ellislab.com/codeigniter/user_guide/libraries/input.html

In general you can't do it in a meaningful way due to the need to provide access and the simplicity of HTTP. Or more basically, you can't deny access to information you need to provide (in this case stateless connection info). The best initial steps are to make sure that the controller only allows access to data that the user should have access to (regardless of how they connect), rather than trying to restrict based on the easily tampered with request information.
That being said, if you have some odd reason to really chase after this, you could use some form of single use token passed with the AJAX request. You could, for instance, generate a random key, persist it somewhere (ideally just in memory in something like a hash table since there should never be a long enough delay to warrant otherwise) and pass it out with the page that will issue the ajax request. The token is passed back with the request and removed, and then that token will no longer be valid. The controller would not be able to be accessed directly since it would need a token.
This would still be able to be worked around since the process could be halted and an issued token used, but it would deter anyone just playing around with curl (so really its not worth the effort).
Long story short, you can't do this in any way that anyone couldn't work around within 10 minutes. Focus on making sure you only expose the data you want no matter how its retrieved.

Related

PHP and AJAX Security

In the past when I have written HTML with jQuery, in order to access specific PHP pages I have simply always done this:
user.php?Action=1&User=Adrian.....
And this would return plain text JSON, which jQuery converts into a javascript object. I have a few questions regarding this method, though.
Is this safe? JSON is being passed back in plain text. Should it be used over HTTPS?
How is the best way to prevent direct access to PHP? Simply checking for an active session?
Is this whole approach ok?
Cheers,
Adrian
For number 2, it depends what you're doing.
If you are doing anything with the 'user.php' file to make any changes to the DB, you would want to use POST rather than GET (this hides the parameters from the URL bar, and is safe if your page is getting crawled/scraped).
To use POST, in your user.php file replace instances of $_GET with $_POST.
In your jQuery Ajax call, make sure parameter "type" is set to "POST"
type: "POST",
GET requests should only ever be for doing anything that gets and displays data from your data model (DB, whatever). POST requests are for making any updates, additions (stricter would be PUT), or deletions (DELETE).
If you want only that specific user to access the user.php script, then you would want check the user's session and make sure it matches with the user trying to access the particular user parameter.
1) It depends on what you're transferring. If you're transferring credit card data via HTTPS, definitely. If you're transferring less sensitive data, maybe not.
2 and 3) Make sure you check your input for SQL injection, just as you would with any $_GET variable. You should really treat it how you would normally treat $_GET data
Whenever I've allowed JSON/crud access, I've always secured the PHP page serving it (user.php) behind session-based access-control rules (role-based or group-based permissions). I then white-list which tables/fields that user/group/role is allowed to access. The level of sophistication depends on the nature of the data that is being served.

AJAX security and user managment

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.

How to protect from malicious use of jQuery post handler?

I use jquery POST calls to fetch data to display in various sections of my websites.
Usually, they POST to a single 'ajax_handler.php' page which reads the requested parameters and returns the relevant data. Typical parameters might be 'get_order_details',123
How could I stop users posting to the script to try and retrieve data which they should not be able to? I know I can verify that data belongs to the currently logged in user, for instance, but how could I stop users 'guessing' that there might be a handler for 'get_some_info'?
Since users could even run javascript straight from the URL this seems to be a major security problem to me as the client would have access to SESSION and COOKIE data (which I would otherwise use for security).
I guess I could start by naming each of my handler identifiers with a random string, but I'd prefer not to compromise the legibility of my code.
Naming your handlers with a random string is security through obscurity and while it might slow someone down, it won't stop them.
The best thing to do is to store a session or database checksum each time a page is accessed. Then also send that same checksum along with the POST content. When the form is submitted, through AJAX or otherwise, you compare the checksums. If they don't match then you know the user wasn't on the appropriate page and is trying to access the handler through some other method.
For each user, you can store within your database which data he should be able to view and which he shouldn't. Each time you get a request, e.g get_order_details, you should call a function which does your security checking to make sure both that the user is logged in, and that he has access to the 'get_order_details' method or any other method he is trying to access.
What you're trying to do is fundamentally antithetical to how the Internet works. You can't and shouldn't attempt to limit the way users make requests to your services. This is an extremely outdated and backwards way of thinking. Instead of trying to limit the ways in which users can use your service, be thankful that they're using your service in the first place.
All you can do is make sure that the user is authenticated and has access to the record they're requesting. If you're using a system which has no authentication, and you want to prevent users from "guessing" the ID of the next record, don't use sequential IDs. Use randomly generated strings as your identifier. Make them sufficiently long that it will be difficult for users to stumble upon other records.

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.

PHP can be exclusively accessed by SWF

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.

Categories