🔐 我的信息我来守护!为什么应该使用会话而不是URL参数(IDOR漏洞)

各位开发者大家好!今天,我想和大家聊聊一种在Web应用程序中非常常见,但一旦被利用就可能失控的安全漏洞及其解决方案。👨‍💻

想象一下,您最近在代码审查中发现了以下修改。

// 修改前 (Before) 👎
// const { userId } = req.params;

// 修改后 (After) 👍
const { userId } = req.session;

仅仅一行代码的改变。然而,这个微小的差异可能会将您的服务从地狱中拯救出来。如果您想对“为什么这更安全?”这个问题获得清晰的答案,请务必关注本文直到最后!🚀


🤔 问题的开始:从URL获取用户ID?

首先,我们来看看有问题的现有代码。

// 不安全的方式
const {
    userId
} = req.params;

allocationsDAO.getByUserIdAndThreshold(userId, threshold, (err, allocations) => {
    // ... 根据用户ID查询数据并显示结果
});

这段代码直接从URL路径中包含的值(req.params)获取并使用userId。例如,如果用户访问这个地址,服务器会将userId识别为“user123”并查询该用户的数据。

乍一看似乎没什么问题,对吧?但这里隐藏着一个非常可怕的陷阱。

假设我是一个恶意用户“hacker”,我的ID是“user456”。我可能会访问来查看我的分配信息。但突然间,我有了这样一个想法。

“咦?如果我只更改URL末尾的ID,是不是也能看到别人的信息?”

于是,我在地址栏中输入并按下回车。如果服务器没有进行任何权限验证…可怕的是,“user123”的信息就会呈现在我眼前!😱

这正是OWASP Top 10中常见的不安全直接对象引用(Insecure Direct Object Reference, IDOR)漏洞。这就像只要知道公寓的楼号和房间号,就可以随意打开别人家门进入一样。


✨ 完美的解决方案:可信信息存在于“会话”中!

那么,提供的修改后的代码是如何解决这个问题的呢?

// 修复 A4 不安全直接对象引用 - 从会话而不是URL参数中获取用户ID
const { userId } = req.session;

allocationsDAO.getByUserIdAndThreshold(userId, threshold, (err, allocations) => {
    // ... 根据用户ID查询数据并显示结果
});

答案就是使用 req.session!

  • req.params (URL参数): 这是用户可以在浏览器地址栏中随意操纵的值。它是一个绝不能信任的外部输入值。
  • req.session (会话): 这是用户成功登录时,服务器内部存储并保证的信息,表明“该用户是经过认证的OOO”。用户无法直接修改此会话信息。它就像政府颁发的不可伪造的身份证。

新代码不关心URL中写了什么。相反,它从服务器上存储的当前登录用户的会话信息中获取userId。

因此,即使我以“user456”身份登录,并巧妙地将URL更改为…/allocations/user123并发送请求,服务器也会这样操作。

  1. “哦,用户‘user456’发送了一个请求。”(通过Cookie检查会话)
  2. “代码指示使用req.session.userId,所以我应该将‘user456’分配给userId变量。”
  3. “最终,我应该查询并显示‘user456’的数据。”

最终,我将永远无法看到他人的信息,只能查看我自己的信息。IDOR漏洞得到了完美的防御!🛡️


🎯 结论:您的代码安全吗?

今天我们讨论的代码更改的答案是明确的。

是的,将代码修改为从会话(req.session)而不是URL参数(req.params)中获取用户标识符,是大幅增强安全性的一个非常正确且重要的措施。👍

这个小小的改变是正确实现用户数据访问授权的关键一步。请始终记住:“所有来自用户的输入都是潜在的威胁。”尤其是在验证用户身份和控制权限时,绝不能相信用户可以操纵的值,而应使用服务器控制的可信信息(会话)。

现在就检查您的代码。您是否在查询重要数据时直接使用了URL中的值呢?😉

标签: 安全, 网络安全, Nodejs, Express, IDOR, 不安全直接对象引用, 会话, 认证, 授权, 开发, 编码


Comments

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注