access-control-testing

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Access 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)

测试矩阵(运行每个单元格)

ReadWrite/UpdateDeleteAdmin 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?
Unauthenticatedno token → data?no token → mutate?—no token → admin?
If any cell succeeds, that's a finding.
读取写入/更新删除管理员操作
作为另一用户(水平)A 读取 B 的对象?A 编辑 B 的?A 删除 B 的?—
作为更低权限(垂直)用户访问管理员读取?用户访问管理员写入?—用户调用管理员功能?
未认证无令牌 → 数据?无令牌 → 修改?—无令牌 → 管理员?
如果任何单元格成功,那就是一个发现。

Method

方法

  1. Capture a legitimate request as user A (note every id, uuid, slug, filename).
  2. Swap the object reference to B's resource, keep A's session → IDOR/BOLA.
  3. Swap the session (remove token / use lower-priv token) on privileged endpoints → BFLA / vertical.
  4. Force-browse hidden routes (
    /admin
    ,
    /api/internal
    ) with a normal account.
  5. Mass assignment — add fields the UI never sends (
    role
    ,
    isAdmin
    ,
    userId
    ,
    price
    ).
  6. Check every method —
    GET
    may be guarded but
    PUT
    /
    DELETE
    /
    PATCH
    forgotten.
See
references/access-control-tests.md
for concrete request recipes and edge cases.
  1. 捕获一个合法请求作为用户 A(记录每个 id、uuid、slug、文件名)。
  2. 交换对象引用为 B 的资源,保留 A 的会话 → IDOR/BOLA。
  3. 交换会话(移除令牌/使用更低权限的令牌)在特权端点上 → BFLA / 垂直。
  4. 强制浏览隐藏路由(
    /admin
    、
    /api/internal
    )使用普通账户。
  5. 批量赋值——添加 UI 从不发送的字段(
    role
    、
    isAdmin
    、
    userId
    、
    price
    )。
  6. 检查每个方法——
    GET
    可能受到保护,但
    PUT
    /
    DELETE
    /
    PATCH
    被遗忘。
参见
references/access-control-tests.md
获取具体的请求配方和边界情况。

Quick reference — bug classes

快速参考——漏洞类别

ClassTest
IDOR / BOLAChange an id/uuid/filename to another user's; do you get their data?
Horizontal privescAct on another same-level user's resources.
Vertical privescLow-priv account reaches admin function/data.
BFLAAdmin endpoint guarded in UI but callable directly by anyone.
Multi-tenant breakTenant A reads tenant B (swap
org_id
/
tenant_id
).
Mass assignmentInject privileged fields into the request body.
Forced browsingGuess/enumerate unlinked privileged routes.
类别测试
IDOR / BOLA将 id/uuid/文件名改为另一个用户的;你能获取他们的数据吗?
水平权限提升操作另一个同级用户的资源。
垂直权限提升低权限账户访问管理员功能/数据。
BFLA管理员端点在 UI 中受保护,但任何人都可直接调用。
多租户突破租户 A 读取租户 B(交换
org_id
/
tenant_id
)。
批量赋值向请求体中注入特权字段。
强制浏览猜测/枚举未链接的特权路由。

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
active-pentest
; chain with others in
vulnerability-chaining
; fix via
security-hardening
(deny-by-default, server-side checks).
在运行中的应用上确认 → 通过
active-pentest
复现;在
vulnerability-chaining
中与其他问题链接;通过
security-hardening
(默认拒绝、服务端检查)修复。

Common 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
    GET
    only — mutations are where damage happens.
  • 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、可猜测的文件名。