不安全直接对象引用 (IDOR)
不安全的直接对象引用 (IDOR) 是一种漏洞,它允许攻击者利用不充分的访问控制和对对象标识符(如数据库密钥或文件路径)的不安全暴露。
网站通常希望为不同的用户提供不同的内容:例如,购物网站可能允许每个用户查看他们的购买历史记录。网站可以通过身份验证来识别用户,使用密码或密钥等方法。通常,一旦网站验证了用户身份,它会在用户的浏览器中设置一个会话 cookie:然后,当用户发出请求时,服务器就会知道该请求来自该已验证的用户。
然而,除了检查请求是否来自已验证的用户之外,服务器还必须为用户请求的资源实施访问控制:也就是说,它们必须检查该用户是否允许访问所请求的特定资源。例如,每个已验证的用户只能查看自己的购买历史记录。
如果服务器没有为资源实施访问控制,那么已登录该网站的攻击者就可能能够访问属于其他用户的数据。这就叫做不安全的直接对象引用 (IDOR) 攻击。
示例场景
经典的 IDOR 攻击发生在服务器仅检查用户是否已通过身份验证,但未检查他们是否有权访问对象引用时。在典型流程中,攻击者会
- 以普通用户身份登录。
- 找到一个引用用户或资源 ID(例如,1234)的 URL、表单字段或文件。
- 将 ID 修改为另一个值(例如,1233)。
- 获得对另一个用户数据的未授权访问。
在接下来的部分中,我们将探讨此攻击的一些具体示例。
URL 篡改
一种常见的 IDOR 攻击类型涉及对 URL 中的直接对象引用进行操作。“1234” 在以下 URL 中是服务器数据库中用户记录的标识符。如果攻击者将此数字更改为任何其他数字(例如“1235”),并获得了对另一个用户信息的访问权限,则您的应用程序就容易受到不安全直接对象引用攻击。
# The attacker is logged in as user 1234
https://example.org/user/id/1234
# The attacker changes the id in the URL and gains access to a different user
https://example.org/user/id/1235
例如,在下面的 Express 代码中,URL 中提供的值可作为 req.params.id 获取,我们使用该值从数据库中检索相应的记录。我们还通过(调用 isAuthenticated 函数)来检查请求是否来自已验证的用户。但关键是,我们没有检查已验证用户的 ID 是否与 URL 中的 ID 匹配,这使得一个已验证的用户(攻击者)能够获取另一个已验证用户的页面(受害者)。
app.get("/user/id/:id", (req, res) => {
const user = db.users.find(req.params.id);
if (req.isAuthenticated()) {
// Authentication is not enough!
res.render("user", { user });
}
});
相反,您应该实施规则来授权访问用户信息。例如,只有当登录用户的 ID 与请求用户的 ID 匹配时,才渲染用户页面。否则,返回 HTTP 401 Unauthorized 响应。
app.get("/user/id/:id", (req, res) => {
const user = db.users.find(req.params.id);
if (req.isAuthenticated() && req.session.userId === req.params.id) {
res.render("user", { user });
} else {
return res.status(401).json({ message: "Unauthorized" });
}
});
文档操纵
与 URL 篡改类似,页面正文可以通过攻击者修改表单元素的值来操纵,例如单选按钮、复选框或浏览器开发者工具中的(隐藏)<input> 元素。例如,您的应用程序可能不在 URL 中提供用户 ID,而是通过隐藏的表单元素传递用户 ID。
<form action="updateUser" method="POST">
<input type="hidden" name="user_id" value="1234" />
<button type="submit">Update profile</button>
</form>
如果没有执行服务器端访问控制,攻击者就可以将隐藏的 <input> 元素中的 user_id 值修改为另一个用户 ID,并可能在未经授权的情况下修改个人资料。
文件访问
IDOR 攻击的一个特殊情况是访问未受访问控制保护的文件或目录。例如,如果您提供一个用于上传 PDF 文件的文件夹,并且上传的文件按顺序命名,那么如果未提供访问控制,攻击者就可以猜测文件名并下载所有文件。潜在地,还可以获取其他目录(如服务器配置文件)中的文件,这可能导致其他漏洞。
https://example.org/static/pdfs/1.pdf
https://example.org/static/pdfs/2.pdf
防范 IDOR 的措施
每个对象的访问控制
防范 IDOR 攻击最重要的措施是为用户尝试访问的每个对象实施服务器端访问控制检查。始终验证已验证的用户是否有权访问目标对象或对其执行操作。
标识符的复杂性
确保资源标识符无法被攻击者猜测。不要在 URL 中暴露任何个人身份信息 (PII),如用户名或电子邮件地址。相反,使用唯一的、不可猜测的令牌来表示用户。您可以使用更复杂的 ID 作为主键,例如 UUID,使其更难猜测有效值。然而,这只会降低猜中有效 ID 的可能性,并不能取代适当的访问控制。
防御总结清单
- 始终验证已验证用户是否有权访问或修改对象。
- 避免暴露可预测、顺序或敏感的对象标识符(如用户 ID 或电子邮件地址)。
- 使用更复杂、更难预测的 ID(例如,UUID)。