-1

I need to allow php scripts to be called only via Ajax and Cron, and not called via it's address in the browser.

In F12 all the php scripts are visible, and any user may call the php script like website.com/file.php

3

1 Answer 1

0

You cannot. Scripts do not know how they are called; all they know is that the web server has them invoked.

And the web server does not know who is it that is calling, just that a request came by on the HTTP or HTTPS port (cron CLI is an exception, see below).

The best you can do is verify these two headers:

HTTP_USER_AGENT            either empty or filled
HTTP_X_REQUESTED_WITH      either 'XMLHttpRequest' or not (possibly empty)

The results will be:

UA empty, XRW empty              cron or a browser faking cron
UA "Lynx" or "wget", XRW empty   cron calling wget or lynx (or curl?)
UA empty, XRW filled             some prankster messing with you (*)
UA filled, XRW filled            AJAX call
UA filled, XRW empty             browser

(*) or some "privacy" client firewall removing the User-Agent header

But do remember that:

  • a browser can fake being cron (e.g. using ModifyHeaders plugin)
  • cron can fake being a browser (why? dunno. But it's possible)
  • anyone can fake anything (e.g. via curl)

You would be better off checking e.g.

HTTP_REMOTE_ADDR

which is not set when calling via cron CLI, and when set, should be the IP address of the servers you authorize, as seen by the Web server.

Another possibility is to use authentication, e.g. via challenge/response with a shared secret between the calling script and the called PHP program.

Other possibilities

I'm going out on a limb here, and imagining that your situation is this:

You have a script that you need to be called periodically, or when a user does something via AJAX, but not too often (maybe because it's computationally expensive). So you call the script from cron once a day, and whenever some user looks at a page, but do not want the user to see the call and be able to replicate it at will, maybe even from a different browser or a cron of their own.

A simple solution is to do it the other way round. You can set a variable in the session:

// AJAX calls are only allowed every 600 seconds PER EACH USER
// (you should verify that a login exists)
if (array_key_exists('ajax', $_SESSION)) {
    if (time() - $_SESSION['ajax'] < 600) {
        return;
    }
}
$_SESSION['ajax'] = time();

Or you can limit the calls using a file:

if (file_exists('call.txt')) {
    if ((time() - filemtime('call.txt')) < 600) {
        return;
    }
}
touch('call.txt');

Now the script cannot be called more often than once every 600 seconds (10 minutes), no matter how (except for cron CLI which will almost surely create the call.txt in a different directory).

You can perhaps also store the script output in a file, and read the file's contents if it's not older than a given value. So you can issue one thousand AJAX calls, but only the first will do any actual work - the other will wait on the locked file and then read a cached copy. This is trickier than it appears due to the need of dealing with race conditions between possibly several parallel calls.

Sign up to request clarification or add additional context in comments.

20 Comments

Thanks a lot, but I still don't know what to do)
What do you need this check for? Is it for security? Maybe what you want to achieve can be achieved in another way. For example, why you need the same script to be accessible from cron and from AJAX? It looks strange.
All .php files are visible in F12 XHR tab. So, a user may just click on php file and call it, just for fun. BTW this is also the question- how to prevent them from being visible?
cron calls the script each day. however, user may call it himself, clicking on a button
Your update doesn't answer my question: I want to prevent the users to call my php files via the browser address tab, that's all)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.