2011-03-17 65 views
0

我用的是这样的:表单安全性和PHP?

<input type="hidden" name="ids" value="1, 3, 5" /> 
<input type="hidden" name="cost" value="350" /> 

但我在想,有人可能只是改变说“3”,并为它付出了$ 3.00的成本..所以我在想,会更安全的(SP )选项将这些值设置为会话时,他们加载页面,如下所示:

<? 
unset($_SESSION['baskettotal']); 
unset($_SESSION['basketids']); 
$_SESSION['baskettotal'] = $grand; 
$_SESSION['basketids'] = implode(", ", $ids); 
?> 
<input type="hidden" name="hash" value="<?=md5('stackoverflow'.$_SESSION['baskettotal'].$_SESSION['basketids']);?>" /> 
<? 
if (($_POST['hash']) != (md5('stackoverflow'.$_SESSION['baskettotal'].$_SESSION['basketids']))){ 
    echo "error"; 
    die(); 
} 
?> 

这是一个很好的方法吗?由于他们无法编辑会话,因此它是由他们的篮子中的什么定义的,而不是将其存储在隐藏的输入字段中,而这些输入字段可以轻松操作?

回答

2

你确实是对的,这是一个很好的方法。

1)创建一个会话,该会话包含来自该表单的所有值的散列。

2)当提交表单时,计算表单中的值的哈希值并将它们与SESSION var中的值进行比较。如果他们是相同的,用户没有改变任何东西...如果他们不同,显然用户改变了一些东西。

为了澄清,用户不能更改任何SESSION变量,但是,如果您将其存储在cookie中,例如,用户可能会通过该cookie编辑哈希(因为它存储在客户端,而不是服务器端与会话)。

一个例子可能是:

$_SESSION['form_data'] = md5("randomsalt123".$formValue1.$formValue2); 

,并在用户提交表单:

if($_SESSION['form_data'] == md5('randomsalt123'.$_POST['form_value_1'].$_POST['form_value_2'])){ 
// valid submission 

} else { 
// invalid 
} 
+0

谢谢,很好的答案。我正在考虑在一个哈希中ids和价格,例如它计算$ hash = md5($ ids。$ price);然后把它放在一个隐藏的帖子值中,当它发布时,它会使用SESSION信息创建相同的咸味散列并根据发布的信息进行检查。 – Latox

+0

我用新代码更新了OP,您怎么看? – Latox

+0

你想要做的是(($ _POST ['hash'])!=(md5('stackoverflow'。$ _ POST ['baskettotal']。$ _ POST ['basketids'])))。你想看看新的POSTED数据并将其与旧的散列进行比较。 –

1

也有方法可以更改会话变量。我会将成本存储在用户无法更改的数据库中,然后检查$ _POST ['cost']以确保它与数据库中的内容匹配或完全取消隐藏字段。

如果你不想使用分贝,你可以将它存储在一个文件中。

+0

小心评论一下如何更改会话变量? – Phil

+1

你可能会让它们与cookies混淆...... SESSION数据存储在服务器端。 –

+0

https://addons.mozilla.org/en-us/firefox/addon/add-n-edit-cookies/ < - 有一个Firefox插件,允许您编辑会话和cookie变量。 – MasterZ

1

怎么样在会话存储它们,而不是表单中显示他们呢? (或者当你正在进行计算时忽略它们)。

+0

这就是我在OP中所说的...... – Latox

+0

@Kyle我只是在确认你说的话,并提出了一些小建议。 – Haochi

0

为什么你甚至在表格中存储价格?这应该只存储在服务器端。您可以向用户展示价格,但您不需要让他们将其提交给您。

+0

价格正在提交给外部支付网关,我认为您误解了我的问题。 – Latox

+1

@凯尔:噢....你的问题你说过吗?如果是PayPal,他们实际上可以选择加密表单。 – mpen

-1

如果表单正在提交给外部脚本。那么你的会话检查将是无用的,因为你没有做最后的数据检查。

为了完全安全(或至少是它的外表)将价格服务器端与会话中的ID一起存储,然后在结账时使用curl在最终检查后执行外部呼叫。

+0

我已经编写了脚本来处理这个问题,我并没有问这个问题,而是要求以最安全的方式通过一个帖子传递一些信息,而不需要通过隐藏表单字段发送它们,这些字段可以很容易地被操纵。看来我的方式是最好的。谢谢。 – Latox

+0

那么,我只是提到了这个,因为你在另一个评论中说你正在将它提交给外部脚本。 如果你仔细阅读,除了卷曲部分,方法主要是相同的。 希望你能解决它while.h。 – frostymarvelous

1

我认为你的方式很好。但是当我们没有在表单上显示该值时,就不需要将隐藏字段与会话值进行匹配。如果某人编辑的隐藏字段值不影响您的计算,请根据会话变量值进行计算。

-1

这对我来说是不够的:

<?php 
session_start(); 
// thanks to bantam 
// http://www.php.net/manual/en/function.mcrypt-encrypt.php#87526 
define('SALT', 'whateveryouwant'); // use define, db stored value, var, included, etc. 
function encrypt($text) 
{ 
    return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, SALT, $text, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)))); 
} 

function decrypt($text) 
{ 
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, SALT, base64_decode($text), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND))); 
} 

unset($_SESSION['baskettotal']); 
unset($_SESSION['basketids']); 

$grand = 350; 
$ids = array(1, 3, 5); 

$_SESSION['baskettotal'] = $grand; 
$_SESSION['basketids'] = implode(", ", $ids); 

?> 
<form method="post" action="<?php $_SERVER['PHP_SELF']?>" enctype="application/x-www-form-urlencoded" > 
    <input type="hidden" name="enc" value="<?= encrypt('stackoverflow' . $_SESSION['baskettotal'] . $_SESSION['basketids']);?>" /> 
    <input name="send" type="submit" value="Submit"> 
</form> 
<? 
if (decrypt($_POST['enc']) !== 'stackoverflow' . $_SESSION['baskettotal'] . $_SESSION['basketids']) die('Not so fast'); 
else echo 'Go ahead'; 
?> 

在第一次运行时,你获得:

没有这么快

当你点击提交按钮:

来吧

希望它有帮助。 Source

0

您的初始代码没问题,而进一步的“改进”没有多大意义。
我看不出所有隐藏的哈希值。

为什么不只是使它

$_SESSION['baskettotal'] = $grand; 
$_SESSION['basketids'] = $ids; 

,然后直接从POST会议提交获得这些2个变量。

$grand = $_SESSION['baskettotal']; 
$ids = $_SESSION['basketids']; 

这就是全部!
为什么设计所有的东西,不必复杂的代码?