performing-api-fuzzing-with-restler
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePerforming API Fuzzing with RESTler
使用RESTler进行API模糊测试
When to Use
适用场景
- Performing automated security testing of REST APIs using their OpenAPI/Swagger specifications
- Discovering bugs that only manifest through specific sequences of API calls (stateful testing)
- Finding 500 Internal Server Error responses that indicate unhandled exceptions or crash conditions
- Testing API input validation by fuzzing parameters with malformed, boundary, and injection payloads
- Running continuous security regression testing in CI/CD pipelines for API changes
Do not use against production environments without explicit authorization and monitoring. RESTler creates and deletes resources aggressively during fuzzing.
- 借助OpenAPI/Swagger规范对REST API执行自动化安全测试
- 发现仅在特定API调用序列下才会显现的漏洞(有状态测试)
- 排查指示未处理异常或崩溃情况的500内部服务器错误响应
- 通过向参数输入畸形、边界值和注入Payload来测试API的输入验证能力
- 在CI/CD流水线中针对API变更运行持续安全回归测试
注意:未经明确授权和监控,请勿在生产环境中使用。RESTler在模糊测试过程中会大量创建和删除资源。
Prerequisites
前置条件
- Written authorization specifying the target API and acceptable testing scope
- Python 3.12+ and .NET 8.0 runtime installed
- RESTler downloaded from https://github.com/microsoft/restler-fuzzer
- OpenAPI/Swagger specification (v2 or v3) for the target API
- API authentication credentials (tokens, API keys, or OAuth credentials)
- Isolated test/staging environment (RESTler can create thousands of resources per hour)
- 针对目标API及可测试范围的书面授权
- 已安装Python 3.12+和.NET 8.0运行时
- 已从https://github.com/microsoft/restler-fuzzer下载RESTler
- 目标API的OpenAPI/Swagger规范(v2或v3版本)
- API认证凭据(令牌、API密钥或OAuth凭据)
- 隔离的测试/预发布环境(RESTler每小时可创建数千个资源)
Workflow
工作流程
Step 1: RESTler Installation and Setup
步骤1:RESTler安装与设置
bash
undefinedbash
undefinedClone and build RESTler
克隆并构建RESTler
git clone https://github.com/microsoft/restler-fuzzer.git
cd restler-fuzzer
git clone https://github.com/microsoft/restler-fuzzer.git
cd restler-fuzzer
Build RESTler
构建RESTler
python3 ./build-restler.py --dest_dir /opt/restler
python3 ./build-restler.py --dest_dir /opt/restler
Verify installation
验证安装
/opt/restler/restler/Restler --help
/opt/restler/restler/Restler --help
Alternative: Use pre-built release
替代方案:使用预构建版本
Download from https://github.com/microsoft/restler-fuzzer/releases
undefinedundefinedStep 2: Compile the API Specification
步骤2:编译API规范
bash
undefinedbash
undefinedCompile the OpenAPI spec into a RESTler fuzzing grammar
将OpenAPI规范编译为RESTler模糊测试语法
/opt/restler/restler/Restler compile
--api_spec /path/to/openapi.yaml
--api_spec /path/to/openapi.yaml
/opt/restler/restler/Restler compile
--api_spec /path/to/openapi.yaml
--api_spec /path/to/openapi.yaml
Output directory structure:
输出目录结构:
Compile/
Compile/
grammar.py - Generated fuzzing grammar
grammar.py - 生成的模糊测试语法
grammar.json - Grammar in JSON format
grammar.json - JSON格式的语法文件
dict.json - Custom dictionary for fuzzing values
dict.json - 用于模糊测试的自定义字典
engine_settings.json - Engine configuration
engine_settings.json - 引擎配置文件
config.json - Compilation config
config.json - 编译配置文件
**Custom dictionary for targeted fuzzing (dict.json):**
```json
{
"restler_fuzzable_string": [
"fuzzstring",
"' OR '1'='1",
"\" OR \"1\"=\"1",
"<script>alert(1)</script>",
"../../../etc/passwd",
"${7*7}",
"{{7*7}}",
"a]UNION SELECT 1,2,3--",
"\"; cat /etc/passwd; echo \"",
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
],
"restler_fuzzable_int": [
"0",
"-1",
"999999999",
"2147483647",
"-2147483648"
],
"restler_fuzzable_bool": ["true", "false", "null", "1", "0"],
"restler_fuzzable_datetime": [
"2024-01-01T00:00:00Z",
"0000-00-00T00:00:00Z",
"9999-12-31T23:59:59Z",
"invalid-date"
],
"restler_fuzzable_uuid4": [
"00000000-0000-0000-0000-000000000000",
"aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
],
"restler_custom_payload": {
"/users/{userId}": ["1", "0", "-1", "admin", "' OR 1=1--"],
"/orders/{orderId}": ["1", "0", "999999999"]
}
}
**用于定向模糊测试的自定义字典(dict.json):**
```json
{
"restler_fuzzable_string": [
"fuzzstring",
"' OR '1'='1",
"\" OR \"1\"=\"1",
"<script>alert(1)</script>",
"../../../etc/passwd",
"${7*7}",
"{{7*7}}",
"a]UNION SELECT 1,2,3--",
"\"; cat /etc/passwd; echo \"",
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
],
"restler_fuzzable_int": [
"0",
"-1",
"999999999",
"2147483647",
"-2147483648"
],
"restler_fuzzable_bool": ["true", "false", "null", "1", "0"],
"restler_fuzzable_datetime": [
"2024-01-01T00:00:00Z",
"0000-00-00T00:00:00Z",
"9999-12-31T23:59:59Z",
"invalid-date"
],
"restler_fuzzable_uuid4": [
"00000000-0000-0000-0000-000000000000",
"aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
],
"restler_custom_payload": {
"/users/{userId}": ["1", "0", "-1", "admin", "' OR 1=1--"],
"/orders/{orderId}": ["1", "0", "999999999"]
}
}Step 3: Configure Authentication
步骤3:配置认证
python
undefinedpython
undefinedauthentication_token.py - RESTler authentication module
authentication_token.py - RESTler认证模块
import requests
import json
import time
class AuthenticationProvider:
def init(self):
self.token = None
self.token_expiry = 0
self.auth_url = "https://target-api.example.com/api/v1/auth/login"
self.credentials = {
"email": "fuzzer@test.com",
"password": "FuzzerPass123!"
}
def get_token(self):
"""Get or refresh authentication token."""
current_time = time.time()
if self.token and current_time < self.token_expiry - 60:
return self.token
resp = requests.post(self.auth_url, json=self.credentials)
if resp.status_code == 200:
data = resp.json()
self.token = data["access_token"]
self.token_expiry = current_time + 3600 # Assume 1-hour TTL
return self.token
else:
raise Exception(f"Authentication failed: {resp.status_code}")
def get_auth_header(self):
"""Return the authentication header for RESTler."""
token = self.get_token()
return f"Authorization: Bearer {token}"import requests
import json
import time
class AuthenticationProvider:
def init(self):
self.token = None
self.token_expiry = 0
self.auth_url = "https://target-api.example.com/api/v1/auth/login"
self.credentials = {
"email": "fuzzer@test.com",
"password": "FuzzerPass123!"
}
def get_token(self):
"""获取或刷新认证令牌。"""
current_time = time.time()
if self.token and current_time < self.token_expiry - 60:
return self.token
resp = requests.post(self.auth_url, json=self.credentials)
if resp.status_code == 200:
data = resp.json()
self.token = data["access_token"]
self.token_expiry = current_time + 3600 # 假设令牌有效期为1小时
return self.token
else:
raise Exception(f"认证失败: {resp.status_code}")
def get_auth_header(self):
"""返回供RESTler使用的认证头。"""
token = self.get_token()
return f"Authorization: Bearer {token}"Export the token refresh command for RESTler
导出供RESTler使用的令牌刷新命令
auth = AuthenticationProvider()
print(auth.get_auth_header())
**Engine settings for authentication (engine_settings.json):**
```json
{
"authentication": {
"token": {
"token_refresh_interval": 300,
"token_refresh_cmd": "python3 /path/to/authentication_token.py"
}
},
"max_combinations": 20,
"max_request_execution_time": 30,
"global_producer_timing_delay": 2,
"no_ssl": false,
"host": "target-api.example.com",
"target_port": 443,
"garbage_collection_interval": 300,
"max_sequence_length": 10
}auth = AuthenticationProvider()
print(auth.get_auth_header())
**用于认证的引擎设置(engine_settings.json):**
```json
{
"authentication": {
"token": {
"token_refresh_interval": 300,
"token_refresh_cmd": "python3 /path/to/authentication_token.py"
}
},
"max_combinations": 20,
"max_request_execution_time": 30,
"global_producer_timing_delay": 2,
"no_ssl": false,
"host": "target-api.example.com",
"target_port": 443,
"garbage_collection_interval": 300,
"max_sequence_length": 10
}Step 4: Run RESTler in Test Mode (Smoke Test)
步骤4:以测试模式运行RESTler(冒烟测试)
bash
undefinedbash
undefinedTest mode: Quick validation that all endpoints are reachable
测试模式:快速验证所有端点是否可达
/opt/restler/restler/Restler test
--grammar_file Compile/grammar.py
--dictionary_file Compile/dict.json
--settings Compile/engine_settings.json
--no_ssl
--target_ip target-api.example.com
--target_port 443
--grammar_file Compile/grammar.py
--dictionary_file Compile/dict.json
--settings Compile/engine_settings.json
--no_ssl
--target_ip target-api.example.com
--target_port 443
/opt/restler/restler/Restler test
--grammar_file Compile/grammar.py
--dictionary_file Compile/dict.json
--settings Compile/engine_settings.json
--no_ssl
--target_ip target-api.example.com
--target_port 443
--grammar_file Compile/grammar.py
--dictionary_file Compile/dict.json
--settings Compile/engine_settings.json
--no_ssl
--target_ip target-api.example.com
--target_port 443
Review test results
查看测试结果
cat Test/ResponseBuckets/runSummary.json
```pythoncat Test/ResponseBuckets/runSummary.json
```pythonParse test results
解析测试结果
import json
with open("Test/ResponseBuckets/runSummary.json") as f:
summary = json.load(f)
print("Test Mode Summary:")
print(f" Total requests: {summary.get('total_requests_sent', {}).get('num_requests', 0)}")
print(f" Successful (2xx): {summary.get('num_fully_valid', 0)}")
print(f" Client errors (4xx): {summary.get('num_invalid', 0)}")
print(f" Server errors (5xx): {summary.get('num_server_error', 0)}")
import json
with open("Test/ResponseBuckets/runSummary.json") as f:
summary = json.load(f)
print("测试模式总结:")
print(f" 总请求数: {summary.get('total_requests_sent', {}).get('num_requests', 0)}")
print(f" 成功请求(2xx): {summary.get('num_fully_valid', 0)}")
print(f" 客户端错误(4xx): {summary.get('num_invalid', 0)}")
print(f" 服务器错误(5xx): {summary.get('num_server_error', 0)}")
Identify uncovered endpoints
识别未覆盖的端点
covered = summary.get('covered_endpoints', [])
total = summary.get('total_endpoints', [])
uncovered = set(total) - set(covered)
if uncovered:
print(f"\nUncovered endpoints ({len(uncovered)}):")
for ep in uncovered:
print(f" - {ep}")
undefinedcovered = summary.get('covered_endpoints', [])
total = summary.get('total_endpoints', [])
uncovered = set(total) - set(covered)
if uncovered:
print(f"\n未覆盖端点({len(uncovered)}):")
for ep in uncovered:
print(f" - {ep}")
undefinedStep 5: Run Fuzz-Lean Mode
步骤5:运行Fuzz-Lean模式
bash
undefinedbash
undefinedFuzz-lean: One pass through all endpoints with security checkers enabled
Fuzz-lean模式:遍历所有端点并启用安全检查器
/opt/restler/restler/Restler fuzz-lean
--grammar_file Compile/grammar.py
--dictionary_file Compile/dict.json
--settings Compile/engine_settings.json
--target_ip target-api.example.com
--target_port 443
--time_budget 1 # 1 hour max
--grammar_file Compile/grammar.py
--dictionary_file Compile/dict.json
--settings Compile/engine_settings.json
--target_ip target-api.example.com
--target_port 443
--time_budget 1 # 1 hour max
/opt/restler/restler/Restler fuzz-lean
--grammar_file Compile/grammar.py
--dictionary_file Compile/dict.json
--settings Compile/engine_settings.json
--target_ip target-api.example.com
--target_port 443
--time_budget 1 # 最长1小时
--grammar_file Compile/grammar.py
--dictionary_file Compile/dict.json
--settings Compile/engine_settings.json
--target_ip target-api.example.com
--target_port 443
--time_budget 1 # 最长1小时
Checkers automatically enabled in fuzz-lean:
Fuzz-lean模式下自动启用的检查器:
- UseAfterFree: Tests accessing resources after deletion
- UseAfterFree: 测试资源删除后的访问情况
- NamespaceRule: Tests accessing resources across namespaces/tenants
- NamespaceRule: 测试跨命名空间/租户的资源访问
- ResourceHierarchy: Tests child resources with wrong parent IDs
- ResourceHierarchy: 测试使用错误父ID的子资源
- LeakageRule: Tests for information disclosure in error responses
- LeakageRule: 测试错误响应中的信息泄露
- InvalidDynamicObject: Tests with malformed dynamic object IDs
- InvalidDynamicObject: 测试使用畸形动态对象ID的情况
undefinedundefinedStep 6: Run Full Fuzzing Mode
步骤6:运行完整模糊测试模式
bash
undefinedbash
undefinedFull fuzz mode: Extended fuzzing for comprehensive coverage
完整模糊测试模式:扩展模糊测试以实现全面覆盖
/opt/restler/restler/Restler fuzz
--grammar_file Compile/grammar.py
--dictionary_file Compile/dict.json
--settings Compile/engine_settings.json
--target_ip target-api.example.com
--target_port 443
--time_budget 4
--enable_checkers UseAfterFree NamespaceRule ResourceHierarchy LeakageRule InvalidDynamicObject PayloadBody
--grammar_file Compile/grammar.py
--dictionary_file Compile/dict.json
--settings Compile/engine_settings.json
--target_ip target-api.example.com
--target_port 443
--time_budget 4
--enable_checkers UseAfterFree NamespaceRule ResourceHierarchy LeakageRule InvalidDynamicObject PayloadBody
/opt/restler/restler/Restler fuzz
--grammar_file Compile/grammar.py
--dictionary_file Compile/dict.json
--settings Compile/engine_settings.json
--target_ip target-api.example.com
--target_port 443
--time_budget 4
--enable_checkers UseAfterFree NamespaceRule ResourceHierarchy LeakageRule InvalidDynamicObject PayloadBody
--grammar_file Compile/grammar.py
--dictionary_file Compile/dict.json
--settings Compile/engine_settings.json
--target_ip target-api.example.com
--target_port 443
--time_budget 4
--enable_checkers UseAfterFree NamespaceRule ResourceHierarchy LeakageRule InvalidDynamicObject PayloadBody
Analyze fuzzing results
分析模糊测试结果
python3 <<'EOF'
import json
import os
results_dir = "Fuzz/ResponseBuckets"
bugs_dir = "Fuzz/bug_buckets"
python3 <<'EOF'
import json
import os
results_dir = "Fuzz/ResponseBuckets"
bugs_dir = "Fuzz/bug_buckets"
Parse bug buckets
解析漏洞分类文件
if os.path.exists(bugs_dir):
for bug_file in os.listdir(bugs_dir):
if bug_file.endswith(".txt"):
with open(os.path.join(bugs_dir, bug_file)) as f:
content = f.read()
print(f"\n=== Bug: {bug_file} ===")
print(content[:500])
if os.path.exists(bugs_dir):
for bug_file in os.listdir(bugs_dir):
if bug_file.endswith(".txt"):
with open(os.path.join(bugs_dir, bug_file)) as f:
content = f.read()
print(f"\n=== 漏洞: {bug_file} ===")
print(content[:500])
Parse response summary
解析响应总结
summary_file = os.path.join(results_dir, "runSummary.json")
if os.path.exists(summary_file):
with open(summary_file) as f:
summary = json.load(f)
print(f"\nFuzz Summary:")
print(f" Duration: {summary.get('time_budget_hours', 0)} hours")
print(f" Total requests: {summary.get('total_requests_sent', {}).get('num_requests', 0)}")
print(f" Bugs found: {summary.get('num_bugs', 0)}")
print(f" 500 errors: {summary.get('num_server_error', 0)}")
EOF
undefinedsummary_file = os.path.join(results_dir, "runSummary.json")
if os.path.exists(summary_file):
with open(summary_file) as f:
summary = json.load(f)
print(f"\n模糊测试总结:")
print(f" 持续时间: {summary.get('time_budget_hours', 0)} 小时")
print(f" 总请求数: {summary.get('total_requests_sent', {}).get('num_requests', 0)}")
print(f" 发现漏洞数: {summary.get('num_bugs', 0)}")
print(f" 500错误数: {summary.get('num_server_error', 0)}")
EOF
undefinedKey Concepts
核心概念
| Term | Definition |
|---|---|
| Stateful Fuzzing | API fuzzing that maintains state across requests by using responses from earlier requests as inputs to later ones, enabling testing of multi-step workflows |
| Producer-Consumer Dependencies | RESTler's inference that a value produced by one API call (e.g., a created resource ID) should be consumed by a subsequent call |
| Fuzzing Grammar | Compiled representation of the API specification that defines how to generate valid and invalid requests for each endpoint |
| Checker | RESTler security rule that tests for specific vulnerability patterns like use-after-free, namespace isolation, or information leakage |
| Bug Bucket | RESTler's categorization of discovered bugs by type and endpoint, grouping similar failures for efficient triage |
| Garbage Collection | RESTler's periodic cleanup of resources created during fuzzing to prevent resource exhaustion on the target system |
| 术语 | 定义 |
|---|---|
| 有状态模糊测试 | 跨请求维护状态的API模糊测试,将早期请求的响应作为后续请求的输入,支持多步骤工作流测试 |
| 生产者-消费者依赖关系 | RESTler推断出的依赖关系:某个API调用生成的值(如创建的资源ID)应被后续调用使用 |
| 模糊测试语法 | API规范的编译表示,定义如何为每个端点生成有效和无效的请求 |
| 检查器 | RESTler的安全规则,用于测试特定漏洞模式,如释放后使用、命名空间隔离或信息泄露 |
| 漏洞分类 | RESTler按类型和端点对发现的漏洞进行分类,将类似故障分组以提高排查效率 |
| 垃圾回收 | RESTler定期清理模糊测试过程中创建的资源,以防止目标系统资源耗尽 |
Tools & Systems
工具与系统
- RESTler: Microsoft Research's stateful REST API fuzzing tool that compiles OpenAPI specs into fuzzing grammars
- Schemathesis: Property-based API testing tool that generates test cases from OpenAPI/GraphQL schemas
- Dredd: API testing tool that validates API implementations against OpenAPI/API Blueprint documentation
- Fuzz-lightyear: Yelp's stateless API fuzzer focused on finding authentication and authorization vulnerabilities
- API Fuzzer: OWASP tool for API endpoint fuzzing with customizable payload dictionaries
- RESTler: 微软研究院开发的有状态REST API模糊测试工具,可将OpenAPI规范编译为模糊测试语法
- Schemathesis: 基于属性的API测试工具,从OpenAPI/GraphQL schema生成测试用例
- Dredd: API测试工具,验证API实现是否符合OpenAPI/API Blueprint文档
- Fuzz-lightyear: Yelp开发的无状态API模糊测试工具,专注于发现认证与授权漏洞
- API Fuzzer: OWASP推出的API端点模糊测试工具,支持自定义Payload字典
Common Scenarios
常见场景
Scenario: Microservice API Fuzzing Campaign
场景:微服务API模糊测试活动
Context: A fintech company has 12 microservice APIs with OpenAPI specifications. Before a major release, the security team runs RESTler fuzzing against each service in the staging environment to catch bugs.
Approach:
- Collect OpenAPI specs for all 12 services and compile each into a RESTler grammar
- Configure authentication for each service with service-specific credentials
- Run test mode on each service to validate endpoint reachability and fix grammar issues
- Run fuzz-lean mode (1 hour per service) to identify quick wins
- Find 23 bugs in fuzz-lean mode: 8 unhandled 500 errors, 5 use-after-free patterns, 4 namespace isolation failures, 6 information leakage in error responses
- Run full fuzz mode (4 hours per service) on the 5 services with the most bugs
- Discover 47 additional bugs including a critical authentication bypass where deleting a user and reusing their token still allows access
- Generate bug reports and track remediation through JIRA integration
Pitfalls:
- Running RESTler against production without understanding that it creates and deletes thousands of resources
- Not configuring authentication correctly, causing RESTler to only test unauthenticated access
- Using the default dictionary without adding application-specific injection payloads
- Not setting a time budget, allowing RESTler to run indefinitely
- Ignoring the compilation warnings that indicate endpoints RESTler cannot reach due to dependency issues
背景: 某金融科技公司拥有12个带OpenAPI规范的微服务API。在重大版本发布前,安全团队在预发布环境中对每个服务运行RESTler模糊测试以排查漏洞。
实施步骤:
- 收集所有12个服务的OpenAPI规范,并将每个规范编译为RESTler语法
- 为每个服务配置专属的认证凭据
- 在每个服务上运行测试模式,验证端点可达性并修复语法问题
- 运行fuzz-lean模式(每个服务1小时)以快速发现明显漏洞
- 在fuzz-lean模式下发现23个漏洞:8个未处理500错误、5个释放后使用模式、4个命名空间隔离失败、6个错误响应中的信息泄露
- 对漏洞最多的5个服务运行完整模糊测试模式(每个服务4小时)
- 额外发现47个漏洞,包括一个严重的认证绕过漏洞:删除用户后复用其令牌仍可访问系统
- 生成漏洞报告并通过JIRA集成跟踪修复进度
常见误区:
- 在未了解RESTler会创建和删除数千个资源的情况下,直接在生产环境中运行
- 未正确配置认证,导致RESTler仅测试未认证的访问路径
- 使用默认字典而未添加针对应用的注入Payload
- 未设置时间预算,导致RESTler无限期运行
- 忽略编译警告,这些警告通常表示RESTler因依赖问题无法访问某些端点
Output Format
输出格式
undefinedundefinedRESTler API Fuzzing Report
RESTler API模糊测试报告
Target: User Service API (staging.example.com)
Specification: OpenAPI 3.0 (42 endpoints)
Duration: 4 hours (full fuzz mode)
Total Requests: 145,832
目标: 用户服务API (staging.example.com)
规范: OpenAPI 3.0 (42个端点)
持续时间: 4小时(完整模糊测试模式)
总请求数: 145,832
Bug Summary
漏洞总结
| Category | Count | Severity |
|---|---|---|
| 500 Internal Server Error | 12 | High |
| Use After Free | 3 | Critical |
| Namespace Rule Violation | 5 | Critical |
| Information Leakage | 8 | Medium |
| Resource Leak | 4 | Low |
| 分类 | 数量 | 严重程度 |
|---|---|---|
| 500内部服务器错误 | 12 | 高 |
| 释放后使用 | 3 | 严重 |
| 命名空间规则违反 | 5 | 严重 |
| 信息泄露 | 8 | 中 |
| 资源泄漏 | 4 | 低 |
Critical Findings
严重发现
1. Use-After-Free: Deleted user token still valid
- Sequence: POST /users -> DELETE /users/{id} -> GET /users/{id}
- After deleting user, GET with the deleted user's token returns 200
- Impact: Deleted accounts can still access the API
2. Namespace Violation: Cross-tenant data access
- Sequence: POST /users (tenant A) -> GET /users/{id} (tenant B token)
- User created by tenant A is accessible with tenant B's credentials
- Impact: Multi-tenant isolation breach
3. 500 Error: Unhandled integer overflow
- Request: POST /orders {"quantity": 2147483648}
- Response: 500 Internal Server Error with stack trace
- Impact: DoS potential, information disclosure via stack trace
1. 释放后使用:已删除用户的令牌仍有效
- 调用序列: POST /users -> DELETE /users/{id} -> GET /users/{id}
- 删除用户后,使用该用户的令牌发起GET请求返回200状态码
- 影响: 已删除的账户仍可访问API
2. 命名空间违规:跨租户数据访问
- 调用序列: POST /users(租户A)-> GET /users/{id}(租户B令牌)
- 租户A创建的用户可被租户B的凭据访问
- 影响: 多租户隔离机制失效
3. 500错误:未处理的整数溢出
- 请求: POST /orders {"quantity": 2147483648}
- 响应: 500内部服务器错误并返回堆栈跟踪
- 影响: 存在拒绝服务风险,堆栈跟踪可能导致信息泄露
Coverage
覆盖范围
- Endpoints covered: 38/42 (90.5%)
- Uncovered: POST /admin/migrate, DELETE /admin/cache, PUT /config/advanced, POST /webhooks/test
undefined- 已覆盖端点: 38/42 (90.5%)
- 未覆盖端点: POST /admin/migrate, DELETE /admin/cache, PUT /config/advanced, POST /webhooks/test
undefined