停止从不同域PHP发布数据

时间:2009-07-01 16:38:12

标签: php forms post

我是PHP的初学者。

我要做的是停止来自其他网页的发布数据。

我遇到的问题是让某人复制我的表格并将其粘贴到他们的网站上。我希望能够阻止Post Data在我的电子邮件表单上运行脚本。

我该怎么做?如果我不够清楚,请告诉我。

我的PHP联系表单在一个带有条件语句的页面上运行。即如果数据签出,请提交。

6 个答案:

答案 0 :(得分:9)

您正试图阻止CSRF - Cross-Site Request ForgeryJeff himself有关于此的博客文章。

真正的XSRF预防需要三个部分:

  • 隐藏输入字段,以防止有人抓住表单并嵌入它
  • 在正在生成的表单的epsilon中进行时间检查,否则有人可以生成一次有效表单并使用该令牌(取决于强制执行/如何存储)
  • Cookies:这是为了防止恶意服务器伪装成客户端,并执行中间人攻击

答案 1 :(得分:7)

$ _ SERVER ['HTTP_Referrer']会很好但是不可靠。您可以使用MD5的隐藏表单字段,然后在另一侧检查它。

答案 2 :(得分:3)

“接受的答案”有安全漏洞。相反,您应该使用更安全的方法。一个简单的例子:

第1步:首先,禁用页面框架(.php),生成表单.php。在顶部添加:

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

第2步:(重要部分!):为了避免XSS和第三方漏洞攻击,您应该创建验证临时密钥。 例如:

  • ASP.NET内置表单使用动态输入 crsf (示例值:gtlkjh29f9ewduh024cfvefb
  • WordPress内置表单使用动态输入 nonce (示例值:340297658942346
  • 您的设置表单?没有?然后它很脆弱。

所以,如果你在一个没有内置临时令牌验证方法的自定义平台上,那么创建你的,就像这个简单的概念:

<?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>

(加密代码为here

提交时,请检查:

if(!empty($_POST)){

   // ================ STEP 1 (Basic validation) ======== //
   // if REFERRER is empty, or it's NOT YOUR HOST, then STOP
   if( !isset($_SERVER['HTTP_REFERRER']) || parse_url($_SERVER['HTTP_REFERRER'])['host'] != $_SERVER['HTTP_HOST'] ){
       exit("You are not allowed 1 !");
   }

   // ================ STEP 2 (Stronger validation) ======== //
   if (   Cryptor::decrypt(  $_POST['temp_random'], $_SERVER['REMOTE_ADDR'] . $secret_key) < time() - 60* 15 ) {
       exit("You are not allowed 2 !");
   }




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

}

答案 3 :(得分:2)

表格形式:

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

当您检查时:

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

答案 4 :(得分:0)

如果您正在寻找快速而肮脏的方法,可以查看REFERER标题。

如果您确实希望确保从您的网站获取表单,则应在每次加载表单时生成令牌并将其附加到会话。一个简单的方法是这样的:

$_SESSION['formToken'] = sha1(microtime());

然后您的表单可以隐藏输入:

<input type="hidden" name="token" value='<?=$_SESSION['formToken'];?>' />

您可以在决定是否处理表单数据时进行检查。

答案 5 :(得分:0)

每个用户都进行注册,然后获取登录ID。

以下是防止CSRF的算法: -

1) $login_id = user login id (converted to a numeric id using mysql)
2) $a_secret_key = $_SERVER['UNIQUE_ID'];
3) $remote_addr = $_SERVER['REMOTE_ADDR'];
4) Request Date and Time -> A unique reference key -> $refkey
5) $_SESSION['secretkey'] = $_SERVER['UNIQUE_ID'];

将数据传输到另一页时,将上述1到4组合以创建json文件。

然后

echo "<input type=\"hidden\" name=\"refkey\" value=\"$refkey\"/>";

在接收方结束时: -

接收页面应检查是否

1) any json file with $refkey exists at server?

2) If $refkey exists, then check $login_id, $a_secret_key and $remote_addr exists and are correct.