普通网友 2026-02-28 03:40 采纳率: 99%
浏览 2
已采纳

如何防止用户篡改URL参数进行越权访问?

常见问题: 用户直接在浏览器地址栏修改URL中的ID类参数(如 `/api/orders/123` 改为 `/api/orders/456`),绕过前端权限控制,非法访问他人数据——这属于典型的“水平越权”(Horizontal Privilege Escalation)。问题根源在于后端未对当前登录用户与请求资源的归属关系做服务端校验,仅依赖前端传入的参数或隐含的会话状态。更危险的是,若参数为可预测的自增ID、明文编码或无签名机制,攻击者还可批量遍历敏感资源。此类漏洞在RESTful API、管理后台及单页应用中尤为高发,且OWASP Top 10长期将其列为关键风险(如Broken Access Control)。仅靠前端路由拦截、隐藏URL或禁用右键等客户端防护完全无效,必须在服务端每次请求时,基于用户身份实时验证其对目标资源的操作权限。
  • 写回答

1条回答 默认 最新

  • 秋葵葵 2026-02-28 08:41
    关注
    ```html

    一、现象层:URL参数篡改即得越权访问

    用户在浏览器地址栏将 /api/orders/123 手动改为 /api/orders/456,成功返回非本人订单详情——这是最直观的水平越权表现。前端未做任何拦截(如路由守卫失效、按钮禁用被绕过),后端响应中甚至包含完整敏感字段(如收货人手机号、支付金额、地址)。此类请求在 Chrome DevTools 的 Network 面板中清晰可见,HTTP 状态码为 200,无任何服务端拒绝痕迹。

    二、机制层:权限校验缺失与ID设计缺陷双重叠加

    • 校验盲区:控制器方法仅验证 Authentication.isAuthenticated(),未调用 authorizeResource(userId, orderId) 检查该订单是否归属当前用户;
    • ID可预测性:数据库使用自增主键(id BIGINT AUTO_INCREMENT),且未启用 UUID 或雪花 ID;
    • 传输无保护:URL 中的 ID 未经混淆(如 Base64 编码无盐值)、未签名、未加密,攻击者可构造 /api/orders/1/api/orders/1000 批量探测。

    三、架构层:分层职责错位与安全控制点漂移

    层级典型错误实践正确责任归属
    前端(React/Vue)通过 v-if="order.userId === $store.state.user.id" 控制按钮渲染仅作体验优化,绝不承担授权决策
    网关(Spring Cloud Gateway)仅校验 JWT 签名与过期时间可做粗粒度路由级鉴权(如 /admin/** → ROLE_ADMIN),但不处理资源级归属判断
    业务服务(OrderService)直接执行 orderMapper.selectById(orderId)必须嵌入归属校验逻辑:先查 SELECT user_id FROM orders WHERE id = ?,再比对当前 subject

    四、防御体系:纵深防御四阶模型

    1. 输入混淆:将数据库主键映射为不可预测 Token(如 Hashids、ULID),URL 变为 /api/orders/z9FmRqT7
    2. 运行时校验:在 Spring @PreAuthorize 中注入 SpEL 表达式:@PreAuthorize("@aclService.canAccessOrder(#orderId, #principal.name)")
    3. 数据隔离:MyBatis 拦截器自动追加 AND user_id = #{currentUserId} 到所有 SELECT 语句(需配合租户上下文);
    4. 审计追溯:记录每次资源访问的 subject_idresource_idactioniptimestamp,接入 SIEM 实时告警异常遍历行为。

    五、验证闭环:从渗透测试到自动化回归

    // 示例:Postman Collection 中的越权检测脚本(JavaScript)
    pm.test("Horizontal Escalation Test", function () {
      const originalOrderId = pm.environment.get("my_order_id");
      const otherOrderId = parseInt(originalOrderId) + 1; // 假设自增
      const url = `{{baseUrl}}/api/orders/${otherOrderId}`;
      
      pm.sendRequest({
        url: url,
        method: 'GET',
        header: { 'Authorization': `Bearer {{token}}` }
      }, function (err, res) {
        // ✅ 合规预期:403 或 404(非 200!)
        pm.expect(res.code).to.be.oneOf([403, 404]);
      });
    });
    

    六、演进趋势:零信任架构下的资源访问控制

    graph LR A[客户端请求] --> B{API 网关} B --> C[JWT 解析 & 主体提取] C --> D[OPA 策略引擎] D --> E[查询策略库: “user X can read order Y if order.owner == X”] E --> F{决策结果} F -->|allow| G[转发至 Order Service] F -->|deny| H[返回 403] G --> I[服务内二次校验:SELECT owner FROM orders WHERE id=Y]

    现代系统正将 ABAC(属性基访问控制)与 OPA(Open Policy Agent)深度集成,策略定义与业务代码解耦,支持动态规则热更新。例如:当订单状态为“已取消”时,即使归属正确也禁止导出 PDF——此类细粒度策略无法靠硬编码实现,必须依赖策略即代码(Policy-as-Code)范式。

    ```
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已采纳回答 3月1日
  • 创建了问题 2月28日