API 安全测试

某金融公司在上线新版 API 前,进行了例行的功能测试和性能测试。系统上线一周后,安全团队在例行审计中发现,有大量异常请求尝试访问管理员接口。原来攻击者通过 API 文档发现了几个被遗忘的旧版本接口,这些接口没有任何权限校验。

事后复盘发现,如果在上线前进行过一次完整的安全测试,这个漏洞本可以避免。功能测试验证的是「功能是否正常工作」,而安全测试验证的是「功能在异常情况下是否还能正常工作」。两者同等重要,但很多团队只做了前者。

一、API 安全测试方法论

测试金字塔

API 安全测试应该遵循测试金字塔原则:

flowchart TB
    subgraph Top["安全测试金字塔"]
        PT[渗透测试<br/>Penetration Testing<br/>少量、高价值]
        SAST[安全代码审计<br/>Code Review<br/>中量]
        DAST[动态扫描<br/>DAST/Fuzzing<br/>大量、自动化]
    end
    
    style PT fill:#ffcccc
    style SAST fill:#ffffcc
    style DAST fill:#ccffcc
层级方法覆盖率成本时机
基础层自动化扫描、Fuzzing每次构建
中间层安全代码审查、SAST每次提交
顶层渗透测试上线前

测试覆盖维度

完整的 API 安全测试应该覆盖以下维度:

维度测试内容典型工具
认证安全Token 强度、会话管理、密码策略Burp Suite、OWASP ZAP
授权安全越权访问、权限绕过Postman、自定义脚本
输入验证注入攻击、XSS、格式校验Fuzzer、SQL Map
业务逻辑绕过验证、负数金额、时间旅行手工测试、API 模拟
速率限制暴力破解、资源耗尽JMeter、Locust
敏感数据数据泄露、加密传输Burp Suite、mitmproxy

二、手工测试

手工测试虽然效率低,但能发现自动化工具难以检测的业务逻辑漏洞。

认证绕过测试

# 测试场景:尝试绕过身份验证

# 1. 空 Token
GET /api/v1/users/me
Authorization: Bearer

# 2. 伪造 Token(使用已知密钥签名)
GET /api/v1/users/me
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

# 3. 删除 Token 头部
GET /api/v1/users/me
Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

# 4. 使用已撤销的 Token
GET /api/v1/users/me
Authorization: Bearer <revoked_token>

# 5. 测试认证失败后的响应
POST /api/v1/auth/login
Content-Type: application/json

{"username":"admin","password":"wrongpassword"}

越权访问测试(IDOR)

# 测试场景:失效的对象级授权

# 1. 尝试访问他人资源
GET /api/v1/orders/12345
Authorization: Bearer <user_a_token>

# 2. 修改资源 ID,尝试越权
GET /api/v1/orders/12346
Authorization: Bearer <user_a_token>

# 3. 尝试负数 ID
GET /api/v1/orders/-1
Authorization: Bearer <user_a_token>

# 4. 尝试数组 ID(批量访问)
GET /api/v1/orders/[1,2,3,4,5]
Authorization: Bearer <user_a_token>

# 5. 尝试模糊 ID
GET /api/v1/orders/12*
Authorization: Bearer <user_a_token>

# 6. 尝试特殊字符
GET /api/v1/orders/' OR '1'='1
Authorization: Bearer <user_a_token>

# 7. 修改响应包提升权限
GET /api/v1/users/me
# 响应: {"role": "user"}

# 修改为
PUT /api/v1/users/me
{"role": "admin"}

SQL 注入测试

# 测试场景:SQL 注入攻击

# 1. 基础注入测试
GET /api/v1/users?search=' OR '1'='1
GET /api/v1/users?search=admin'--

# 2. UNION 注入
GET /api/v1/users?search=' UNION SELECT null,username,password,null FROM users--

# 3. 布尔盲注
GET /api/v1/users?search=admin' AND 1=1--
GET /api/v1/users?search=admin' AND 1=2--

# 4. 时间盲注
GET /api/v1/users?search=admin' AND SLEEP(5)--

# 5. JSON 参数注入
POST /api/v1/search
Content-Type: application/json

{"query": "admin'--"}
{"query": "admin\"; DROP TABLE users;--"}

参数污染测试

# 测试场景:HTTP 参数污染

# 同一参数多次提交
GET /api/v1/users?id=1&id=2&id=3
GET /api/v1/users?id=1,2,3
GET /api/v1/users?id[]=1&id[]=2

# JSON 和表单参数混合
POST /api/v1/users
Content-Type: application/x-www-form-urlencoded

username=admin&data={"role":"admin"}

# 大小写混淆
GET /api/v1/ADMIN/users
GET /api/v1/users/ADMIN

三、自动化测试工具

Postman + Newman

Postman 是最流行的 API 测试工具,结合 Newman 可以实现自动化:

Postman
{
  "info": {
    "name": "API Security Tests",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    {
      "key": "baseUrl",
      "value": "https://api.example.com"
    }
  ],
  "item": [
    {
      "name": "认证绕过测试",
      "event": [
        {
          "listen": "test",
          "script": {
            "exec": [
              "pm.test('应返回401认证失败', function() {",
              "    pm.response.to.have.status(401);",
              "});",
              "",
              "pm.test('不应泄露用户信息', function() {",
              "    var jsonData = pm.response.json();",
              "    pm.expect(jsonData).to.not.have.property('username');",
              "    pm.expect(jsonData).to.not.have.property('email');",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "GET",
        "url": "{{baseUrl}}/api/v1/users/me",
        "header": []
      }
    },
    {
      "name": "越权访问测试",
      "event": [
        {
          "listen": "test",
          "script": {
            "exec": [
              "pm.test('不应访问其他用户的订单', function() {",
              "    var jsonData = pm.response.json();",
              "    // 检查返回的订单不属于当前用户",
              "    if (jsonData.orderId !== pm.collectionVariables.get('userOrderId')) {",
              "        pm.expect.fail('检测到越权访问漏洞');",
              "    }",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "GET",
        "url": "{{baseUrl}}/api/v1/orders/{{otherUserOrderId}}",
        "header": [
          {
            "key": "Authorization",
            "value": "Bearer {{userToken}}"
          }
        ]
      }
    }
  ]
}
Newman
# 安装 Newman
npm install -g newman

# 运行安全测试集合
newman run security-tests.postman_collection.json \
  --environment prod-env.json \
  --reporters cli,junit \
  --reporter-junit-export output/results.xml

# 失败时返回非零退出码
if [ $? -ne 0 ]; then
  echo "安全测试失败,阻止部署"
  exit 1
fi

OWASP ZAP

OWASP Zed Attack Proxy 是免费的开源 Web 安全扫描器:

ZAP
# 使用 Docker 运行 ZAP
docker run -t owasp/zap2docker-stable zap-api-scan.py \
  -t https://api.example.com/openapi.json \
  -f openapi \
  -r report.html

# 基础认证和 Bearer Token
docker run -t owasp/zap2docker-stable zap-api-scan.py \
  -t https://api.example.com/swagger.yaml \
  -f openapi \
  -z "-config api.addheader.Authorization='Bearer {{token}}'" \
  -r report.html

# 使用 CI 模式
docker run -t owasp/zap2docker-stable zap-full-scan.py \
  -t https://api.example.com \
  -J zap-report.json \
  --context /zap/wrk/context.context

Burp Suite

Burp Suite 是专业渗透测试工具:

Burp
# 使用 Burp Scanner 进行 API 扫描
java -jar burpsuite_pro.jar \
  --project-file=api-test.b旭 \
  --dependency-check=false \
  --target-file=targets.txt

# 与 CI 集成
# 导出 Burp 报告
docker run --rm -v $(pwd):/output \
  portswigger/burp-api-scan \
  --api-url https://api.example.com/swagger.json \
  --output /output/burp-report.html

四、Fuzzing 测试

Fuzzing 通过生成大量畸形输入来发现潜在漏洞:

Fuzzing 策略

策略原理适用场景
随机 Fuzz随机生成输入快速发现崩溃
字典 Fuzz基于已知关键词生成注入类漏洞
协议 Fuzz基于协议规范生成协议解析漏洞
生成式 Fuzz基于语法生成有效输入结构化数据漏洞
进化式 Fuzz根据反馈优化输入高覆盖率

API Fuzzing 实现

API
public class ApiFuzzer {
    
    private final RestTemplate restTemplate;
    private final PayloadGenerator generator;
    private final VulnerabilityReporter reporter;
    
    /**
     * Fuzzing 测试入口
     */
    public FuzzingReport fuzz(String baseUrl, ApiEndpoint endpoint) {
        FuzzingReport report = new FuzzingReport(endpoint);
        
        // 1. 获取 API 规范
        OpenApiSpec spec = loadApiSpec(baseUrl);
        
        // 2. 对每个端点进行 Fuzzing
        for (Operation operation : spec.getOperations(endpoint)) {
            List<FuzzingResult> results = fuzzOperation(
                baseUrl, operation
            );
            report.addResults(operation, results);
        }
        
        return report;
    }
    
    /**
     * 对单个操作进行 Fuzzing
     */
    private List<FuzzingResult> fuzzOperation(String baseUrl, Operation operation) {
        List<FuzzingResult> results = new ArrayList<>();
        
        // 1. Fuzz 每个参数
        for (Parameter param : operation.getParameters()) {
            results.addAll(fuzzParameter(baseUrl, operation, param));
        }
        
        // 2. Fuzz 请求体
        if (operation.getRequestBody() != null) {
            results.addAll(fuzzRequestBody(baseUrl, operation));
        }
        
        // 3. Fuzz HTTP 头
        results.addAll(fuzzHeaders(baseUrl, operation));
        
        return results;
    }
    
    /**
     * Fuzz 字符串参数
     */
    private List<FuzzingResult> fuzzParameter(String baseUrl, 
                                               Operation operation,
                                               Parameter param) {
        List<FuzzingResult> results = new ArrayList<>();
        
        // SQL 注入 payloads
        List<String> sqlPayloads = List.of(
            "' OR '1'='1",
            "' OR '1'='1' --",
            "'; DROP TABLE users;--",
            "1' AND '1'='1",
            "admin'--"
        );
        
        // XSS payloads
        List<String> xssPayloads = List.of(
            "<script>alert(1)</script>",
            "javascript:alert(1)",
            "<img src=x onerror=alert(1)>",
            "{{constructor.constructor('alert(1)')()}}"
        );
        
        // 命令注入 payloads
        List<String> cmdPayloads = List.of(
            "; ls",
            "| cat /etc/passwd",
            "`whoami`",
            "$(whoami)"
        );
        
        // 长字符串测试
        List<String> overflowPayloads = List.of(
            "A".repeat(1000),
            "A".repeat(10000),
            "A".repeat(100000)
        );
        
        for (String payload : sqlPayloads) {
            FuzzingResult result = sendFuzzedRequest(
                baseUrl, operation, param, payload, VulnerabilityType.SQL_INJECTION
            );
            if (result.isVulnerable()) {
                results.add(result);
            }
        }
        
        // ... 对其他 payload 类型的处理类似
        
        return results;
    }
    
    /**
     * 发送 Fuzzed 请求
     */
    private FuzzingResult sendFuzzedRequest(String baseUrl, 
                                            Operation operation,
                                            Parameter param,
                                            String payload,
                                            VulnerabilityType type) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put(param.getName(), payload);
            
            ResponseEntity<String> response = restTemplate.exchange(
                buildUrl(baseUrl, operation, params),
                HttpMethod.valueOf(operation.getMethod().toUpperCase()),
                buildHttpEntity(operation, params),
                String.class
            );
            
            // 分析响应判断是否漏洞
            return analyzeResponse(operation, param, payload, response, type);
            
        } catch (Exception e) {
            // 异常可能表示发现了漏洞
            return FuzzingResult.vulnerable(
                operation, param, payload, type, e.getMessage()
            );
        }
    }
    
    private FuzzingResult analyzeResponse(Operation operation,
                                          Parameter param,
                                          String payload,
                                          ResponseEntity<String> response,
                                          VulnerabilityType type) {
        
        String body = response.getBody();
        int statusCode = response.getStatusCode().value();
        
        switch (type) {
            case SQL_INJECTION:
                // 检查 SQL 错误信息泄露
                if (body != null && (
                    body.contains("SQL syntax") ||
                    body.contains("mysql_fetch") ||
                    body.contains("ORA-") ||
                    body.contains("SQLServer")
                )) {
                    return FuzzingResult.vulnerable(
                        operation, param, payload, type, 
                        "SQL 错误信息泄露"
                    );
                }
                break;
                
            case XSS:
                // 检查输入是否被反射
                if (body != null && body.contains(payload)) {
                    // 检查是否有编码或转义
                    if (!isProperlyEscaped(body, payload)) {
                        return FuzzingResult.vulnerable(
                            operation, param, payload, type,
                            "输入未经过滤直接反射"
                        );
                    }
                }
                break;
        }
        
        return FuzzingResult.notVulnerable(operation, param, payload, type);
    }
}

使用 FFUF 进行 API Fuzzing

FFUF
# 安装
go install github.com/ffuf/ffuf@latest

# 目录和参数 Fuzzing
ffuf -w wordlists/api-paths.txt \
  -u https://api.example.com/api/v1/FUZZ \
  -H "Authorization: Bearer $TOKEN" \
  -mc 200,401,403 \
  -o results.json

# 参数值 Fuzzing
ffuf -w wordlists/sql-injection.txt \
  -u "https://api.example.com/api/v1/users?id=FUZZ" \
  -H "Authorization: Bearer $TOKEN" \
  -mr "SQL syntax" \
  -o sqli-results.json

# JSON body Fuzzing
ffuf -w wordlists/fuzzing.txt \
  -u https://api.example.com/api/v1/search \
  -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query":"FUZZ"}' \
  -mr "error\|exception\|traceback" \
  -o fuzz-results.json

五、渗透测试流程

渗透测试阶段

flowchart LR
    subgraph Recon["情报收集"]
        R1[API 发现]
        R2[端点枚举]
        R3[指纹识别]
    end
    
    subgraph Analyze["分析与建模"]
        A1[请求分析]
        A2[参数识别]
        A3[认证机制分析]
    end
    
    subgraph Exploit["漏洞利用"]
        E1[注入测试]
        E2[越权测试]
        E3[认证绕过]
    end
    
    subgraph Report["报告"]
        RP1[漏洞记录]
        RP2[风险评估]
        RP3[修复建议]
    end
    
    Recon --> Analyze --> Exploit --> Report

情报收集

API
# 1. 发现 API 文档
# robots.txt
curl https://api.example.com/robots.txt

# Swagger/OpenAPI
curl https://api.example.com/swagger.json
curl https://api.example.com/api-docs

# 2. 枚举 API 版本
curl https://api.example.com/api/v1/health
curl https://api.example.com/api/v2/health
curl https://api.example.com/api/v3/health

# 3. 指纹识别
curl -I https://api.example.com/api/v1/users
# 检查 Server、CORS、认证头

# 4. GraphQL 探测
curl -X POST https://api.example.com/graphql \
  -H "Content-Type: application/json" \
  -d '{"query":"{__schema{types{name}}}"}'

漏洞利用

越权漏洞利用脚本
public class IDORExploiter {
    
    /**
     * 测试批量 IDOR
     */
    public List<IDORFinding> testBulkIDOR(String baseUrl, String token, 
                                          int startId, int endId) {
        List<IDORFinding> findings = new ArrayList<>();
        RestTemplate client = new RestTemplate();
        
        HttpHeaders headers = new HttpHeaders();
        headers.setBearerAuth(token);
        
        for (int id = startId; id <= endId; id++) {
            try {
                ResponseEntity<String> response = client.exchange(
                    baseUrl + "/orders/" + id,
                    HttpMethod.GET,
                    new HttpEntity<>(headers),
                    String.class
                );
                
                if (response.getStatusCode().value() == 200) {
                    // 成功访问到他人资源
                    findings.add(new IDORFinding(
                        id,
                        response.getBody(),
                        determineSeverity(response)
                    ));
                }
            } catch (Exception e) {
                // 忽略错误
            }
        }
        
        return findings;
    }
    
    /**
     * 测试参数篡改
     */
    public IDORFinding testParameterTampering(String baseUrl, String token) {
        RestTemplate client = new RestTemplate();
        
        HttpHeaders headers = new HttpHeaders();
        headers.setBearerAuth(token);
        
        // 原始请求:更新自己的邮箱
        Map<String, Object> originalBody = Map.of(
            "email", "attacker@example.com"
        );
        
        // 尝试更新其他用户的邮箱
        Map<String, Object> tamperedBody = Map.of(
            "email", "attacker@example.com",
            "userId", 12345  // 篡改用户 ID
        );
        
        ResponseEntity<String> response = client.exchange(
            baseUrl + "/users/me",
            HttpMethod.PUT,
            new HttpEntity<>(tamperedBody, headers),
            String.class
        );
        
        if (response.getStatusCode().value() == 200) {
            // 验证是否真的修改了他人邮箱
            ResponseEntity<User> victimResponse = client.exchange(
                baseUrl + "/users/12345",
                HttpMethod.GET,
                new HttpEntity<>(headers),
                User.class
            );
            
            if ("attacker@example.com".equals(victimResponse.getBody().getEmail())) {
                return new IDORFinding(12345, true);
            }
        }
        
        return IDORFinding.notVulnerable();
    }
}

六、CI/CD 集成

安全测试集成到流水线

.gitlab-ci.yml
stages:
  - test
  - security
  - deploy

variables:
  ZAP_API_TARGET: "https://api.example.com/swagger.json"

# 单元测试
unit-tests:
  stage: test
  script:
    - mvn test
  coverage: '/TOTAL.* ([0-9]{1,3})%/'

# 安全测试
api-security-scan:
  stage: security
  image: owasp/zap2docker-stable:latest
  script:
    - zap-api-scan.py -t $ZAP_API_TARGET -f openapi -r zap_report.html
    - zap-baseline.py -t https://api.example.com -J zap_baseline.json
  artifacts:
    reports:
      security: zap_report.html
    paths:
      - zap_report.html
      - zap_baseline.json
    expire_in: 30 days
  allow_failure: true  # 允许扫描失败,不阻塞部署

# Fuzzing 测试
api-fuzzing:
  stage: security
  image: maven:3.8-openjdk-17
  script:
    - mvn exec:java -Dfuzz.skip=false
  artifacts:
    reports:
      junit: target/fuzzing-results.xml
    paths:
      - target/fuzzing-results.json
  only:
    - schedules  # 定期执行,不阻塞每次部署

# 渗透测试(仅在 scheduled pipelines)
penetration-test:
  stage: security
  image: Kali
  script:
    - export BURP_KEY=$BURP_API_KEY
    - python3 burp_scanner.py --target api.example.com --output report.html
  artifacts:
    paths:
      - report.html
  only:
    - schedules
  when: manual

GitHub Actions 集成

.github/workflows/security-test.yml
name: API Security Tests

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
  schedule:
    - cron: '0 2 * * *'  # 每天凌晨执行

jobs:
  zap-scan:
    name: ZAP API Scan
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Run ZAP Scan
        uses: zaproxy/action-api-scan@v0.7.0
        with:
          target: 'https://api.example.com/openapi.json'
          token: ${{ secrets.ZAP_API_KEY }}
      
      - name: Upload Report
        uses: actions/upload-artifact@v4
        with:
          name: zap-report
          path: zap_report.html
      
      - name: Fail on High Vulnerabilities
        if: ${{ github.event_name == 'pull_request' }}
        run: |
          HIGH_COUNT=$(cat zap_report.json | jq '.site[0].alerts | map(select(.riskdesc | contains("High"))) | length')
          if [ "$HIGH_COUNT" -gt 0 ]; then
            echo "发现 $HIGH_COUNT 个高危漏洞"
            exit 1
          fi

  fuzzing:
    name: API Fuzzing
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: '17'
      
      - name: Run Fuzzing
        run: mvn exec:java -Dfuzz.skip=false
      
      - name: Upload Fuzzing Results
        uses: actions/upload-artifact@v4
        with:
          name: fuzzing-results
          path: target/fuzzing-results.json

七、测试环境 vs 生产环境

维度测试环境生产环境
数据脱敏的测试数据真实用户数据
权限可开启调试模式安全模式
限流宽松限制严格限制
影响可接受破坏性测试禁止破坏性测试
监控完整日志受限日志
工具所有工具可用有限工具
警告

在生产环境进行任何安全测试前,必须获得明确的书面授权。未授权的安全测试在很多司法管辖区属于违法行为。

八、安全测试报告

安全测试报告生成
public class SecurityTestReport {
    
    private String projectName;
    private String environment;
    private List<Vulnerability> vulnerabilities;
    private List<SecurityMetric> metrics;
    private LocalDateTime scanTime;
    
    public String generateMarkdown() {
        StringBuilder report = new StringBuilder();
        
        report.append("# API 安全测试报告\n\n");
        report.append("**项目**: ").append(projectName).append("\n");
        report.append("**环境**: ").append(environment).append("\n");
        report.append("**扫描时间**: ").append(scanTime).append("\n\n");
        
        // 执行摘要
        report.append("## 执行摘要\n\n");
        report.append(generateExecutiveSummary()).append("\n\n");
        
        // 漏洞统计
        report.append("## 漏洞统计\n\n");
        report.append(generateVulnerabilityStats()).append("\n\n");
        
        // 漏洞详情
        report.append("## 漏洞详情\n\n");
        for (Vulnerability vuln : vulnerabilities) {
            report.append(generateVulnerabilitySection(vuln)).append("\n\n");
        }
        
        // 修复建议
        report.append("## 修复建议\n\n");
        report.append(generateRemediationPlan()).append("\n\n");
        
        return report.toString();
    }
    
    private String generateVulnerabilitySection(Vulnerability vuln) {
        return String.format("""
            ### %s (%s)
            
            **严重程度**: %s
            
            **发现时间**: %s
            
            **影响**: 
            %s
            
            **复现步骤**:
            %s
            
            **修复建议**:
            %s
            """,
            vuln.getTitle(),
            vuln.getCweId(),
            vuln.getSeverity(),
            vuln.getDiscoveredAt(),
            vuln.getImpact(),
            vuln.getReproductionSteps(),
            vuln.getRemediation()
        );
    }
}

思考题

问题 1:在 API 安全测试中,如何区分「真正的漏洞」和「误报」?哪些测试结果应该引起重视,哪些可能是误报?

参考答案

判断真正漏洞 vs 误报的标准:

  1. 可复现性

    • 真正的漏洞:多次请求都能触发相同结果
    • 误报:偶发性触发,通常是竞态条件或环境问题
  2. 上下文分析

    • 真正的漏洞:攻击者能从中获取非法利益
    • 误报:看似异常但实际无害
  3. 危害评估

    • 真正的漏洞:有明确的安全影响
    • 误报:没有实际危害或无法利用
  4. 具体判断示例

    • SQL 注入:需要验证数据库是否真的被影响,而非仅检测到 SQL 语法
    • XSS:需要验证脚本是否真的被执行,而非仅检测到反射
    • 越权访问:需要验证是否真的访问到他人的私密数据
  5. 验证步骤

    • 使用不同的 payload 重试
    • 在测试环境完整复现
    • 分析响应数据的实际含义
    • 评估攻击的可行性和影响范围

问题 2:自动化安全测试工具(如 ZAP、Burp Suite)的扫描结果应该如何处理?哪些漏洞可以自动修复,哪些需要人工干预?

参考答案

扫描结果处理策略:

可自动修复的漏洞

  1. 配置类漏洞

    • 缺少安全响应头(X-Frame-Options、CSP)
    • CORS 配置过于宽松
    • 调试模式未关闭
    • 版本信息泄露
  2. 简单输入验证

    • 缺少参数长度限制
    • 缺少字符类型校验
  3. 低风险告警

    • 信息泄露(如详细的错误信息)
    • 自动添加到 ignore list

需要人工干预的漏洞

  1. 业务逻辑漏洞

    • 越权访问(需要理解业务上下文)
    • 业务流程绕过(需要完整流程分析)
    • 认证机制缺陷(需要深入分析)
  2. 复杂注入

    • 嵌套注入
    • 编码绕过
    • 上下文敏感的注入
  3. 架构设计问题

    • 加密算法选择
    • 密钥管理方案
    • 整体安全架构

建议流程

  1. 自动化工具扫描
  2. 自动修复低风险配置问题
  3. 安全工程师审查所有发现
  4. 对真正漏洞进行优先级排序
  5. 制定修复计划并跟踪
  6. 修复后重新测试验证