4

Is it possible to check that the $_GET or $_POST values are submitted from specific page?

For example, there is an ajax in page1 submitted value to page2.php?q=abc, and the page2 only accept the q when it is submitted from page1.

If I directly browse to the page page2.php?q=abc, the php will not run unless I submitted the value from page1.

Is it possible to do that?

Edit 1:

Because I can access the page2 and get the result. Don't mention about the session, because I can validate the session to match my needs and the values submitted to php is valid or not.

What I want is to check if the request is sent from specific page or not. If true, then accept the values and process it, else, redirect to homepage or something else.

Edit 2: My question is, not only values submitted through Ajax, but also direct access, such as href="page2.php?q=abc". I guess token will be the best way to do that, and the query part will validate again.

Chin
  • 593
  • 4
  • 15
  • 36
  • 1
    Explain the original intentions. Why do you need that? – zerkms May 08 '14 at 04:55
  • if you are submitting values then it means you are submitting form and what method a form will have it depends on you – user3470953 May 08 '14 at 04:56
  • 1
    My favorite mechanism to do this is with tokens, produce a token on the form and store it in a database, and check its validity when posted, delete the token once used. – Scuzzy May 08 '14 at 04:57
  • Anything that comes from the dark dangerous internet is possibly compromised. Anything you might try to enforce this could possibly be spoofed. That said, setting a $_SESSION variable might give you a method –  May 08 '14 at 04:57
  • maybe you were looking for this? check this [post](http://stackoverflow.com/questions/4301150/how-do-i-check-if-the-request-is-made-via-ajax-with-php) – user1978142 May 08 '14 at 04:58
  • 3
    So basically, you are looking to validate that a request is not a forgery from an unexpected source. My suggestion would be to use a validation token to compare against a similar token in session. This is something you Should be doing anyway for secure form handling. – Mike Brant May 08 '14 at 05:00
  • As a sidenote you could add one more restriction, that is checking whether the request is only coming from AJAX. Or you could send in a hashed string which you can decrypt at page2.php to make sure the page1.php has sent the request. – AyB May 08 '14 at 05:04
  • @MikeBrant, yes, token is one of the way. – Chin May 08 '14 at 05:13
  • @ICanHasCheezburger, is there such function to check the request is only coming from Ajax? Can you show me an example? – Chin May 08 '14 at 05:14
  • $_SERVER['HTTP_X_REQUESTED_WITH'] can be used to detect Ajax request. IN case of ajax request it returns the XmlHttpRequest value. However according to online resources, It may not be supported by all servers. – kuldeep.kamboj May 08 '14 at 05:33
  • possible duplicate of [How to check if the request is an AJAX request with PHP](http://stackoverflow.com/questions/18260537/how-to-check-if-the-request-is-an-ajax-request-with-php) – esqew May 08 '14 at 05:33
  • @esqew, may be it's a duplicate to you. But my question is not only limited to Ajax, such as a `href` with values. Hope you can understand my question. – Chin May 08 '14 at 08:05

3 Answers3

7

There are two security checks you could perform while dealing with AJAX:

1) Check if the request it sent through AJAX:

if ( !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest' )
{
       //AJAX Request Detected
}

2) Hashed tokens:

On the page that's holding the AJAX Request, create a token:

session_start();
$hashed='';
$_SESSION['token'] = microtime(); 
if (defined("CRYPT_BLOWFISH") && CRYPT_BLOWFISH) {
    $salt = '$2y$11$' . substr(md5(uniqid(mt_rand(), true)), 0, 22);
    $hashed = crypt($_SESSION['token'], $salt);
}

This is using the blowfish algorithm with the crypt() to create hashed string.

Your AJAX function would be like:

$.ajax({
    type: "POST",
    url: 'page2.php',
    data: {
        action: '<?php echo $hashed;?>', //pasted the hashed string created in PHP
        q: 'test'
    },
    success: function (data) {}
});

Upto you whether you want to use $_GET or $_POST method.

And then on the second page which is receiving the AJAX request, you do:

session_start();
if(crypt($_SESSION['token'], $_POST['action']) == $_POST['action']){
   //Hashed string matches. Request has come from page1.
   echo $_POST['q'];
}
AyB
  • 11,609
  • 4
  • 32
  • 47
1

in your form you can just add a hidden field and add a page id. On the page that should send post or get request you can do something like

<form action='phpscript.php'>
    <input type='hidden' name='page' value='valid_page'>
    <input name='your_other_info'>
</form>

In the phpscript.php you can do something like

<?php
    //If you have a request, it can be either post or get method
    if(isset($_SERVER['REQUEST_METHOD']) && (isset($_POST['page']) || isset($_GET['page']))){

    }else{
        //Post or get is not from the valid page
    }
?>
ksealey
  • 1,698
  • 1
  • 17
  • 16
0

You cannot restrict the "origin" of the request, because there's no such thing per se. Your "page" isn't sending a request, it's the browser that does it. And the browser may have any number of reasons why it's sending you a request; be that because one of your pages has instructed it to do so or because a user is fiddling around with the Javascript console manually.

All you get on your end is an HTTP request. Go ahead, inspect it. In the browser, look at the network tab and inspect the raw request being sent. It's just a bunch of HTTP headers, nothing more. Anyone can send an HTTP request with arbitrary HTTP headers any time from anywhere and make it look like anything they want. Even the Referer HTTP header is not going to "protect" you.

If you need any sort of protection, you can use session tokens or user authentication to restrict the set of potential entities that can send queries somewhat. But what you have is still by definition a public URL endpoint which answers to arbitrary HTTP queries. You cannot restrict their "origin page". The best you can do is obfuscate it by requiring certain headers to be set (like Referer or X-Requested-With).

deceze
  • 510,633
  • 85
  • 743
  • 889
  • You make it sound completely hopeless, but it's not. There are many cases where the "referrer" header *does*provide essential security. For an AJAX request, the "referer" HTTP header contains the URL which originated the request. This is extremely useful, because it serves as evidence for where any AJAX request came from. This is often good enough for cross-site scripting protection: JavaScript which is injected on page A cannot spoof the "referrer" header to make it look like it is from page B. – Jay Sullivan May 06 '19 at 13:35