暴露您的主键(特别是如果它们是可预测的)是一个称为不安全直接对象引用的漏洞。
通过这样的 URL(或任何其他客户端提供的参数):
http://www.domain.com/myaccount?userid=12
您让最终用户有机会处理这些变量并传递他们喜欢的任何数据。缓解此漏洞的对策是创建间接对象引用。这听起来像是一个很大的变化,但不一定非得如此。您不必重新设置所有表或任何东西的密钥,只需通过使用间接引用映射巧妙地处理数据即可。
考虑一下:您有一个用户正在您的网站上进行购买。当需要付款时,他们会看到您“存档”的他们的信用卡号码的下拉列表。如果您查看下拉菜单的代码,您会看到信用卡号与密钥 8055、9044 和 10099 相关联。
用户可能会看到这个并认为它们看起来很像自动递增的主键(用户可能是对的)。于是他开始尝试其他钥匙,看看他是否可以用别人的卡支付。
现在从技术上讲,您应该在服务器端有代码,以确保所选卡是用户帐户的一部分并且他们可以使用它。这是一个人为的例子。现在我们假设情况并非如此,或者这是另一种可能没有这种服务器端控件的表单。
那么我们如何防止最终用户选择他们不应该使用的密钥呢?
不要向他们显示对数据库中记录的直接引用,而是给他们一个间接引用。
我们将在服务器上创建一个数组并将其填充到用户的会话中,而不是将数据库密钥放入下拉列表中。
Array cards = new Array(3);
cards[0] = 8055;
cards[1] = 9044;
cards[2] = 10099;
在下拉列表中,我们现在提供对存储卡的数组索引的引用。因此,如果最终用户查看源代码,他们将看到值 0、1 和 2,而不是看到实际的键。
提交表单时,将传递其中一个值。然后我们从用户会话中取出数组,并使用索引来获取值。实际密钥从未离开服务器。
如果用户愿意,他可以全天传递不同的值,但他永远不会得到除了他自己的卡片以外的结果,不管服务器端的访问控制如何。
请记住,当使用传入的索引来获取值时,如果用户确实弄乱了它,您可能会遇到一些异常(ArrayOutOfBounds、InvalidIndex 等)。因此,将这些东西包装在 try/catch 中,这样您就可以抑制这些错误并记录失败以查找破解尝试。
希望这会有所帮助。
要了解有关不安全直接对象引用的更多信息,请查看 OWASP Top 10。风险编号为 A4。 https://www.owasp.org/index.php/Top_10_2010-A4-Insecure_Direct_Object_References