使用 Anthropic-Cybersecurity-Skills 检测与测试 OWASP API3:2023 对象属性级授权缺陷(BOPLA)
2026/9/12 2:46:01 网站建设 项目流程

使用 Anthropic-Cybersecurity-Skills 检测与测试 OWASP API3:2023 对象属性级授权缺陷(BOPLA)

【免费下载链接】Anthropic-Cybersecurity-Skills817 structured cybersecurity skills for AI agents · Mapped to 6 frameworks: MITRE ATT&CK, NIST CSF 2.0, MITRE ATLAS, D3FEND, NIST AI RMF & MITRE F3 (Fight Fraud) · agentskills.io standard · Works with Claude Code, GitHub Copilot, Codex CLI, Cursor, Gemini CLI & 20+ platforms · 29 security domains · Apache 2.0项目地址: https://gitcode.com/GitHub_Trending/an/Anthropic-Cybersecurity-Skills

本指南以 skills/detecting-broken-object-property-level-authorization/SKILL.md 为核心,系统讲解 Broken Object Property Level Authorization(BOPLA,OWASP API Security Top 10 2023 版 API3:2023)的检测方法论、自动化测试工具与修复方案。读者将掌握如何通过 Excessive Data Exposure 与 Mass Assignment 两类缺陷模式,识别 API 响应中过度暴露的敏感字段、请求体中可注入的越权属性,并能直接运行仓库提供的扫描器对目标接口进行批量验证与告警输出。

一、BOPLA 是什么:对象级授权之外的第二道缺口

BOPLA(Broken Object Property Level Authorization)是 OWASP API Security Top 10 中 API3:2023 的分类,它合并了两类紧密相关的漏洞家族:

缺陷类别核心描述
Excessive Data Exposure(过度数据暴露)API 返回的响应属性超出客户端实际需要,敏感字段虽然不在 UI 中展示,却完整传输给了调用方
Mass Assignment(批量赋值)API 不加过滤地把客户端提交的数据绑定到内部对象属性,导致攻击者可写入本无权限修改的字段

对应的 CWE 编号在 references/api-reference.md 中有明确归类:CWE-213(因策略不一致导致敏感信息暴露)与CWE-915(对动态确定的对象属性控制不当)。

BOPLA 的关键在于:即使 API 正确地实现了对象级授权(用户只能访问属于自己的对象),它仍可能在属性级上失守——用户能读取对象上不该读的字段,或写入对象上不该写的字段。攻击者正是利用这一差异,从 API 响应中读取敏感属性,或向请求体中注入额外属性来修改无权触碰的字段。

在本仓库的 MITRE ATT&CK 映射中(见 SKILL.md 的 front matter),该技能关联了T1190(利用面向公网的应用程序漏洞)、T1213(从信息系统中收集数据)与T1212(利用工具/机制漏洞),同时映射了 NIST CSF 2.0 的PR.PS-01 / ID.RA-01 / PR.DS-10 / DE.CM-01控制项,说明它既可用于攻击面评估(ID.RA-01),也可指导安全监控覆盖的验证(DE.CM-01)。

二、适用场景与前置条件

适用场景

  • 安全事件调查中需要检测对象属性级授权缺陷时
  • 为这一领域编写检测规则或威胁狩猎查询时
  • SOC 分析人员需要结构化分析流程时
  • 验证安全监控对相关攻击技术的覆盖有效性时

前置条件

  • 提供或接受对象数据的目标 API 端点
  • API 文档或 schema(优先使用 OpenAPI 规范)
  • 用于请求改写的 Burp Suite 或 Postman
  • 多个不同权限级别的用户账号(普通用户与管理员账号对比尤为关键)
  • Python 3.8+ 环境,并安装requests库用于自动化测试
  • 具备开展安全测试的合法授权(未经授权对他人系统进行测试可能违反计算机欺诈相关法律)

三、漏洞模式剖析:两类缺陷的典型形态

3.1 Excessive Data Exposure:响应中多出来的字段

GET /api/v1/users/123返回下述 JSON 时,UI 实际只展示idusernamename,而响应中携带了大量敏感字段:

{ "id": 123, "username": "john_doe", "email": "john@example.com", "name": "John Doe", "ssn": "123-45-6789", // Sensitive - not needed by UI "salary": 95000, // Sensitive - not needed by UI "internal_notes": "VIP client", // Internal - should not be exposed "password_hash": "$2b$12...", // Critical - never expose "role": "admin", // May enable privilege discovery "created_by": "system_admin", // Internal metadata "credit_card_last4": "4242" // PCI compliance violation }

这里的核心认知是:前端过滤不等于安全。客户端把多余字段隐藏掉,但完整响应在网络上可被任意拦截与读取,安全性为零。仓库中另一份关联技能 exploiting-excessive-data-exposure-in-api/SKILL.md 对此有更细化的操作流程(UI 展示字段与 API 实际返回字段的差异对比、响应头与错误响应中的调试信息泄露检测),可与此技能配合使用。

3.2 Mass Assignment:请求体中注入的越权属性

当更新接口把请求体直接绑定到 ORM 对象时,攻击者可以附加字段:

// Normal user update request PUT /api/v1/users/123 Content-Type: application/json { "name": "John Updated", "email": "new@example.com", "role": "admin", // Attacker-injected: privilege escalation "is_verified": true, // Attacker-injected: bypass verification "discount_rate": 100, // Attacker-injected: business logic abuse "account_balance": 999999 // Attacker-injected: financial fraud }
  • role: "admin"直接造成权限提升
  • is_verified: true绕过验证流程
  • discount_rate/account_balance则构成业务逻辑滥用金融欺诈

关于这一缺陷的专门利用方法论(含 Rails/Django/Laravel/Spring 等 ORM 自动绑定框架下的参数发现技术),仓库中还有一份 exploiting-mass-assignment-in-rest-apis/SKILL.md 可作为深入补充。

四、自动化测试方法论:BOPLA 扫描器完整实现

SKILL.md 内置了一套完整的BOPLAScanner类,用 Python 实现两类缺陷的自动化测试。它同时被 scripts/agent.py 封装为可直接运行的 CLI 工具。

4.1 核心数据结构与字典表

扫描器先定义两个关键数据源:

  • 敏感属性模式字典SENSITIVE_PROPERTY_PATTERNS:按严重级别分级(CRITICAL / HIGH / MEDIUM / LOW),用于对响应中出现但未被预期的字段进行敏感性归类。CRITICAL 级包含passwordpassword_hashsecrettokenapi_keyprivate_keyaccess_tokenrefresh_token;HIGH 级包含ssncredit_cardcvvbank_account等金融数据;MEDIUM 级包含salaryinternal_notesroleis_adminsession_id等权限与内部元数据;LOW 级包含phoneaddressdate_of_birth等个人资料。

  • 批量赋值测试载荷MASS_ASSIGNMENT_FIELDS:一组(字段名, 注入值)组合,覆盖权限(role=adminis_admin=True)、验证状态(is_verified=Trueemail_verified=True)、账户类型(account_type=premiumsubscription_tier=enterprise)、财务字段(discount_rate=100credit_limit=999999account_balance=999999)与权限列表(permissions=[...])等典型目标。

4.2 过度数据暴露检测:test_excessive_data_exposure

该函数对目标端点发起 GET 请求,将实际响应字段与调用方提供的expected_fields(期望字段集合)做差集运算:

def test_excessive_data_exposure(self, endpoint: str, expected_fields: Set[str]) -> List[BOPLAFinding]: """Test if API response contains more fields than expected.""" findings = [] url = f"{self.base_url}{endpoint}" try: response = requests.get(url, headers=self.auth_headers, timeout=10) if response.status_code != 200: return findings data = response.json() # Handle both single object and list responses objects = data if isinstance(data, list) else [data] if isinstance(data, dict) and "data" in data: objects = data["data"] if isinstance(data["data"], list) else [data["data"]] for obj in objects[:5]: # Check first 5 objects if not isinstance(obj, dict): continue response_fields = set(self._flatten_keys(obj)) unexpected_fields = response_fields - expected_fields for field_name in unexpected_fields: severity = self._classify_sensitivity(field_name) if severity: finding = BOPLAFinding( endpoint=endpoint, method="GET", vulnerability_type="excessive_exposure", severity=severity, property_name=field_name, details=f"Unexpected sensitive field '{field_name}' in response" ) findings.append(finding) self.findings.append(finding) except (requests.exceptions.RequestException, json.JSONDecodeError): pass return findings

实现要点:

  • 单对象与列表统一处理:既兼容data为数组或单字典的情况,也兼容{"data": [...]}的常见分页包装格式;
  • 最多取前 5 个对象:避免对超大规模列表响应造成不必要的请求开销;
  • 递归展平嵌套键_flatten_keys方法把嵌套对象转换为a.b.c形式的点分路径,确保深层嵌套对象中的敏感字段(如user.profile.ssn)不会被漏掉;
  • 敏感性分级_classify_sensitivity取字段名最后一段(去掉前缀)做子串匹配,命中即返回对应的严重级别,未命中返回None从而跳过无害字段。

4.3 批量赋值检测:test_mass_assignment

该函数先 GET 获取对象当前状态作为基线,再逐一对MASS_ASSIGNMENT_FIELDS中的字段做注入测试,并在注入成功后通过再次 GET 校验字段确实被修改,随后尽可能恢复原值,避免破坏测试环境:

def test_mass_assignment(self, endpoint: str, method: str = "PUT", original_data: Optional[dict] = None) -> List[BOPLAFinding]: """Test if API accepts and processes additional injected properties.""" findings = [] url = f"{self.base_url}{endpoint}" # First, get the current object state if original_data is None: try: response = requests.get(url, headers=self.auth_headers, timeout=10) if response.status_code == 200: original_data = response.json() else: original_data = {} except (requests.exceptions.RequestException, json.JSONDecodeError): original_data = {} # Test each mass assignment field for field_name, injected_value in self.MASS_ASSIGNMENT_FIELDS: if field_name in original_data: # Field exists - test if we can modify it original_value = original_data[field_name] if original_value == injected_value: continue # Already has this value test_data = deepcopy(original_data) test_data[field_name] = injected_value headers = {**self.auth_headers, "Content-Type": "application/json"} try: if method == "PUT": response = requests.put(url, json=test_data, headers=headers, timeout=10) elif method == "PATCH": response = requests.patch(url, json={field_name: injected_value}, headers=headers, timeout=10) elif method == "POST": response = requests.post(url, json=test_data, headers=headers, timeout=10) if response.status_code in (200, 201, 204): # Verify the field was actually modified verify_response = requests.get(url, headers=self.auth_headers, timeout=10) if verify_response.status_code == 200: updated_data = verify_response.json() if updated_data.get(field_name) == injected_value: finding = BOPLAFinding( endpoint=endpoint, method=method, vulnerability_type="mass_assignment", severity="CRITICAL" if field_name in ["role", "is_admin", "permissions"] else "HIGH", property_name=field_name, details=f"Successfully injected '{field_name}={injected_value}'" ) findings.append(finding) self.findings.append(finding) # Restore original value if possible if field_name in original_data: restore_data = {field_name: original_data[field_name]} requests.patch(url, json=restore_data, headers=headers, timeout=10) except requests.exceptions.RequestException: continue return findings

关键设计值得注意:

  • HTTP 方法自适应:PUT 发送完整对象(含注入字段);PATCH 只发送单字段载荷(更贴近真实攻击手法);POST 用于创建类接口;
  • 双重确认机制:仅当写请求返回 2xx后续 GET 确认字段值等于注入值时,才判定为漏洞,最大程度降低误报;
  • 严重级别差异化roleis_adminpermissions这类可直接提权的字段标为 CRITICAL,其余财务/状态字段标为 HIGH;
  • 状态回滚:注入成功后如果原对象中存在该字段,会尝试用 PATCH 恢复原值,体现负责任的安全测试实践。

4.4 GraphQL 属性暴露检测:test_graphql_property_exposure

该函数向 GraphQL 端点发送 introspection 内省查询,探测 schema 是否被完整暴露:

def test_graphql_property_exposure(self, graphql_endpoint: str, query: str) -> List[BOPLAFinding]: """Test GraphQL APIs for property-level authorization issues.""" findings = [] url = f"{self.base_url}{graphql_endpoint}" # Introspection query to discover available fields introspection = """ { __schema { types { name fields { name type { name kind } } } } } """ try: response = requests.post( url, json={"query": introspection}, headers=self.auth_headers, timeout=10 ) if response.status_code == 200: data = response.json() if "errors" not in data: finding = BOPLAFinding( endpoint=graphql_endpoint, method="POST", vulnerability_type="excessive_exposure", severity="MEDIUM", property_name="__schema", details="GraphQL introspection enabled - full schema exposed" ) findings.append(finding) self.findings.append(finding) except requests.exceptions.RequestException: pass return findings

GraphQL 内省开关本身就是一张属性级授权地图:攻击者借它枚举出全部类型与字段名,再逐个尝试读取敏感字段。SKILL.md 同时会在内省开启时给出__schema的 MEDIUM 级告警。

4.5 报告聚合:generate_report

扫描结果统一汇总为结构化报告,按漏洞类型(excessive_exposure/mass_assignment)与严重级别(CRITICAL / HIGH / MEDIUM / LOW)分组,并附完整发现列表,可直接喂给 SIEM、缺陷跟踪系统或检测规则生成流程,支撑 DE.CM-01(持续监控)场景下的规则验证。

五、命令行一键扫描:运行 agent.py

scripts/agent.py 将上述类封装为标准 CLI。其参数解析逻辑(main()函数)支持:

  • --base-url(必填):API 基础 URL;
  • --endpoint(必填):待测试端点,如/api/v1/users/1
  • --token:Bearer Token,会自动组装成Authorization请求头;
  • --expected-fields:期望响应字段列表(空格分隔);
  • --test:测试模式,exposure/mass_assignment/both(默认both);
  • --method:批量赋值测试使用的 HTTP 方法,PUT/PATCH/POST(默认PUT)。

典型调用方式(来自 references/api-reference.md):

python skills/detecting-broken-object-property-level-authorization/scripts/agent.py \ --base-url https://api.example.com \ --endpoint /api/v1/users/123 \ --token "eyJhbGciOiJIUzI1NiJ9..." \ --expected-fields id username name email \ --test both --method PUT

运行前需安装依赖:pip install requests(脚本在缺少requests时会明确提示)。脚本输出 JSON 格式的结果,包含findings列表、total_findings计数与by_severity严重级别统计,便于脚本化集成。

同时,若希望将本技能对接到更广泛的攻击面评估或威胁狩猎流程,可参阅仓库 mappings/README.md 了解 MITRE ATT&CK、NIST CSF 等框架的映射组织方式,以及 index.json 中该技能与仓库内其他 API 安全类技能的关联关系。

六、手工验证补充:requests 库与 Burp Suite 技巧

在自动化扫描之外,references/api-reference.md 给出了轻量的手工验证方法:

import requests # GET - test for excessive exposure resp = requests.get(url, headers={"Authorization": f"Bearer {token}"}, timeout=10) resp.status_code # 200, 401, 403 resp.json() # parsed response body # PUT - test for mass assignment resp = requests.put(url, json={"role": "admin"}, headers=headers, timeout=10) # PATCH - test for partial mass assignment resp = requests.patch(url, json={"is_admin": True}, headers=headers, timeout=10)

配套的典型 Mass Assignment 测试载荷:

{"role": "admin"} {"is_admin": true} {"is_verified": true} {"account_type": "premium"} {"discount_rate": 100} {"permissions": ["admin", "write", "delete"]}

Burp Suite 侧推荐组合扩展:

  • Autorize:跨角色测试授权差异(普通用户账号访问管理员功能);
  • Param Miner:发现隐藏参数与可能的可绑定字段;
  • JSON Beautifier:快速检查响应中的属性集合。

七、修复与加固:服务端显式白名单

SKILL.md 给出了对应的服务端修复模式,核心原则是永远不要在响应序列化时直接to_json()/to_dict()整个对象,永远不要让框架把请求体原样绑定到模型

7.1 响应侧:按角色分级字段白名单

# Server-side: Explicit property allowlists class UserSerializer: # Only expose these fields - never use to_json() or to_dict() PUBLIC_FIELDS = ['id', 'username', 'name', 'avatar_url'] OWNER_FIELDS = PUBLIC_FIELDS + ['email', 'phone', 'preferences'] ADMIN_FIELDS = OWNER_FIELDS + ['role', 'created_at', 'last_login'] def serialize(self, user, requesting_user): if requesting_user.is_admin: fields = self.ADMIN_FIELDS elif requesting_user.id == user.id: fields = self.OWNER_FIELDS else: fields = self.PUBLIC_FIELDS return {field: getattr(user, field) for field in fields}

7.2 请求侧:可写字段白名单过滤

# Mass assignment protection - explicit allowlist for writable fields WRITABLE_FIELDS = {'name', 'email', 'phone', 'avatar_url', 'preferences'} def update_user(user_id, request_data, requesting_user): # Filter out any fields not in the allowlist safe_data = {k: v for k, v in request_data.items() if k in WRITABLE_FIELDS} # Apply updates only with safe data User.objects.filter(id=user_id).update(**safe_data)

在 Django REST Framework 中对应的落地方式是显式fields白名单 +read_only_fields声明(见 references/api-reference.md):

# Allowlist serialization (Django REST Framework) class UserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ['id', 'username', 'name'] # explicit allowlist read_only_fields = ['id', 'role', 'is_admin']

八、实战落地建议

综合 SKILL.md 与配套文件,建议按如下闭环落地 BOPLA 检测能力:

  1. 资产清单阶段:梳理所有返回/接收对象数据的端点,收集 OpenAPI 文档作为期望字段基线;
  2. 自动化扫描阶段:为每个端点准备两个权限账号(普通用户 + 管理员),用agent.py分别跑--test both,比较两类账号下的响应差异(普通用户能看到管理员字段即为缺陷);
  3. 手工验证阶段:对自动化告警用 Burp Suite 复测,确认误报并记录可利用性;
  4. 修复阶段:按第七章的响应侧 + 请求侧双白名单模式整改,为敏感字段建立read_only_fieldsWRITABLE_FIELDS约束;
  5. 监控阶段:将扫描结果输出为检测用例,映射到本技能 front matter 中声明的 MITRE ATT&CK 技术(T1190 / T1213 / T1212)与 NIST CSF 控制项,纳入日常监控覆盖验证(DE.CM-01),并通过仓库的 docs/mitre-f3-mapping.md 等映射文档沉淀为组织级检测知识。

需要注意的是,本技能面向已获授权的安全测试场景,所有自动化载荷(尤其是权限字段注入)都应在测试环境或获得书面授权的目标上执行,并在测试后尽量恢复对象原始状态。

【免费下载链接】Anthropic-Cybersecurity-Skills817 structured cybersecurity skills for AI agents · Mapped to 6 frameworks: MITRE ATT&CK, NIST CSF 2.0, MITRE ATLAS, D3FEND, NIST AI RMF & MITRE F3 (Fight Fraud) · agentskills.io standard · Works with Claude Code, GitHub Copilot, Codex CLI, Cursor, Gemini CLI & 20+ platforms · 29 security domains · Apache 2.0项目地址: https://gitcode.com/GitHub_Trending/an/Anthropic-Cybersecurity-Skills

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询