Home » Php » php – Prevent Direct Access To File Called By ajax Function

php – Prevent Direct Access To File Called By ajax Function

Posted by: admin April 23, 2020 Leave a comment

Questions:

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.

How to&Answers:

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"); 

Answer:

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

Answer:

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.

Answer:

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.

Answer:

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.

Answer:

I solved this problem preparing a check function that make three things

  1. check referer $_SERVER[‘HTTP_REFERER’];
  2. check http x request $_SERVER[‘HTTP_X_REQUESTED_WITH’];
  3. 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

Answer:

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.

Answer:

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.

Answer:

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

Answer:

I have a simplified version of Edoardo’s solution.

  1. 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).

  2. Page A passes the [token] along with the AJAX request to the script B (in OP’s queryString).

  3. Script B checks if the [token] filename exists and if so it carries on with the rest of the script, otherwise exits.

  4. 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.

Answer:

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.

Answer:

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.