【问题标题】:Protecting against record ID manipulation防止记录 ID 操纵
【发布时间】:2016-01-28 17:55:02
【问题描述】:

如何防止恶意用户更改 URL 或表单数据,特别是记录 ID。例如:

http://example.com/deleteproduct.php?id=34

用户可以将 ID 值从 34 更改为 69,然后删除属于另一个客户的记录。我想明显的保护是在执行删除之前验证 ID 以确保用户可以访问该记录,但是否有另一种方法被认为是更好的做法?验证 ID 的不利之处在于需要更多的数据库查询,这很好避免。

【问题讨论】:

  • 尝试生成随机唯一ID和主键。类似sdfjh484957934ueirt
  • 您永远不会对数据过于谨慎,尤其是在更改数据时。在你做之前验证一切。
  • 出于这些原因,我显然会避免使用查询字符串。此外,我会使用@Mr.Engineer 和 Robbie 上面所说的内容。确保 ID 属于相关用户。
  • @JayBlanchard:恶意用户可以像修改查询字符串一样简单地发布请求。
  • 这就是为什么我添加了额外的警告@BradKent

标签: php database security


【解决方案1】:

我想显而易见的保护措施是在执行删除之前验证 ID,以确保用户可以访问该记录。

这是确保您的用户有权删除这些行的唯一方法。

验证 ID 的不利之处在于需要更多的数据库查询,这很好避免。

不一定。您可以简单地检查何时删除以仅删除属于您的用户的行。

例如,假设您的表结构类似于:

users
-----
id | username
1  | Dave
2  | John

products
-----
id | name | user_owner
1  | Milk | 1
2  | Cake | 2

因此,如果 Dave 访问了 deleteproduct.php?id=2,则会执行以下查询:

DELETE FROM products WHERE id = 2 AND user_owner = 1;

它不会删除任何内容,$mysqli->affected_rows 将返回零。

当受影响的行数为零时,表示产品 ID 无效或产品不属于用户,无论哪种方式:您将显示一条消息,告诉用户产品 ID 是无效。

【讨论】:

  • 这个逻辑也适用于其他地方。例如,如果您想注册某人,并检查他们的用户名是否未被使用。而不是做两个查询(一个选择,一个插入)。只需在用户名列上放置一个唯一约束,并使用 PHP 捕获任何错误。如果$mysqli->error 不为空,则该用户已被占用。这 a) 避免了两次查询(节省时间),并且 b) 防止发生任何竞速条件。
【解决方案2】:

他们是否有权删除项目?如果是这样,有关系吗? 如果是按记录授权...只需检查他们是否对请求的 id 有授权。长答案简短:检查他们是否被授权并且永远不要相信用户输入。

【讨论】:

  • 谢谢,把它作为底线是有意义的:永远不要相信用户输入
【解决方案3】:

你说的很危险。

安全

首先,您需要保护数据并使其仅对选定的用户可用。请使用角色和权限创建或微调您的访问列表。

  • 仅显示(登录的)用户可以访问的元素的链接/按钮
  • 在(登录的)用户访问元素之前检查权限(和角色)。不仅是动作,还有数据
  • 身份验证(用户是否登录?)、授权(用户是否有权访问(数据)元素?)

其次,使用内部 id 的 public 不是正确的方法。

隐藏您的内部 id 总是好的,因为它使您的应用程序更安全。

数据访问

您必须访问您的数据。最简单的想法是在查询中检查它,如下所示:

DELETE FROM table WHERE id = 34 AND user_id = 1 // Delete only if id = 34 and user is 1

你明白这个想法吗?

内部 ID

您可以使用现有算法对您的 ID 进行编码。只能使用您的密钥进行解码。有很多解决方案和软件包。

Hashids 是一个小型开源库,可从数字生成短的、唯一的、非连续的 id。 (http://hashids.org/php/)

【讨论】:

  • 感谢您的输入,我的项目确实有用户权限,所以用户只有在有权限的情况下才能删除记录。问题在于记录 ID 的通信,应该无法操纵此值。它自己承认 Hashids 不是一个强大的加密系统,可以通过暴力攻击来破解。我最初实现了一个安全的 32 字符散列系统,但它极大地膨胀了 json 数据。我的问题是开始评估整个架构以及应该采用什么替代系统。
  • 是的,没错。但它比使用内部 id 更安全。此外,我已经添加了关于从您的查询中访问数据的更详细的答案。如果你明白,请告诉我。
  • 明白。由此产生了两件事:a)我违反了规则,没有添加额外的约束,以确保无法使用被操纵的 ID;b)ID 的加密不是主要的防线,验证才是。考虑到这一点,我将回过头来考虑 Hashids,它使我的代码更改更容易实现,并通过向用户呈现不明显的数据值来阻止 ID 操作。再次感谢您的意见。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-07
  • 2015-05-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多