漏洞深度教学报告:访问控制漏洞与权限提升(中阶通关版)
0. 📖 学习路径
两轮学习法
第一轮:建立手感(目标:Apprentice 全通)
├─ 读:A(一句话定义 + 原理)→ B(触发点,扫一遍有印象)
├─ 做:直接开 Apprentice Lab,边做边学
├─ 卡住时:
│ ├─ 第一反应:看 E 排错流程,按步骤诊断
│ └─ 还不行:看 C-Layer1 对应的检测思路
└─ 完成标志:能不看笔记说出「垂直越权」「水平越权」「IDOR」的区别
第二轮:突破防御(目标:Practitioner 全通)
├─ 读:A(子类型族谱)→ C-Layer2(绕过思维)→ E(怪坑区)
├─ 做:Practitioner Lab
├─ 卡住时:
│ ├─ 第一反应:E 排错流程
│ ├─ 被 403/拦截:C-Layer2 绕过思路
│ └─ 反复失败:D 常见错误思路,检查自己是不是犯了
└─ 完成标志:遇到权限拦截能想出 ≥2 种绕过方向
按困境跳转
| 你卡在哪 | 跳到哪 |
|---|
| 完全没概念,不知道这漏洞是什么 | A-1(一句话定义) |
| 不知道什么情况该测访问控制 | B(触发点) |
| 改了参数没反应 | E(排错流程)→ E(怪坑区) |
| 被 403/Unauthorized 了 | C-Layer2(绕过思维) |
| 反复失败,怀疑自己思路有问题 | D(常见错误思路) |
| 想确认自己是不是真的懂了 | F(自测问题) |
A. 漏洞全景
1️⃣ 一句话定义
这个漏洞本质上是什么?
访问控制漏洞 = 应用没有正确验证「你是否有权做这件事」,导致你能访问不该访问的资源、执行不该执行的操作。
生活类比
想象一栋办公楼:你刷卡进了大门(身份认证),但每层楼、每个房间应该还有单独的门禁。访问控制漏洞就像是——财务室的门虽然关着,但根本没锁;或者门禁系统只看你工牌上「自己写的」部门名称。
2️⃣ 为什么会发生?(正常流 vs 攻击流)
正常流程:
用户请求资源 → [身份认证:你是谁?] → [权限校验:你能做这个吗?] → 允许/拒绝
↓ ↓
Session 确认 检查角色/资源归属
攻击流程:
攻击者请求 → [身份认证 OK] → [权限校验缺失/逻辑有漏洞]
↓
直接访问了不该访问的东西
三个关键点:
- 攻击者能控制什么:URL 路径、请求参数(id/role/admin)、HTTP 方法、HTTP Header(Referer/X-Original-URL)、Cookie 中的角色标识
- 哪里断了让攻击成功:服务端没有在「每个敏感操作点」独立验证权限,而是依赖「前端隐藏」「URL 难猜」「客户端传值」
- 危险点在哪:权限判断逻辑——它是在服务端真正检查数据库里的角色,还是只相信请求里传来的值?
3️⃣ 子类型族谱
| 子类型 | 一句话特点 | 常见场景 | 难度分布 | 🎯 能帮你拿数据吗? |
|---|
| 未保护的功能 | 敏感页面根本没权限检查 | 管理后台直接能访问 | Apprentice | 直接拿(管理功能全开) |
| 隐藏 URL 泄露 | 靠 URL 难猜当安全,但 JS 里写着 | robots.txt/JS 泄露路径 | Apprentice | 直接拿 |
| 参数控制角色 | Cookie/参数里的 role 值可改 | admin=true、role=1 | Apprentice | 直接拿(伪造高权限) |
| 水平越权(IDOR) | 改 id 参数访问别人的数据 | ?id=123 → ?id=456 | Apprentice | 直接拿(别人的数据) |
| GUID 泄露型 IDOR | ID 不可猜但别处泄露 | 评论区暴露用户 GUID | Apprentice | 直接拿 |
| 重定向中的数据泄露 | 虽然跳转了但响应里有数据 | 302 响应 body 含敏感信息 | Apprentice | 直接拿 |
| 水平→垂直提权 | 先越权访问管理员页面拿凭证 | 管理员密码明文显示 | Apprentice | 直接拿(拿到后完全控制) |
| 平台层 URL 绕过 | 用 X-Original-URL 绕前端控制 | 前端拦 URL,后端认 Header | Practitioner | 直接拿 |
| HTTP 方法绕过 | 换个 HTTP 方法就过了 | POST 被拦,GET 没拦 | Practitioner | 直接拿 |
| 多步骤流程漏洞 | 前几步有检查,最后一步没有 | 跳过前置步骤直接提交 | Practitioner | 直接拿 |
| Referer 依赖 | 只检查请求来源页面 | 伪造 Referer 头 | Practitioner | 直接拿 |
4️⃣ 学习投入
| Lab 分布 | 数量 | 预估时间 |
|---|
| Apprentice | 9 个 | 每个 10-20 分钟 |
| Practitioner | 4 个 | 每个 30-45 分钟 |
| 本报告覆盖 | 13 个 | 约 4-6 小时 |
5️⃣ 📊 拖库思维:这个漏洞能帮你拿到数据吗?
定位判断
问自己:「访问控制漏洞能帮我拿到数据吗?」
├─ 🔴 能直接拿
│ → 水平越权:直接读别人的数据
│ → 垂直越权:拿到管理权限后访问所有数据
│ → 这是「直接拖库点」
│
├─ 🟡 能拿到凭证
│ → 越权访问管理员页面 → 看到密码明文
│ → 它是「跳板」,拿到凭证后解锁更多
│
└─ 🟢 它本身就是「权限放大器」
→ 从普通用户 → 管理员
→ 解锁整个系统的攻击面
本漏洞的定位:访问控制漏洞是核心权限放大器,同时也是直接数据获取点。它不像 SQLi 那样需要构造复杂 payload,往往改个参数就能拿到数据。
从这个漏洞到数据的路径
路径 A(水平越权直取):
发现可控 ID 参数 → 遍历其他用户 ID → 直接获取他们的数据
路径 B(垂直提权后取):
发现角色标识可控 → 伪造管理员 → 访问管理后台 → 导出全部数据
路径 C(越权+凭证泄露):
水平越权访问管理员账户页 → 发现密码明文 → 用凭证登录 → 完全控制
拿数据时优先拿什么?
| 优先级 | 拿什么 | 为什么 |
|---|
| 先拿 | 管理员凭证 | 拿到后可以操作整个系统 |
| 再拿 | 其他用户敏感数据 | 证明危害范围 |
| 最后 | 系统配置 | 可能有数据库连接串 |
6️⃣ 🌐 现代 API 环境下的样子
传统 Web vs API 的差异
| 传统 Web | API 环境 | 检测时要注意 |
|---|
| 页面级权限控制 | 端点+资源级控制 | 每个 API 端点都要测 |
| 角色存 Session/Cookie | 角色可能在 JWT 里 | 解码 JWT 看有没有可改字段 |
| 前端不显示 = 伪安全 | 前端不调用 ≠ 后端不存在 | 从 JS/Swagger 找隐藏端点 |
| URL 路径敏感 | RESTful 资源 ID 敏感 | /api/users/{id} 必测 |
API 环境特有的检测点
□ REST API 场景:
- GET /api/users/123 → 改成 /api/users/456
- /api/users/me 可能也接受 /api/users/{id}
- 测不同 HTTP 方法:GET/POST/PUT/DELETE/PATCH
□ GraphQL 场景:
- query { user(id: "123") } → 改 id
- 用 Introspection 发现隐藏 mutation
- 批量查询能否越权拉多条
□ JWT/Token 场景:
- 解码看 role/admin/isAdmin 字段
- 若无签名验证 → 直接改值
- 测:过期 Token、空 Token、其他用户的 Token
B. 触发点:什么情况该想到测这个漏洞?
🧠 目标:建立条件反射,看到特定功能/参数/现象,脑子自动响「要测访问控制」
1️⃣ 功能触发(看到这种功能 → 想到测这个)
| 看到这种功能 | 脑子里要响 | 初步验证动作 |
|---|
| 「我的账户」「个人中心」 | 「URL 里有 ID 吗?能改吗?」 | 改 ID 看能不能访问别人 |
| 「管理后台」「Admin Panel」 | 「普通用户能直接访问吗?」 | 直接访问 /admin 类路径 |
| 「删除用户」「修改权限」 | 「我没权限能调这个接口吗?」 | 抓包重放,去掉管理员 Cookie |
| 「查看订单」「下载文件」 | 「订单号/文件名可控吗?」 | 改 orderid/filename 参数 |
| 多步骤流程(确认页面) | 「能跳过前面步骤吗?」 | 直接请求最后一步 |
2️⃣ 参数触发(看到这种参数 → 想到测这个)
| 参数长这样 | 脑子里要响 | 初步验证动作 |
|---|
?id=123 ?uid=xxx | 「这是 IDOR 的典型目标」 | 改成其他数字/GUID |
?admin=false ?role=user | 「能改成 true/admin 吗?」 | 改值看响应变化 |
Cookie:isAdmin=0 | 「客户端控制角色?危险」 | 改成 1 |
?action=view | 「能改成 delete/edit 吗?」 | 测其他 action 值 |
3️⃣ 现象触发(看到这种响应/报错 → 想到测这个)
| 看到这种现象 | 脑子里要响 | 下一步动作 |
|---|
| 403 Forbidden | 「有东西在这!怎么绕?」 | 试 HTTP 方法/Header 绕过 |
| 302 重定向到登录页 | 「响应 body 里有没有数据?」 | 检查重定向前的响应内容 |
JS 里有 isAdmin 判断 | 「管理员 URL 写在哪?」 | 搜索 JS 找隐藏路径 |
| robots.txt 有 Disallow | 「这些路径可能是敏感功能」 | 直接访问这些路径 |
| API 文档/Swagger | 「有哪些端点?哪些需要认证?」 | 测每个端点的权限 |
4️⃣ API 环境特有触发点
□ 如果是 REST API:
- 看到 /api/v1/users/{id} → 必测 IDOR
- 看到 /api/admin/... → 测普通用户能否访问
- 看到不同 HTTP 方法 → 测方法替换
□ 如果是 GraphQL:
- 看到 id 参数 → 测越权查询
- 能做 Introspection → 找隐藏 mutation
□ 如果响应是 JSON:
- 看到 role/permission 字段 → 记录下来,尝试篡改请求
- 看到其他用户 ID → 记录用于越权测试
C. 攻击技术
Layer 1 - 基础检测与利用(Apprentice 核心)
检测思维:怎么判断存不存在?
核心思路:
访问控制漏洞的检测 = 「做你本不该能做的事,看看能不能成功」
具体步骤:
Step 1:明确「正常情况下我不该能做什么」
Step 2:尝试去做那件事
Step 3:观察是被拒绝了,还是成功了
Step 4:如果成功 → 漏洞存在;如果失败 → 分析失败原因,调整方法
基础检测思路(本漏洞专用)
| 检测目的 | 操作思路 | 如果存在会看到什么 |
|---|
| 未保护的管理功能 | 尝试直接访问 /admin、/administrator、/管理常见路径 | 无需认证就能看到管理页面 |
| 隐藏 URL 泄露 | 检查 robots.txt、查看 JS 源码搜索路径 | 找到隐藏的管理入口 |
| 参数控制角色 | 找 Cookie/参数中的 role/admin/isAdmin,尝试修改 | 修改后获得更高权限 |
| 水平越权 | 把 URL/参数中的用户 ID 改成别人的 | 能看到别人的数据 |
| GUID 型越权 | 在应用其他地方找目标用户的 GUID | 用泄露的 GUID 访问其账户 |
基础利用思维
确认存在后,下一步思考:
├─ 是水平越权?→ 遍历 ID,批量获取数据
├─ 是垂直越权?→ 尝试执行管理操作(删用户、改配置)
├─ 能看到别人密码?→ 尝试访问管理员账户
└─ 有多个角色?→ 测试每个角色的边界
Layer 2 - 绕过思维(Practitioner 核心)
被 403/拒绝了怎么想?
第一步:确认「到底是谁在拦」
├─ 是应用层拦的?(响应里有业务逻辑提示)
├─ 是平台/框架层拦的?(标准 403 页面)
└─ 是 WAF 拦的?(特殊错误页面)
第二步:根据拦截层选择绕过方向
├─ 应用层 → 逻辑绕过(参数篡改、流程跳跃)
├─ 平台层 → Header 覆盖、方法替换、路径变形
└─ WAF → 编码、大小写、路径混淆
常见防御与绕过方向(本漏洞专用)
| 你遇到的情况 | 可能的防御 | 绕过思考方向 |
|---|
| 直接访问 /admin 被拦 | 前端 URL 黑名单 | 用 X-Original-URL / X-Rewrite-URL Header |
| POST 请求被拦 | HTTP 方法白名单 | 换成 GET/PUT/PATCH/HEAD |
| /admin/delete 403 | 路径精确匹配 | 试 /admin/delete/、/ADMIN/DELETE、/admin/delete.json |
| 检查了 Referer | Referer 白名单 | 伪造 Referer 头为允许的来源 |
| 前两步有检查 | 多步骤流程控制 | 直接请求第三步,带上必要参数 |
| ID 不可预测 | 使用 GUID | 在评论/消息/日志里找泄露的 GUID |
平台层绕过技巧
URL 覆盖 Header(当 URL 被前端拦截时):
├─ X-Original-URL: /admin/deleteUser
├─ X-Rewrite-URL: /admin/deleteUser
└─ 实际请求路径设为 /(或其他允许的路径)
HTTP 方法替换(当特定方法被拦截时):
├─ POST 被拦 → 试 GET(参数放 URL)
├─ POST 被拦 → 试 POSTX(有些框架不认识就放行)
└─ 记得:body 参数可能要转成 URL 参数
路径变形(当路径精确匹配时):
├─ /admin/deleteUser → /admin/deleteUser/
├─ /admin/deleteUser → /Admin/DeleteUser
├─ /admin/deleteUser → /admin/deleteUser.anything
└─ /admin/deleteUser → /admin/./deleteUser
Layer 3 - 多步骤流程攻击
思维框架
多步骤操作的访问控制漏洞:
前提:敏感操作被分成多个步骤(如:选择→确认→执行)
漏洞模式:
├─ 步骤 1 有权限检查 ✓
├─ 步骤 2 有权限检查 ✓
└─ 步骤 3 没有检查 ✗ ← 开发者假设「能到这一步的一定已经通过前面的检查」
攻击思路:
├─ 观察正常流程,抓取每一步的请求
├─ 分析最后一步需要哪些参数
└─ 以低权限用户身份,直接发送最后一步的请求
D. 思维演示
完整探索过程(含「卡住→调整」)
🎯 目标:测试某网站的访问控制
👀 第一眼观察:
- 登录后有「我的账户」页面
- URL 是 /myaccount?id=12345
- 这个 ID 看起来像用户标识
💭 第一个念头:
- 经典 IDOR 场景
- 试试改 ID 能不能看到别人的账户
📤 第一次尝试:
- 把 id=12345 改成 id=12346
- 期望看到另一个用户的信息
📥 结果:
- 返回 403 Forbidden
💭 分析:
- 有访问控制,但可能不完善
- 403 说明这个参数确实被用来查数据
- 问题是怎么绕过这个检查
🔄 第二次尝试:
- 检查有没有其他地方泄露用户 ID
- 在博客评论区看到用户名和对应的 profile 链接
📥 结果:
- 找到了管理员的 profile 链接
- 里面有个 GUID:a1b2c3d4-e5f6-...
❌ 卡住了,用 GUID 访问还是 403:
- 可能的原因 1:ID 参数不是这个 GUID
- 可能的原因 2:访问控制确实到位
- 可能的原因 3:需要其他条件配合
🔄 第三次尝试:
- 仔细看 403 响应的 body
- 发现虽然返回 403,但 body 里有部分数据!
💡 突破:
- 原来是「响应里包含数据,但状态码是拒绝」
- 应用先查了数据,再检查权限,但数据已经在响应里了
✅ 总结:
- 关键教训:别只看状态码,要看响应内容
- 下次遇到 403/302 都要检查响应 body
❌ 常见错误思路(本漏洞专用)
| 错误直觉 | 为什么错 | 正确想法 |
|---|
| 「URL 不显示 ID,应该没有越权问题」 | ID 可能在 Cookie、POST body、Header 里 | 抓包看所有参数,不只看 URL |
| 「返回 403 就是没戏了」 | 可能是前端拦的,后端没拦;或者响应 body 有数据 | 尝试绕过方法,检查响应内容 |
| 「ID 是 GUID 猜不到就安全」 | GUID 可能在别处泄露(评论、日志、API响应) | 全站搜索目标 GUID |
| 「管理功能我没看到入口就不存在」 | 入口可能在 JS 里、robots.txt 里、或者直接猜 | 主动寻找隐藏路径 |
| 「登录了不同账号测就行」 | 还要测未登录、低权限、高权限的各种组合 | 系统测试每种角色组合 |
E. 排错与怪坑
排错流程(测试不生效时按这个走)
访问控制测试没效果
│
├─ 1. 「参数找对了吗?」
│ 检验:这个参数真的影响数据获取吗?
│ ├─ 删掉参数看响应变化
│ ├─ 改成明显错误的值看报错
│ └─ 确认它确实是「控制访问哪条数据」的参数
│
├─ 2. 「目标 ID 存在吗?」
│ 检验:你要越权访问的那个 ID 真的存在吗?
│ ├─ 试连续的 ID(如果是数字)
│ ├─ 从应用其他地方找真实 ID
│ └─ 404 和 403 是不同的信号
│
├─ 3. 「被拦在哪一层?」
│ 检验:是应用层还是平台层?
│ ├─ 应用层:可能有逻辑绕过
│ └─ 平台层:试 Header/方法/路径绕过
│
├─ 4. 「响应真的什么都没有吗?」
│ 检验:
│ ├─ 403/302 的 body 里有没有数据?
│ ├─ 响应时间有没有差异?(可能说明查了数据)
│ └─ 有没有其他信息泄露?
│
└─ 5. 「角色/Session 对吗?」
检验:
├─ 你是用哪个账号测的?
├─ Cookie/Token 是当前用户的吗?
└─ 有没有混用不同账号的凭证?
卡关自查清单
□ URL 参数、POST body、Cookie、Header 里的 ID 都测了吗?
□ robots.txt 看了吗?
□ 页面 JS 源码搜过敏感路径吗?
□ 不同 HTTP 方法都试了吗?
□ X-Original-URL / X-Rewrite-URL 试了吗?
□ 路径大小写、结尾斜杠、扩展名都试了吗?
□ 多步骤流程的每一步都抓包分析了吗?
□ Referer 头试着伪造了吗?
□ 403/302 响应的 body 仔细看了吗?
□ 应用里有没有其他地方泄露了目标用户的 ID/GUID?
通用怪坑
| 坑 | 症状 | 为什么想不到 | 避坑方法 |
|---|
| Session 混乱 | 换账号测试但结果不变 | 浏览器缓存了 Cookie | 用隐私模式/不同浏览器 |
| ID 类型不匹配 | 改 ID 没反应 | 数字 ID 和字符串 ID 混了 | 观察原始格式,保持一致 |
| 需要完整流程 | 直接请求某步骤失败 | 服务端检查了流程状态 | 先正常走一遍,记录每步参数 |
本漏洞特有怪坑
| 坑 | 症状 | 为什么想不到 | 避坑方法 |
|---|
| 302 里藏数据 | 被重定向了以为失败 | 习惯只看最终页面 | Burp 里看原始响应 |
| GUID 在评论里 | 找不到其他用户 ID | 只关注账户相关页面 | 全站浏览,注意任何用户引用 |
| Header 绕过要配合根路径 | X-Original-URL 没生效 | 没把请求路径改成 / | 路径设 /,敏感路径放 Header |
| 多步骤最后一步需要特定参数 | 跳步请求返回错误 | 没分析完整流程 | 先正常走一遍,抓取所有参数 |
F. 自测问题
📋 做完 Lab 后用这些问题检验自己
概念理解
- 垂直越权 vs 水平越权,一句话区别?
→ 答不上来:回看 A-3 子类型族谱
- 为什么「隐藏 URL」不是真正的访问控制?
→ 说不清:回看 A-2 漏洞原理
- IDOR 和访问控制漏洞是什么关系?
→ 搞不清:IDOR 是访问控制漏洞的一个子类型
实战能力
- 给你一个 /myaccount?id=123 的 URL,你会做哪些测试?
→ 说不出 3 种以上:回看 C-Layer1
- 遇到 403 被拦了,你会尝试哪些绕过方向?
→ 说不出 3 种以上:回看 C-Layer2
- 怎么找到应用里隐藏的管理功能 URL?
→ 只能说「猜」:回看 B 触发点
- 多步骤流程漏洞怎么测?
→ 说不清步骤:回看 C-Layer3
思维检验
- 你做题时遇到的最坑的点是什么?
→ 想不起来:做题时养成记录习惯
- 如果 ID 是 GUID 猜不到,你会怎么办?
→ 只说「没办法」:回看 D 思维演示
G. 延伸
同类漏洞关联
| 相关漏洞 | 共同点 | 差异点 |
|---|
| 认证漏洞 | 都涉及「谁能做什么」 | 认证=你是谁;访问控制=你能做什么 |
| 业务逻辑漏洞 | 都是逻辑层面问题 | 访问控制更聚焦权限;业务逻辑更广泛 |
| SSRF | 都可能让你访问不该访问的东西 | SSRF 是让服务器帮你访问;访问控制是你直接访问 |
进阶方向(Practitioner 通关后可探索)
- Expert 级 Lab:涉及更复杂的 OAuth 流程、JWT 篡改
- 真实场景:API 网关的权限配置、微服务间的信任边界
- 工具进阶:Autorize(Burp 扩展)自动化检测越权
- 深入阅读:OWASP Broken Access Control、API Security Top 10
✅ 输出前自检确认
☑ 一句话定义 + 办公楼类比能让零基础 2 分钟内建立直觉
☑ 触发点表格覆盖了功能/参数/现象三个维度
☑ Layer1 讲的是「怎么想」而不是具体 payload
☑ Layer2 绕过讲的是思考方向(Header/方法/路径)
☑ 思维演示包含「403→检查响应body→发现数据」的调整过程
☑ 常见错误包含「只看状态码」「GUID就安全」等真实误区
☑ 排错流程可以系统诊断「测不动」的问题
☑ 怪坑包含「302里藏数据」「Header要配合根路径」等反直觉点
☑ 无任何 Lab 名称/编号/具体解法剧透