·7 分钟IDOR授权实战
授权漏洞实战 — URL中的一个数字,打开了全部客户数据
IDOR是自动扫描工具最难抓到的代表性漏洞之一。实际的攻击模式,以及在代码层面防范的方法。
只是把URL里的/orders/1042改成/orders/1043,就能看到别人的订单记录——这不是偶然,而是授权(Authorization)漏洞。业界称之为IDOR(Insecure Direct Object Reference,不安全的直接对象引用),是自动扫描工具最难抓到的漏洞之一。
认证与授权是不同的
能不能登录(认证,Authentication),和登录的人是否有资格查看那份数据(授权,Authorization),是完全不同的问题。大多数服务都会仔细打造登录功能,却很容易忘记检查"这个用户是不是真的拥有这个资源"。
实际上是这样被攻破的
GET /api/orders/1042 → 我的订单(正常) GET /api/orders/1043 → 直接看到别人的订单(有漏洞)
当服务器代码大致长这样时,就会发生这个问题。
// 有漏洞的代码:只用id查询,没有确认所有者
app.get('/api/orders/:id', async (req, res) => {
const order = await db.order.findUnique({ where: { id: req.params.id } });
res.json(order);
});只确认有没有登录,没有确认"这笔订单是不是登录用户本人的"。 只要依次把数字ID换一遍,就能浏览所有客户的订单。
为什么扫描工具容易漏掉
一般的自动扫描工具擅长抓"这个API是不是返回200"、"是否存在SQL注入"这类模式。但IDOR的响应确实正常地返回200和有效数据,必须理解"这份数据是谁的"这种业务上下文,才能发现问题。这需要比简单模式匹配更深一层的分析。
修复方法
// 修复:查询条件务必包含所有者(userId)
app.get('/api/orders/:id', async (req, res) => {
const order = await db.order.findFirst({
where: { id: req.params.id, userId: req.user.id },
});
if (!order) return res.status(404).end();
res.json(order);
});原则只有一个:"查询条件永远要包含当前登录的用户"。 只要有单靠ID查询的query,都应该视为可疑对象。
测试方法
最可靠的做法是创建两个账号,在登录A账号的状态下,直接请求B账号的资源ID。 如果响应是200和正常数据,就代表有问题。响应应该是404或403才正常。
IDOR不需要花哨的黑客技术。只要在浏览器地址栏改一个数字就能被发现并利用。这正是它更危险的原因。
WhiteHat Code的深度扫描会一并分析代码的业务上下文,找出这类授权缺失的模式。现在就用免费扫描确认一下吧。