33

How can I check whether a request being received is sent from the same server??

Say, I've my domain at www.domain.com. Now I've php processing files which will process forms hosted through this domain. This processes will be executed only if the requests are sent from within the domain ie. www.domain.com and any other requests sent from other domains will be discarded.

ptamzz
  • 9,235
  • 31
  • 91
  • 147
  • do you mean checking url of the domain which is requesting the php file – KoolKabin Mar 23 '11 at 19:05
  • I'll post as comment because I'm unsure, but couldn't you just get the Requester's IP and see if it matches your server's IP? I do something similar in one of my asp.net apps – Nick Rolando Mar 23 '11 at 19:11
  • With curl I can set the REFERER to be 'www.domain.com', and call the form url (at www.domain.com) from my server (at www.mrhacker.com), but $_SERVER['HTTP_REFERER'] will give the value of www.domain.com (Almost) Anything coming from the client can be spoofed! I say almost, because the average Joe cannot spoof IP address, you can only send via proxy. – phper Oct 07 '20 at 11:11

3 Answers3

95

Basically : you cannot.
With the HTTP protocol, each request is independent from the others.


A first idea would be to check the Referer HTTP header, but note that :

  • It can be faked (it's sent by the browser)
  • It is not always present.

So : not a reliable solution.


A possible, and far better than the Referer idea, solution could be to use a nonce :

  • When displaying the form, put a hidden input field in it, containing a random value
  • At the same time, store that random value into the session that correspond to the user.
  • When the form is submitted, check that the hidden field has the same value as the one that's stored in session.

If those two values are not the same, refuse to use the submitted data.

Note : this idea is often used to help fight against CSRF -- and integrated in the "Form" component of some Frameworks (Zend Framework, for instance).

MaxSem
  • 3,457
  • 21
  • 34
Pascal MARTIN
  • 395,085
  • 80
  • 655
  • 663
  • 13
    This is a complete and accurate answer for this question. – tplaner Mar 23 '11 at 19:07
  • 2
    But this is a problem when you open the same webpage in different tabs. Because the random value is generated again in each tab, the user has to stick with his current tab. – Jordy Jun 09 '16 at 22:29
  • How can this achieved while making APIs? – VishalParkash Jan 04 '17 at 04:57
  • @Jordy i am thinking to store tokens like this session array $_SESSION['usertokens'][] = rand(); Then when user will submit form we can check it using inarray() php function with $_SESSION['usertokens']. Is it a bettter logic? – prashant Aug 30 '17 at 05:39
  • @VishalParkash you can use http_authorization header variable by sending a unique key while submitting values through apis. – prashant Aug 30 '17 at 05:40
  • @prashant, could be a solution, but if you open 2 tabs, in each one to have same form and you go to complete first form from first tab, where you have first random string, in hidden field, then an error will appear – Vas Hanea Aug 15 '19 at 12:30
  • Why not just crearte a new session at the beginning of the original file with the value containing the current page name and once on the other since just use an if statement to match the name of the previous file... If it matches, then execute rest of the code if it doesn't use a header and send the visitor wherever You like. – Samuel Ramzan Jan 12 '22 at 01:32
18

this will check if there is a referer, then it will compare it with current domain, if different then it is from outside referer

if ((isset($_SERVER['HTTP_REFERER']) && !empty($_SERVER['HTTP_REFERER']))) {
if (strtolower(parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST)) != strtolower($_SERVER['HTTP_HOST'])) {
// referer not from the same domain
}
}
Ashraf
  • 717
  • 6
  • 11
7

I know this is an old thread, but some one else can probably find it relevant.

The answer is: Yes you can. But it depends if your Apache/nginx server is set to populate the $_SERVER variable with the required information. Most the server are, so probably you can use this approach.

What you need to do is to extract the HTTP_REFERER from the $_SERVER variable and compare with your domain.

<?php
function requestedByTheSameDomain() {
    $myDomain       = $_SERVER['SCRIPT_URI'];
    $requestsSource = $_SERVER['HTTP_REFERER'];

    return parse_url($myDomain, PHP_URL_HOST) === parse_url($requestsSource, PHP_URL_HOST);
}
andergmartins
  • 2,738
  • 2
  • 13
  • 7