Stop Post Data From Different Domain PHP

"accepted answer" has security holes. Instead, you should use more secure methods. A simple example:

Step 1: Disable framing of the page (.php), where the form is generated, in the top add:

header('X-Frame-Options: Deny');

Step 2: (important part ! ): In order to avoid XSS and 3rd party exploits, you should create a expirable validation. For example:

  • ASP.NET builtin forms use dynamic input csrf (example value: gtlkjh29f9ewduh024cfvefb )
  • WordPress builtin forms use dynamic input nonce (example value: 340297658942346 )

So, if you are on a custom platform, which doesn't have built-in temporary token validation methods, then implement your approach. A simple concept:

<?php  
$secret_key      = 'fjd3vkuw#KURefg';  //change this
$encrypted_value = Cryptor::encrypt( time(), $_SERVER['REMOTE_ADDR'] . $secret_key);
?>
<form>
...
...
<input value="<?php echo $encrypted_value;?>" name="temp_random" type="hidden"  />
</form>

(Cryptor code is here )

on submission, check:

if(!empty($_POST)){

   // If REFERRER is empty, or it's NOT YOUR HOST, then STOP it
   if( !isset($_SERVER['HTTP_REFERRER']) || parse_url($_SERVER['HTTP_REFERRER'])['host'] != $_SERVER['HTTP_HOST'] ){
       exit("Not allowed - Unknown host request! ");
   }

   // Now, check if valid
   if (   Cryptor::decrypt(  $_POST['temp_random'], $_SERVER['REMOTE_ADDR'] . $secret_key) < time() - 60* 15 ) {
       exit("Not allowed - invalid attempt! ");
   }

   ...........................................
   ... Now, you can execute your code here ...
   ...........................................

}

In the form:

<?
$password = "mypass"; //change to something only you know
$hash = md5($password . $_SERVER['REMOTE_ADDR']);
echo "<input type=\"hidden\" name=\"iphash\" value=\"$hash\"/>";
?>

When you are checking:

$password = "mypass"; //same as above
if ($_POST['iphash'] == md5($password . $_SERVER['REMOTE_ADDR'])) {
    //fine
}
else {
    //error
}

You're trying to prevent CSRF - Cross-Site Request Forgery. Jeff himself has a blog article about this.

True XSRF Prevention requires three parts:

  • Hidden Input Fields, to prevent someone from just snatching the form and embedding it
  • Timechecking within an epsilon of the form being generated, otherwise someone can generate a valid form once and use the token (depending on impementation/how it's stored)
  • Cookies: this is to prevent a malicious server from pretending it's a client, and performing a man-in-the-middle attack

$_SERVER['HTTP_Referrer'] would be nice but it isn't reliable. You could use a hidden form field that MD5's something and then you check it on the other side.

Tags:

Php

Forms

Post