# 越权访问(IDOR 不安全的直接对象引用)识别与修复 > IDOR全称:Insecure Direct Object References,属于**访问控制缺陷**,OWASP Top10经典漏洞 > 一句话定义:应用直接使用用户可控参数指向后端资源对象(id、orderId、userId),**未校验当前登录用户是否有权访问该对象**,攻击者修改参数即可查看/操作他人数据。 ## 一、两类越权区分(考试/审计必记) 1. **水平越权(IDOR最常见)** 同角色之间,A用户修改参数,访问B用户的数据。 例:用户A订单接口 `getOrder?orderId=1001`,改成 `orderId=1002`,读取用户B订单。 2. **垂直越权** 低权限用户,访问高权限角色接口/资源。 例:普通用户调用管理员接口 `deleteUser?uid=1`,执行管理员删除操作。 > 注意:垂直越权不一定是IDOR,属于权限控制失效大类;IDOR多指水平越权。 ## 二、识别方法(授权安全测试场景) ### 1. 寻找可控对象参数 常见参数:`id、uid、userId、orderId、fileId、articleId、ticketId、recordId` - URL参数、POST json、Cookie、请求头里面的数字/字符串ID - REST路径:`/user/1001`、`/api/order/2005` ### 2. 测试步骤(标准复现流程) 1. 账号A登录,拿到属于A的资源ID(例如orderId=1001),正常访问接口,确认返回A数据 2. 切换账号B登录,拿到B的资源ID=1002 3. 在A的会话下,把参数修改为B的ID,发起请求 4. 判断:**成功返回B数据 → 存在水平越权IDOR** > 对照验证:修复后,相同请求应当返回无权限/403,不能返回他人数据 ### 3. 辅助判断特征 - 资源ID自增数字(风险极高) - ID可被用户随意篡改,后端仅校验ID格式,**不校验归属关系** - 接口只校验是否登录,不校验:`资源所属用户 == 当前登录用户` ### 4. 容易遗漏场景 - 文件下载接口 `/download?fileId=xxx` - 图片预览、工单、账单、个人信息接口 - 批量查询接口:传入id数组,未逐个校验归属 - 前端隐藏参数、Cookie里存放业务对象ID ## 三、漏洞原理一句话 **后端直接信任客户端传入的对象ID,只校验登录态,缺少「资源归属权限校验」** ## 四、修复方案(核心:服务端鉴权!前端隐藏参数不算防护) > ❌ 无效修复:前端隐藏ID、前端加密ID(客户端可解密/篡改,只是增加难度) ### ✅ 根治方案(必须后端执行) 1. **每次接口请求,服务端校验资源归属(最重要)** 拿到传入的`orderId`,去数据库查询这条订单对应的`user_id`,**和当前登录用户id比对**,不一致直接拒绝返回403。 伪代码示例: ```java // 错误写法:直接根据id查订单,无归属校验 Order order = orderDao.getById(orderId); // 正确写法:校验订单归属 Order order = orderDao.getById(orderId); if(order == null || !order.getUserId().equals(currentLoginUserId)){ return 403 无权限; } ``` 2. **使用无规律不可预测ID(降低风险,辅助防护,不能单独作为修复)** 不用自增数字id;改用UUID、雪花ID。攻击者无法批量遍历猜测ID。 3. **统一全局权限中间件/切面** 所有涉及对象资源的接口,统一接入权限校验逻辑,避免开发遗漏。 4. **最小权限原则** 接口只返回当前用户有权限的数据;查询列表时,sql自动增加`where user_id=当前用户`,从数据库层面隔离数据。 ```sql -- 查询当前用户订单,自动带上用户条件,无法查别人 select * from orders where id=#{orderId} AND user_id=#{currentUserId}; ``` 5. 垂直越权额外加固:接口增加角色校验 高管理员接口,校验当前用户角色是否拥有管理员权限。 ## 五、检测规则(SIEM/WAF辅助告警,仅辅助) > 无法根治,用于发现异常行为 1. 同一会话短时间大量遍历不同id(id=1,2,3,4批量请求) 2. 用户访问不属于自己的资源ID,返回200成功(业务日志埋点才能检测) > WAF静态规则很难识别IDOR,属于业务逻辑漏洞,必须业务层校验。 ## 六、审计检查清单 - [ ] 所有带id参数的业务接口,后端是否校验资源归属 - [ ] 列表查询SQL是否强制带上当前用户id过滤 - [ ] 是否依赖前端隐藏/加密ID做权限控制 - [ ] 测试:两个账号交叉替换ID,验证访问隔离 ## 七、常见误区 1. ❌ ID加密就安全:加密后的ID依然可以被复制、重放,归属校验缺失依然越权 2. ❌ 前端看不到id就安全:抓包可以看到请求参数 3. ❌ 登录了就是合法:登录只是身份认证;IDOR缺少**授权(权限校验)** > 区分概念:认证(你是谁) vs 授权(你能访问哪些资源) ## 八、漏洞笔记模板适配(沿用你之前的漏洞笔记格式) 漏洞名称:不安全的直接对象引用(IDOR/水平越权) 漏洞类型:访问控制缺陷 水平越权 风险等级:高危 前置权限:已登录普通账号 原理:接口接收用户可控资源ID,后端未校验资源归属,修改ID读取其他用户数据 复现步骤: 1. 账号A登录,获取A的资源ID 2. 修改参数为账号B的资源ID,保持A的Cookie/token 3. 成功返回B用户敏感数据 缓解方案:临时增加接口参数白名单,限制ID范围 永久修复:后端增加资源归属校验,SQL增加user_id过滤,统一权限切面 日志特征:同一token访问多个不同user所属对象ID