Prevent direct access to a PHP page - php

How do I prevent my users from accessing directly pages meant for ajax calls only?
Passing a key during ajax call seems like a solution, whereas access without the key will not be processed. But it is also easy to fabricate the key, no? Curse of View Source...
p/s: Using Apache as webserver.
EDIT: To answer why, I have jQuery ui-tabs in my index.php, and inside those tabs are forms with scripts, which won't work if they're accessed directly. Why a user would want to do that, I don't know, I just figure I'd be more user friendly by preventing direct access to forms without validation scripts.

There is no way of guaranteeing that they're accessing it through AJAX. Both direct access and AJAX access come from the client, so it can easily be faked.
Why do you want to do this anyways?
If it's because the PHP code isn't very secure, make the PHP code more secure. (For example, if your AJAX passes the user id to the PHP file, write code in the PHP file to make sure that is the correct user id.)

As others have said, Ajax request can be emulated be creating the proper headers.
If you want to have a basic check to see if the request is an Ajax request you can use:
if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
//Request identified as ajax request
}
However you should never base your security on this check. It will eliminate direct accesses to the page if that is what you need.

It sounds like you might be going about things the wrong way. An AJAX call is just like a standard page request, only by convention the response is not intended for display to the user.
It is, however, still a client request, and so you must be happy for the client to be able to see the response. Obfuscating access using a "key" in this way only serves to complicate things.
I'd actually say the "curse" of view source is a small weapon in the fight against security through obscurity.
So what's your reason for wanting to do this?

If the browser will call your page, either by normal request or ajax, then someone can call it manually. There really isn't a well defined difference between normal and ajax requests as far as the server-client communication goes.
Common case is to pass a header to the server that says "this request was done by ajax". If you're using Prototype, it automatically sets the http header "X-Requested-With" to "XMLHttpRequest" and also some other headers including the prototype version. (See more at http://www.prototypejs.org/api/ajax/options at "requestHeaders" )
Add: In case you're using another AJAX library you can probably add your own header. This is useful for knowing what type of request it was on the server side, and for avoiding simple cases when an ajax page would be requested in the browser. It does not protect your request from everyone because you can't.

COOKIES are not secure... try the $_SESSION. That's pretty much one of the few things that you can actually rely on cross-page that can't be spoofed. Because, of course, it essentially never leaves your control.

thanks, albeit I use
define('IS_AJAX', isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');
if(IS_AJAX) {
//Request identified as ajax request
}
cheers!

Not sure about this, but possibly check for a referrer header? i think if someone manually typed in your url, it wouldn't have a referrer header, while AJAX calls do (at least in the quickly test I just did on my system).
It's a bad way of checking though. Referrer can be blank for a lot of reasons. Are you trying to stop people from using your web service as a public service or something?
After reading your edit comments, if the forms will be loaded via ajax calls, than you could check window.location to see if the url is your ajax form's url. if it is, go to the right page via document.location

This definitely isn't useful for securing something.. but I think this could be of use if you wanted to have say a php page that generated a whole page if the page was not requested by ajax but only generate the part that you needed returned when ajax was used.. This would allow you to make your site non ajax friendly so if say they click on a link and it's supposed to load a box of comments but they don't have ajax it still sends them to the page that is then generated as a whole page displaying the comments.

Pass your direct requests through index.php and your ajax requests through ajax.php and then dont let the user browse to any other source file directly - make sure that index.php and ajax.php have the appropriate logic to include the code they need.

In the javascript file that calls the script:
var url = "http://website.com/ajax.php?say=hello+world";
xmlHttp.open("GET", url, true);
xmlHttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
then in the php file ajax.php:
if($_SERVER['HTTP_X_REQUESTED_WITH'] != "XMLHttpRequest") {
header("Location: http://website.com");
die();
}
Geeks can still call the ajax.php script by forging the header but the rest of my script requires sessions so execution ends when no valid session is detected. I needed this to work in order to redirect people with expired hybridauth sessions to the main site in order to login again because they ended up being redirected to the ajax script.

Related

Block direct access to PHP file except from AJAX request?

I wish to have a webpage that uses AJAX to access a PHP file in ./ajax/file.ajax.php
Trouble is, I don't want people to be able to type the address in their browser to access that PHP file directly.
Is there a way I can make it so that only AJAX requests can access the file?
Is there something I can check for in the PHP file to achieve this?
If you're using jQuery to make the XHR, it will set a custom header X-Requested-With. You can check for that and determine how to serve your response.
$isXhr = isset($_SERVER["HTTP_X_REQUESTED_WITH"])
AND strotlower($_SERVER["HTTP_X_REQUESTED_WITH"]) == "xmlhttprequest";
However, this is trivial to spoof. In the past, I've used this to decide whether to render a whole page (if not set) or a page fragment (if set, to be injected into current page).
If you're not using jQuery or you are not interested/you can't use custom headers (to go with what alex has offered), you may just simple POST some data with your Ajax request, and in that specific file check if that data has sent or not. If you send by GET it would be visible on the address bar, that's why I suggest POST.
<?php
if (empty($_POST['valid_ajax']))
header('Location: /');
?>
It's not solid as you can fool that with providing handmade data, however that's better than nothing if your problem is not that critical.

PHP page as a function/process module

First of all, this is my first post in Stack Overflow and I'm trying to learn PHP/MySql for a personal project that I'm working on. I think I will be spending alot of time on here to ask heaps of questions, so forgive me if I ask too many questions that you may find trivial.
On with the question.
I'm using a combination of ajax and PHP to process server side scripts. What I want to do is have a PHP module that will accept input, process something, and provide output. Much like a function.
What I'm trying to wrap my head around is how can I make PHP like a black box process module, like a function, rather than a page.
As an example, I have a login.html page which uses AJAX to send request to a login.php page. The login.php accepts the input, process the input, and output a json object which tells the calling page if it is successful, and if not will list the errors that it encountered along the way.
Here lies the issue. I don't want user to be able to go to login.php directly. In fact, I don't even want login.php to be visible to the public. The login.php is only a process, so if you go to it, it will be blank. This doesn't seem like a good practice to let users see a blank page.
I thought about putting the login.php outside the public folder, but this would mean that ajax won't be able to make a request to it either.
To get around this I have the login.html sit within the login.php. It will make a request to itself, then based on the type of request, the php will perform different things. This will resolve the "blank page" issue. But I can't help wonder if there is a way to make a standalone PHP module without having to make it work like a page also.
Any thoughts into this will be much appreciated. Thanks.
If an AJAX can request the page, then any user will be able to navigate to the page with their browser. You really shouldn't be concerned with this, because unless they snoop around they won't happen upon the PHP page. If you want a little bit of verification that the request was made by AJAX you can look for the X-Requested-With header, but this doesn't always work because every browser doesn't send this:
if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
// Ajax Request
} else {
// Not AJAX, redirect to login page
header('Location: login.html');
exit();
}
To make this work reliably on every browser, you'll need to set this header on the clientside:
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
However this is still not fullproof because anyone can send a header with a program like Tamperdata, but this should be good enough to prevent the lazy snoop. Again though, allowing users to see this page (if they snoop) won't be a huge problem. It's not going to create a security vulnerability and on the off chance that a user stumbles upon the login.php page, they'll be redirected back to login.html.
Anything you send an AJAX request to can also be navigated to directly, by the nature of AJAX. All you can do is not provide the user with any indication that that page exists.
You do have the option of having one PHP file call another, via include. That way, you can have the request to login.php change behavior based on the request, but have the login handling actually processed by a file that isn't publicly accessible:
if($_POST) {include '../login-handler.php'; die();}

How to deny ajax PHP files from browser

There is AJAX script on my WS.
Is there a method to deny straight access to ajax php backend?
And to access to it only if it is run from my ajax code
You can try heuristics (such as examining X-Requested-With HTTP header) but NOT as any security measure. Any such difference in how the request looks can easily be duplicated by anyone who really wants to.
The answer is no.
The way your ajax calls access the php scripts is just as direct as any other method.
That said, you can limit the access to your scripts in different ways, such as requiring a valid session which is created only after a login. However, once a user has logged in, accessing the backend via an ajax script or "directly" are both fair game. In other words, you cannot count on being able distinguish an ajax call from some other call at the server side.
The security of your backend needs to depend on somewhere else.
On server-side you can add this to the top of your backend files:
if(empty($_SERVER['HTTP_X_REQUESTED_WITH']) || strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest') {
die("You need to use an AJAX request");
}
Edit: As stated by others, this is not reliable as a security measure.

PHP Render/Redirect AJAX Call

I am working on a PHP application and missing some of the functionality that Rails has. I currently have an AJAX form that when submitted accesses my_page_save_ajax.php. After I process the form and save it, I would like to redirect the AJAX call to either my_page_show_ajax.php if successful or back to my_page_edit_ajax.php if an error occurred.
I have thought about using an include my_page_..._ajax.php, but I have always had problems with the file paths and PHP not knowing what to render. Not to mention, both of those files include utilities.php and I'm afraid there might be conflicts. I guess I could use include_once but it seems like there might be a more elegant solution.
How can I process the form and return the output of another PHP page?
Thanks very much!
If you redirect the AJAX response, it won't actually redirect the user's browser anywhere. It will simply affect what data comes back through the AJAX call. This may be a good instance to simply not use AJAX, since it sounds like the user may go on only one of two paths.
If you still want to redirect the user, you could send back a javascript snippet which redirects the user via setting window.location

How to make sure a human doesn't view the results from a PHP script URL?

How to make sure a human doesn't view the results from a PHP script URL?
Recently when viewing the source of a site that was making an AJAX call, I tried to follow the link in the browser
www.site.com/script.php?query=value
Instead of getting the result I expected to see, I saw a message stating only scripts should view that page.
How do you restrict a script to only allowing a script to access it?
UPDATE:
here is the page DEMO page
Short answer: you can't.
Long answer: You can make it harder to do it by requiring special header values in the HTTP request (setting Accept to application/json is a common one). On the server side just check to make sure that header is set to the value you expect. This will make it so that regular users will get the message you mention and your scripts will work just fine. Of course advanced users will be able to easily work around that sort of limitation so don't rely on it for security.
with php you can check for and only display results if the page is called via ajax
function isAjax() {
return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'));
}
if(isAjax()) {
// display content
} else {
// not ajax, dont show
echo 'Invalid Request';
}
You can't. A human being can always spoof the request. You can send your request with a post variable, to make sure a human doesn't end up on the page by accident.
One possible solution is to check the HTTP Request for it's origin.
Another solution is to send a "password" with every request. Take a look into this tutorial how to do this.
But it's never 100% secure, it only makes it harder for possible intruders.
As Tim stated, this script is almost certainly looking for this request header, which is being sent with each request to rpc.php (found via the net panel in firebug, naturally):
X-Requested-With : XMLHttpRequest
As to cross-browser compatibility, the setRequestHeader method appears to be available with both the activex and xmlhttprequest connections so this should work in all major modern browsers.
If you are calling the script by AJAX, then it MUST be accessible for you because an AJAX call is similar to your browser actually asking for the page, thus it is not only script accessible but accessible to anyone.
If it was actually called by PHP or by some other means, you could "maybe" use Apache rules or PHP scripting to diminish the accessibility.
You could set a secret value into the php session with the 'view' script and check for it with the ajax scripts.
Request 'index.php' with the
browser.
PHP builds the page, saves a key into
the session, sends the content back
to the browser.
The browser gets the page content and
makes some ajax request to your site.
Those ajax scripts also have access
to the same session your main page
did, which allows you to check for a
key.
This insures only authenticated browsers are allow to make the ajax requests.
Don't count on the ajax request being able to write to the session though. With many requests being satisfied at the same time, the last one in will be the last one written back to your session storage.
http://us.php.net/manual/en/book.session.php
A lot of open source applications use a variation of this on top of every php file:
if (!defined('SOMETHING')) {
die('only scripts have direct access');
}
Then in index.php they define SOMETHING:
define("SOMETHING", "access granted.");
edit: I'm not saying this is a good approach btw
edit2: Seems I missed the part about it being an ajax request. I agree in this case this isn't a solution.

Categories