I need to restrict POST request from specific domain. As far I know, HTTP_REFERER checking cannot be a good solution because it can be spoofed. So what can be the good solution when two different websites from different technology and web servers will work together?
Asked
Active
Viewed 1,634 times
0
-
You mean that you want only one other server to be allowed to send POST requests to your server? You can use a shared mutating code system. – Jared Farrish Oct 21 '12 at 15:01
-
There are a number of solutions from limiting the accepted IP address to signing the payload using a shared secret. – Maerlyn Oct 21 '12 at 15:05
-
I want to allow some specific domain to send post request. Actually I cannot understand how to generate some random keys and check those into different servers. – PHPLearner Oct 21 '12 at 15:09
-
reverse DNS lookup on `$_SERVER["REMOTE_ADDR"]`, but your system will slow to a crawl. – Marc B Oct 21 '12 at 15:09
-
should be more clearly specified ... examples and etc. – Reflective Oct 21 '12 at 15:43
1 Answers
4
Heres a method you could try, by adding a hidden field within your form that is session values that are set server side. This way if the form has not originated from your server the session would not have been set and the values would not match.
Example:
<?php
session_start();
if($_SERVER['REQUEST_METHOD']=='POST'){
if(isset($_SESSION['security']) &&
isset($_SESSION['security_key']) &&
!empty($_POST[$_SESSION['security_key']]) &&
$_POST[$_SESSION['security_key']] == $_SESSION['security'])
{
/* forms post is from domain as session would
not have been started and security would not have been set */
echo 'good';
}else{
/* forms post is not from domain */
echo 'bad';
}
$_SESSION['security_key'] = sha1(microtime(true)+1);
$_SESSION['security'] = sha1(microtime(true));
}else{
$_SESSION['security_key'] = sha1(microtime(true)+1);
$_SESSION['security'] = sha1(microtime(true));
}
?>
<form method="POST" action="">
<input type="hidden" name="<?=$_SESSION['security_key'];?>" value="<?=$_SESSION['security'];?>"/>
<p><input type="text" name="Text" size="20"><input type="submit" value="Submit"></p>
</form>
Alternatively you could use encryption instead of hashing, that way you could check the values:
<?php
session_start();
define('SECURE_KEY',$_SERVER['SERVER_NAME']);
if($_SERVER['REQUEST_METHOD']=='POST'){
if(isset($_SESSION['security_key']) && isset($_SESSION['security'])){
//Decrypt
list($servername,$userip) = explode('X',decrypt(base64_decode($_SESSION['security'])));
//Check the decrypted values
if($servername == $_SERVER['SERVER_NAME'] && $userip == $_SERVER['REMOTE_ADDR']){
/* forms post is from domain as session would
not have been started and security would not have been set */
echo 'good';
}else{
echo 'bad';
}
}else{
/* forms post is not from domain */
echo 'bad';
}
$_SESSION['security_key'] = sha1(microtime(true));
$_SESSION['security'] = base64_encode(encrypt($_SERVER['SERVER_NAME'].'X'.$_SERVER['REMOTE_ADDR']));
}else{
$_SESSION['security_key'] = sha1(microtime(true));
$_SESSION['security'] = base64_encode(encrypt($_SERVER['SERVER_NAME'].'X'.$_SERVER['REMOTE_ADDR']));
}
function encrypt($string, $key = 'PrivateKey', $secret = 'SecretKey', $method = 'AES-256-CBC') {
// hash
$key = hash('sha256', $key);
// create iv - encrypt method AES-256-CBC expects 16 bytes
$iv = substr(hash('sha256', $secret), 0, 16);
// encrypt
$output = openssl_encrypt($string, $method, $key, 0, $iv);
// encode
return base64_encode($output);
}
function decrypt($string, $key = 'PrivateKey', $secret = 'SecretKey', $method = 'AES-256-CBC') {
// hash
$key = hash('sha256', $key);
// create iv - encrypt method AES-256-CBC expects 16 bytes
$iv = substr(hash('sha256', $secret), 0, 16);
// decode
$string = base64_decode($string);
// decrypt
return openssl_decrypt($string, $method, $key, 0, $iv);
}
?>
<form method="POST" action="">
<input type="hidden" name="<?=$_SESSION['security_key'];?>" value="<?=$_SESSION['security'];?>"/>
<p><input type="text" name="Text" size="20"><input type="submit" value="Submit"></p>
</form>

Lawrence Cherone
- 46,049
- 7
- 62
- 106
-
would it work if the form is submitted from remote server? I mean would session value be same? – PHPLearner Oct 21 '12 at 16:00
-
Remote server? The steps would be, user hits your site and the values are generated, form is rendered with its hidden field, user posts form and all is good. If form is from another domain values would not have been created and would fail validation. – Lawrence Cherone Oct 21 '12 at 16:04
-