access-control-testing
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAccess Control Testing (FIND/EXPLOIT — OWASP A01)
访问控制测试(查找/利用——OWASP A01)
Overview
概述
Verify that every object and every action enforces "is this caller allowed?" server-side.
Broken access control is the most common and highest-impact real-world flaw — and the easiest
to miss because the happy path works perfectly.
Core principle: Authentication proves who you are; authorization proves what you may do.
Test the second one on every object and every action — not just the UI-visible ones.
验证每个对象和每个操作是否在服务端强制执行“该调用者是否有权限?”
访问控制失效是现实世界中最常见、影响最大的缺陷——而且最容易
被忽略,因为正常路径完全正常。
核心原则: 身份验证证明你是谁;授权证明你可以做什么。
测试后者时,应覆盖每个对象和每个操作——不仅仅是 UI 可见的那些。
Applies when / Skip when
适用场景 / 跳过场景
- Applies when: the app has authentication, multiple users, roles, or multi-tenant data — any resource or action that should be restricted. (Almost every non-trivial app.)
- Skip when: the app is fully public/anonymous with no per-user or privileged data → N/A.
- If N/A: report "access-control-testing: N/A — no auth/multi-user surface" and stop. Don't invent access boundaries that don't exist.
- 适用场景: 应用具有身份验证、多用户、角色或多租户数据—— 任何应受限制的资源或操作。(几乎所有非平凡应用。)
- 跳过场景: 应用完全公开/匿名,没有每用户或特权数据 → 不适用。
- 如果不适用: 报告“access-control-testing: N/A — no auth/multi-user surface”并停止。不要 虚构不存在的访问边界。
⚠️ Authorization
⚠️ 授权
Use test accounts you created on an app you own/are authorized to test. Two accounts (A and B)
plus one admin/one low-priv account is the cleanest setup.
使用您在自己拥有/被授权测试的应用上创建的测试账户。两个账户(A 和 B)
外加一个管理员/一个低权限账户是最干净的设置。
The test matrix (run every cell)
测试矩阵(运行每个单元格)
| Read | Write/Update | Delete | Admin action | |
|---|---|---|---|---|
| As another user (horizontal) | A reads B's object? | A edits B's? | A deletes B's? | — |
| As lower privilege (vertical) | user hits admin read? | user hits admin write? | — | user invokes admin fn? |
| Unauthenticated | no token → data? | no token → mutate? | — | no token → admin? |
If any cell succeeds, that's a finding.
| 读取 | 写入/更新 | 删除 | 管理员操作 | |
|---|---|---|---|---|
| 作为另一用户(水平) | A 读取 B 的对象? | A 编辑 B 的? | A 删除 B 的? | — |
| 作为更低权限(垂直) | 用户访问管理员读取? | 用户访问管理员写入? | — | 用户调用管理员功能? |
| 未认证 | 无令牌 → 数据? | 无令牌 → 修改? | — | 无令牌 → 管理员? |
如果任何单元格成功,那就是一个发现。
Method
方法
- Capture a legitimate request as user A (note every id, uuid, slug, filename).
- Swap the object reference to B's resource, keep A's session → IDOR/BOLA.
- Swap the session (remove token / use lower-priv token) on privileged endpoints → BFLA / vertical.
- Force-browse hidden routes (,
/admin) with a normal account./api/internal - Mass assignment — add fields the UI never sends (,
role,isAdmin,userId).price - Check every method — may be guarded but
GET/PUT/DELETEforgotten.PATCH
See for concrete request recipes and edge cases.
references/access-control-tests.md- 捕获一个合法请求作为用户 A(记录每个 id、uuid、slug、文件名)。
- 交换对象引用为 B 的资源,保留 A 的会话 → IDOR/BOLA。
- 交换会话(移除令牌/使用更低权限的令牌)在特权端点上 → BFLA / 垂直。
- 强制浏览隐藏路由(、
/admin)使用普通账户。/api/internal - 批量赋值——添加 UI 从不发送的字段(、
role、isAdmin、userId)。price - 检查每个方法——可能受到保护,但
GET/PUT/DELETE被遗忘。PATCH
参见 获取具体的请求配方和边界情况。
references/access-control-tests.mdQuick reference — bug classes
快速参考——漏洞类别
| Class | Test |
|---|---|
| IDOR / BOLA | Change an id/uuid/filename to another user's; do you get their data? |
| Horizontal privesc | Act on another same-level user's resources. |
| Vertical privesc | Low-priv account reaches admin function/data. |
| BFLA | Admin endpoint guarded in UI but callable directly by anyone. |
| Multi-tenant break | Tenant A reads tenant B (swap |
| Mass assignment | Inject privileged fields into the request body. |
| Forced browsing | Guess/enumerate unlinked privileged routes. |
| 类别 | 测试 |
|---|---|
| IDOR / BOLA | 将 id/uuid/文件名改为另一个用户的;你能获取他们的数据吗? |
| 水平权限提升 | 操作另一个同级用户的资源。 |
| 垂直权限提升 | 低权限账户访问管理员功能/数据。 |
| BFLA | 管理员端点在 UI 中受保护,但任何人都可直接调用。 |
| 多租户突破 | 租户 A 读取租户 B(交换 |
| 批量赋值 | 向请求体中注入特权字段。 |
| 强制浏览 | 猜测/枚举未链接的特权路由。 |
Output
输出
Findings in the register: which account hit which endpoint/object, the exact swapped request,
what was exposed, and horizontal vs vertical. Severity is almost always High+.
在注册表中记录发现:哪个账户访问了哪个端点/对象、确切的交换请求、
暴露了什么,以及水平还是垂直。严重性几乎总是高+。
Hand-off
交接
Confirmed on a running app → reproduce via ; chain with others in
; fix via (deny-by-default, server-side checks).
active-pentestvulnerability-chainingsecurity-hardening在运行中的应用上确认 → 通过 复现;在
中与其他问题链接;通过 (默认拒绝、服务端检查)修复。
active-pentestvulnerability-chainingsecurity-hardeningCommon mistakes
常见错误
- Testing only as admin — you'll never see the bug. Always test as the lower privilege.
- Trusting that a hidden/unlinked endpoint is safe — enumerate and call it directly.
- Checking only — mutations are where damage happens.
GET - Assuming UUIDs are safe — they leak (in responses, logs, referrers) and are still IDOR-able.
- Forgetting predictable patterns: sequential ids, base64'd ids, guessable filenames.
- 仅以管理员身份测试——你永远不会看到问题。始终以更低权限测试。
- 相信隐藏/未链接的端点是安全的——枚举并直接调用它。
- 只检查 ——修改操作才是造成损害的地方。
GET - 假设 UUID 是安全的——它们会泄漏(在响应、日志、引用者中),并且仍然可能被 IDOR。
- 忘记可预测模式:连续 id、base64 编码的 id、可猜测的文件名。