1

我正在尝试开发一个表单助手来防止表单欺骗。所以我想出了这个:

<form...>
<?=form::secure()?>
...
</form>

它使用一个令牌标记一个隐藏的表单,该表单带有一个令牌,该令牌是用户会话 id 的 md5(它是随机的,并在 1 周后更新)。然后在“动作”网址(来自表单):

$token = (isset($_GET['_token'])) ? $_GET['_token'] : null;
$token = (is_null($token) and isset($_POST['_token'])) ? $_POST['_token'] : $token;
if (form::is_secure($token)) { // checks if the given token is equal to md5(user id)
    ...ok...
} else {
    ...error...
}

这是否可以防止表单欺骗或我遗漏了什么?如果用户 id 在用户刚刚加载页面然后提交其表单的确切时刻过期,它只会打印一个错误,他应该再次提交表单,但这是可以接受的(很少见)。

我认为这里唯一可能出错的是,如果潜在的攻击者能够获取用户会话 ID,然后他可以将 ?_token=id 附加到它的请求并将其提供给用户进行浏览,但那时,如果攻击者拥有用户会话 ID,它无论如何都可以为所欲为。

我对吗?如果没有,我该如何编辑我的代码来实现我的目标?

4

2 回答 2

5

您实际上是在重新发明轮子,因为令牌需要有效的会话来验证,因此只会重复会话的安全层,而不添加任何额外的东西。这相当于要求某人输入他们的密码,然后再次要求确认。它可能会让每个人感觉更好,但如果密码被泄露,它只会减缓攻击,但不能阻止攻击。

这并不是说您不应该认真对待这些事情或拒绝您的尝试。我的哲学是表单的内容(通过GET或传递的内容)POST) 应与其他逻辑(例如安全性和计算)分开,并且服务器不应将用户提供的数据视为用户提供的数据以外的任何内容。理想情况下,任何人都可以将任何内容发布到表单操作,并且服务器/控制器将正确且一致地管理它。会话被验证(安全),数据被清理然后验证,当用户实际使用 Web 表单时通过 JS 生成的任何值都被重新计算/验证。理想情况下,响应足够通用,无论是重定向响应还是 Web 标准响应,以便请求者,无论是 Web 浏览器、命令行用户还是 Web 服务都可以解释它。

如果是上述情况,那么对欺骗的重视和关注就会减少,更多地强调分别增强安全层和验证层,而且最重要的是,做得好的后端控制器可以很容易地被移植/重用为一个网络服务后端。

长话短说:您的解决方案还不错,据我所知,它只是没有添加任何真正的安全性,甚至可能会暴露您的后端安全性逻辑。如果您有特定的欺骗问题/威胁,最好解决该用例并解决问题,而不是立即尝试提出一种万能的解决方案。事实证明,您的用例具有特定的解决方案/考虑因素,需要在交换的不同点解决。

于 2012-06-27T00:02:31.603 回答
1

不要重新发明轮子。如果您不使用 Web 框架,请集成为您的项目添加 CSRF 保护的无数库之一,例如CSRF4PHP

您的解决方案很接近,但无法正常工作,因为攻击者可以抓取会话 ID。

于 2012-06-27T00:34:25.043 回答