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.