Web API 模糊测试

Web API fuzzing 对 API 操作参数进行模糊测试。模糊测试将操作参数设置为意外值,在 API 后端引起意外行为和错误。这有助于您发现其他 QA 流程可能遗漏的错误和潜在安全问题。

除了极狐GitLab 安全的其他安全扫描器和您自己的测试过程,我们建议您使用模糊测试。如果您使用极狐GitLab CI/CD,您可以运行模糊测试作为 CI/CD 工作流程的一部分。

当 Web API 模糊测试运行时

Web API 模糊测试在 CI/CD 流水线的 fuzz 阶段运行。为确保 API 模糊测试扫描最新代码,您的 CI/CD 流水线应在 fuzz 阶段之前的某个阶段将更改部署到测试环境。

请注意,对 API 模糊测试模板进行了以下更改:

  • 在 14.0 及更高版本,您必须在 .gitlab-ci.yml 文件中定义一个 fuzz 阶段。
  • 在 13.12 及更早版本,API 模糊测试模板定义了 buildtestdeployfuzz 阶段。fuzz 阶段默认最后运行。预定义的阶段已被弃用,并从 API-Fuzzing.latest.gitlab-ci.yml 模板中删除。它们将在未来的极狐GitLab 版本中被删除。

如果您的流水线配置为在每次运行时部署到同一个 Web 服务器,则在另一个流水线仍在运行时运行流水线,可能会导致一个流水线覆盖另一个流水线的代码的竞争条件。在模糊扫描期间,应将要扫描的 API 从更改中排除。API 的唯一更改应该来自模糊扫描器。扫描期间对 API 所做的任何更改(例如,用户、计划任务、数据库更改、代码更改、其他流水线或其他扫描程序)都可能导致不准确的结果。

您可以使用以下方法运行 Web API 模糊扫描:

启用 Web API fuzzing

要求:

  • 以下 Web API 类型之一:
  • REST API
    • SOAP
    • GraphQL
    • 表单正文、JSON 或 XML
  • 提供 API 进行测试的以下资产之一:
    • OpenAPI v2 或 v3 API 定义
    • 要测试的 API 请求的 HTTP 存档 (HAR)
    • Postman 收集 v2.0 或 v2.1
    caution从不对生产服务器运行模糊测试。它不仅可以执行 API 可以执行的任何功能,还可能触发 API 中的错误。包括修改和删除数据等操作。仅对测试服务器运行模糊测试。

要启用 Web API 模糊测试:

在 14.0 及更高版本中,API 模糊测试配置文件必须位于存储库的 .gitlab 目录中,而不是仓库的根目录中。

Web API fuzzing 测试配置表单

引入于 13.10 版本。

API fuzzing 配置表单可帮助您创建或修改项目的 API fuzzing 配置。该表单允许您为最常见的 API 模糊测试选项选择值,并构建一个 YAML 片段,您可以将其粘贴到极狐GitLab CI/CD 配置中。

在 UI 中配置 Web API fuzzing

要生成 API Fuzzing 配置片段:

  1. 在顶部栏上,选择 菜单 > 项目 并找到您的项目。
  2. 在左侧边栏上,选择 安全与合规 > 配置
  3. API Fuzzing 行中,选择 启用 API Fuzzing
  4. 填写字段。有关详细信息,请参阅可用的 CI/CD 变量
  5. 选择 生成代码片段。将打开一个窗口,其中包含与您在表单中选择的选项相对应的 YAML 片段。
  6. 执行以下操作之一:
    1. 要将代码段复制到剪贴板,请选择 仅复制代码
    2. 要将代码段添加到项目的 .gitlab-ci.yml 文件中,请选择 复制代码并打开 .gitlab-ci.yml 文件。流水线编辑器打开。
      1. 将代码段粘贴到 .gitlab-ci.yml 文件中。
      2. 选择 Lint 选项卡以确认编辑的 .gitlab-ci.yml 文件有效。
      3. 选择 编辑 选项卡,然后选择 提交更改

当代码片段提交到 .gitlab-ci.yml 文件时,流水线会包含一个 API Fuzzing 作业。

OpenAPI 规范

  • 对 OpenAPI Specification v3.0 的支持引入于 13.9 版本。
  • 对使用 YAML 格式的 OpenAPI Specification 的支持引入于 14.0 版本。
  • 对 OpenAPI Specification v3.1 的支持引入于 14.2 版本.
  • 对生成媒体类型 application/xml 的支持引入于 14.8 版本。
  • 对选择媒体的支持引入于 14.10 版本。

OpenAPI 规范(以前称为 Swagger 规范)是 REST API 的 API 描述格式。本节向您展示如何使用 OpenAPI 规范配置 API 模糊测试,以提供有关要测试的目标 API 的信息。 OpenAPI 规范作为文件系统资源或 URL 提供。支持 JSON 和 YAML OpenAPI 格式。

API fuzzing 使用 OpenAPI 文档来生成请求正文。当需要请求正文时,正文生成仅限于以下正文类型:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • application/json
  • application/xml

OpenAPI 和媒体类型

媒体类型(以前称为 MIME 类型)是传输的文件格式和格式内容的标识符。OpenAPI 文档允许您指定给定的操作可以接受不同的媒体类型,因此给定的请求可以使用不同的文件内容发送数据。例如,更新用户数据的 PUT /user 操作可以接受 XML(媒体类型 application/xml)或 JSON(媒体类型 application/json)格式的数据。 OpenAPI 2.x 允许您指定全局或每个操作接受的媒体类型,OpenAPI 3.x 允许您指定每个操作接受的媒体类型。 API Fuzzing 检查列出的媒体类型并尝试为每种支持的媒体类型生成样本数据。

  • 在 14.10 及更高版本中,默认行为是选择一种支持的媒体类型来使用。从列表中选择第一个支持的媒体类型。此行为是可配置的。
  • 在 14.9 及更早版本中,默认行为是使用所有支持的媒体类型执行测试。这意味着如果列出了两种媒体类型(例如,application/jsonapplication/xml),则使用 JSON 执行测试,然后使用 XML 执行相同的测试。

使用不同的媒体类型(例如,application/jsonapplication/xml)测试相同的操作(例如,POST /user)并不总是可取的。 例如,如果目标应用程序无论请求内容类型如何都执行相同的代码,则完成测试会话需要更长的时间,并且可能会根据目标应用程序报告与请求正文相关的重复漏洞。

环境变量 FUZZAPI_OPENAPI_ALL_MEDIA_TYPES 允许您指定在为给定操作生成请求时是否使用所有支持的媒体类型而不是一种。当环境变量 FUZZAPI_OPENAPI_ALL_MEDIA_TYPES 设置为任何值时,API Fuzzing 将尝试为所有支持的媒体类型生成请求,而不是在给定操作中生成一个请求。这将导致测试花费更长的时间,因为对每种提供的媒体类型都重复测试。

或者,变量 FUZZAPI_OPENAPI_MEDIA_TYPES 用于提供将被测试的媒体类型列表。提供一种以上的媒体类型会导致测试花费更长的时间,因为要针对所选的每种媒体类型执行测试。当环境变量 FUZZAPI_OPENAPI_MEDIA_TYPES 设置为媒体类型列表时,创建请求时仅包含列出的媒体类型。

FUZZAPI_OPENAPI_MEDIA_TYPES 中的多种媒体类型必须用冒号 (:) 分隔。例如,要将请求生成限制为媒体类型 application/x-www-form-urlencodedmultipart/form-data,请将环境变量 FUZZAPI_OPENAPI_MEDIA_TYPES 设置为 application/x-www-form-urlencoded:multipart/form-data。创建请求时仅包含此列表中支持的媒体类型,但始终会跳过不支持的媒体类型。媒体类型文本可能包含不同的部分。 例如 application/vnd.api+json; charset=UTF-8 是 ``type “/” [tree “.”] subtype [”+” suffix]* [”;” parameter]`。在请求生成时过滤媒体类型时不考虑参数。

环境变量 FUZZAPI_OPENAPI_ALL_MEDIA_TYPESFUZZAPI_OPENAPI_MEDIA_TYPES 允许您决定如何处理媒体类型。这些设置是互斥的。如果两者都启用,API Fuzzing 会报告错误。

使用 OpenAPI 规范配置 Web API 模糊测试

使用 OpenAPI 规范在极狐GitLab 中配置 API 模糊测试:

  1. fuzz 阶段添加到您的 .gitlab-ci.yml 文件中。

  2. 在您的 .gitlab-ci.yml 文件中包含 API-Fuzzing.gitlab-ci.yml 模板

  3. 通过将 FUZZAPI_PROFILE CI/CD 变量添加到 .gitlab-ci.yml 文件来提供配置文件。配置文件指定运行多少测试。将Quick-10 替换为您选择的配置文件。更多详细信息,请参阅 API fuzzing 配置文件

    variables:
      FUZZAPI_PROFILE: Quick-10
    
  4. 提供 OpenAPI 规范的位置。您可以将规范作为文件或 URL 提供。通过添加 FUZZAPI_OPENAPI 变量来指定位置。

  5. 提供目标 API 实例的基本 URL。 使用 FUZZAPI_TARGET_URL 变量或 environment_url.txt 文件。

    在项目根目录的 environment_url.txt 文件中添加 URL 非常适合在动态环境中进行测试。要针对在极狐GitLab CI/CD 流水线期间动态创建的应用程序运行 API 模糊测试,请让应用程序将其 URL 保存在 environment_url.txt 文件中。API fuzzing 会自动解析该文件以找到其扫描目标。您可以在 Auto DevOps CI YAML 中查看示例。

使用 OpenAPI 规范的示例 .gitlab-ci.yml 文件:

   stages:
     - fuzz

   include:
     - template: API-Fuzzing.gitlab-ci.yml

   variables:
     FUZZAPI_PROFILE: Quick-10
     FUZZAPI_OPENAPI: test-api-specification.json
     FUZZAPI_TARGET_URL: http://test-deployment/

这是 API Fuzzing 的最小配置。从这里您可以:

有关 API fuzzing 配置选项的详细信息,请参阅可用的 CI/CD 变量

HTTP 存档(HAR)

HTTP 存档格式 (HAR) 是一种用于记录 HTTP 事务的存档文件格式。当与极狐GitLab API fuzzer 一起使用时,HAR 必须包含调用 Web API 进行测试的记录。API fuzzer 提取所有请求并使用它们来执行测试。

有关更多详细信息,包括如何创建 HAR 文件,请参阅 HTTP 存档格式

cautionHAR 文件可能包含敏感信息,例如身份验证令牌、API 密钥和会话 cookie。我们建议您在将 HAR 文件内容添加到存储库之前查看它们。

使用 HAR 文件配置 Web API 模糊测试

要将 API 模糊测试配置为使用 HAR 文件:

  1. fuzz 阶段添加到您的 .gitlab-ci.yml 文件中。

  2. 在您的 .gitlab-ci.yml 文件中,包含 API-Fuzzing.gitlab-ci.yml 模板

  3. 通过将 FUZZAPI_PROFILE CI/CD 变量添加到 .gitlab-ci.yml 文件来提供配置文件。配置文件指定运行多少测试。将 Quick-10 替换为您选择的配置文件。更多详细信息,请参阅 API fuzzing 配置文件

    variables:
      FUZZAPI_PROFILE: Quick-10
    
  4. 提供 HAR 规范的位置。您可以将规范作为文件或 URL 提供。13.10 及更高版本引入了 URL 支持。通过添加 FUZZAPI_HAR 变量来指定位置。

  5. 目标 API 实例的基本 URL 也是必需的。通过使用 FUZZAPI_TARGET_URL 变量或 environment_url.txt 文件来提供它。

    在项目根目录的 environment_url.txt 文件中添加 URL 非常适合在动态环境中进行测试。要针对在极狐GitLab CI/CD 流水线期间动态创建的应用程序运行 API 模糊测试,请让应用程序将其域保存在 environment_url.txt 文件中。API fuzzing 会自动解析该文件以找到其扫描目标。您可以在我们的 Auto DevOps CI YAML 中看到一个示例

使用 HAR 文件的示例 .gitlab-ci.yml 文件:

   stages:
     - fuzz

   include:
     - template: API-Fuzzing.gitlab-ci.yml

   variables:
     FUZZAPI_PROFILE: Quick-10
     FUZZAPI_HAR: test-api-recording.har
     FUZZAPI_TARGET_URL: http://test-deployment/

这是 API 模糊测试的最小配置。从这里您可以:

有关 API fuzzing 配置选项的详细信息,请参阅可用的 CI/CD 变量

GraphQL Schema

对 GraphQL Schema 的支持引入于 15.4 版本。

GraphQL 是一种用于 API 的查询语言,也是 REST API 的替代品。 API Fuzzing 支持多种方式测试 GraphQL 端点:

  • 使用 GraphQL Schema 进行测试。引入于 15.4 版本。
  • 使用 GraphQL 查询的记录 (HAR) 进行测试。
  • 使用包含 GraphQL 查询的 Postman collection 进行测试。

本节介绍如何使用 GraphQL 模式进行测试。API Fuzzing 中的 GraphQL schema 支持能够从支持自检的端点查询 schema。 默认情况下启用自检,允许 GraphiQL 等工具工作。

使用 GraphQL 端点 URL 进行 API 模糊扫描

API Fuzzing 中的 GraphQL 支持能够查询 GraphQL 端点的 schema。

noteGraphQL 端点必须支持自检查询,此方法才能正常工作。

要将 API Fuzzing 配置为使用 GraphQL 端点 URL,该 URL 提供有关要测试的目标 API 的信息:

  1. 在您的 .gitlab-ci.yml 文件中包含 API-Fuzzing.gitlab-ci.yml 模板

  2. 提供 GraphQL 端点路径,例如 /api/graphql。通过添加 FUZZAPI_GRAPHQL 变量来指定路径。

  3. 目标 API 实例的基本 URL 也是必需的。通过使用 FUZZAPI_TARGET_URL 变量或 environment_url.txt 文件来提供它。

    在项目根目录的 environment_url.txt 文件中添加 URL 非常适合在动态环境中进行测试。有关详细信息,请参阅文档的动态环境解决方案部分。

使用 GraphQL 端点 URL 的完整示例配置:

stages:
  - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

apifuzzer_fuzz:
  variables:
    FUZZAPI_GRAPHQL: /api/graphql
    FUZZAPI_TARGET_URL: http://test-deployment/

此示例是 API Fuzzing 的最小配置。从这里您可以:

使用 GraphQL Schema 文件进行 API 模糊测试

要将 API Fuzzing 配置为使用 GraphQL schema 文件,该文件提供有关要测试的目标 API 的信息:

  1. 在您的 .gitlab-ci.yml 文件中包含 API-Fuzzing.gitlab-ci.yml 模板

  2. 提供 GraphQL 端点路径,例如 /api/graphql。通过添加 FUZZAPI_GRAPHQL 变量来指定路径。

  3. 提供 GraphQL 架构文件的位置。您可以将位置提供为文件路径或 URL。通过添加 FUZZAPI_GRAPHQL_SCHEMA 变量来指定位置。

  4. 目标 API 实例的基本 URL 也是必需的。通过使用 FUZZAPI_TARGET_URL 变量或 environment_url.txt 文件来提供它。

    在项目根目录的 environment_url.txt 文件中添加 URL 非常适合在动态环境中进行测试。有关详细信息,请参阅文档的动态环境解决方案部分。

使用 GraphQL schema 文件的完整示例配置:

stages:
  - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

apifuzzer_fuzz:
  variables:
    FUZZAPI_GRAPHQL: /api/graphql
    FUZZAPI_GRAPHQL_SCHEMA: test-api-graphql.schema
    FUZZAPI_TARGET_URL: http://test-deployment/

使用 GraphQL schema 文件 URL 的完整示例配置:

stages:
  - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

apifuzzer_fuzz:
  variables:
    FUZZAPI_GRAPHQL: /api/graphql
    FUZZAPI_GRAPHQL_SCHEMA: http://file-store/files/test-api-graphql.schema
    FUZZAPI_TARGET_URL: http://test-deployment/

此示例是 API Fuzzing 的最小配置。从这里您可以:

Postman Collection

Postman API 客户端是开发人员和测试人员用来调用各种类型 API 的流行工具。API 定义 可以导出为 Postman Collection 文件用于 API Fuzzing。导出时,请确保选择受支持的 Postman Collection 版本:v2.0 或 v2.1。

当与极狐GitLab API fuzzer 一起使用时,Postman Collections 必须包含 Web API 的定义以使用有效数据进行测试。API fuzzer 提取所有 API 定义并使用它们来执行测试。

cautionPostman Collection 文件可能包含敏感信息,例如身份验证令牌、API 密钥和会话 cookie。我们建议您在将 Postman Collection 文件内容添加到仓库之前查看它们。

使用 Postman Collection 文件配置 Web API 模糊测试

要将 API 模糊测试配置为使用 Postman 集合文件:

  1. fuzz 阶段添加到您的 .gitlab-ci.yml 文件中。

  2. 在您的 .gitlab-ci.yml 文件中,包含 API-Fuzzing.gitlab-ci.yml 模板

  3. 通过将 FUZZAPI_PROFILE CI/CD 变量添加到 .gitlab-ci.yml 文件来提供配置文件。配置文件指定运行多少测试。将 Quick-10 替换为您选择的配置文件。更多详细信息,请参阅 API fuzzing 配置文件

    variables:
      FUZZAPI_PROFILE: Quick-10
    
  4. 提供 Postman Collection 规范的位置。您可以将规范作为文件或 URL 提供。在 13.10 及更高版本中引入了 URL 支持。通过添加 FUZZAPI_POSTMAN_COLLECTION 变量来指定位置。

  5. 提供目标 API 实例的基本 URL。使用 FUZZAPI_TARGET_URL 变量或 environment_url.txt 文件。

    在项目根目录的 environment_url.txt 文件中添加 URL 非常适合在动态环境中进行测试。要针对在极狐GitLab CI/CD 流水线期间动态创建的应用程序运行 API 模糊测试,请让应用程序将其域保存在 environment_url.txt 文件中。API fuzzing 会自动解析该文件以找到其扫描目标。您可以在我们的 Auto DevOps CI YAML 中看到一个示例

使用 Postman Collection 文件的示例 .gitlab-ci.yml 文件:

   stages:
     - fuzz

   include:
     - template: API-Fuzzing.gitlab-ci.yml

   variables:
     FUZZAPI_PROFILE: Quick-10
     FUZZAPI_POSTMAN_COLLECTION: postman-collection_serviceA.json
     FUZZAPI_TARGET_URL: http://test-deployment/

这是 API 模糊测试的最小配置。从这里您可以:

有关 API fuzzing 配置选项的详细信息,请参阅可用的 CI/CD 变量

Postman 变量

  • 对 Postman 环境文件格式的支持引入于 15.1 版本。
  • 对多变量文件的支持引入于 15.1 版本。
  • 对 Postman 变量范围:全局和环境的支持引入于 15.1 版本。
Postman 客户端中的变量

Postman 允许开发人员定义可用于请求的不同部分的占位符。这些占位符称为变量,如 Postman 文档使用变量中所述。 您可以使用变量来存储和重用请求和脚本中的值。例如,您可以编辑集合以将变量添加到文档中:

Edit collection variable tab View

或者,您可以在环境中添加变量:

Edit environment variables View

然后,您可以在 URL、headers 和其他部分中使用变量:

Edit request using variables View

Postman 已经从一个具有良好 UX 体验的基本客户端工具发展为一个更复杂的生态系统,它允许使用脚本测试 API、创建触发辅助请求的复杂集合以及在此过程中设置变量,并非 Postman 生态系统中的所有功能都受支持。例如,不支持脚本。Postman 支持的主要重点是摄取 Postman 客户端使用的 Postman 集合定义及其在工作区、环境和集合本身中定义的相关变量。

Postman 允许在不同的范围内创建变量。在 Postman 工具中,每个范围都有不同的可见性级别。例如,您可以在每个操作定义和工作区看到的全局环境范围内创建一个变量。您还可以在特定环境范围内创建一个变量,该变量仅在选择使用该特定环境时可见和使用。有些范围并不总是可用,例如在 Postman 生态系统中,您可以在 Postman 客户端中创建请求,这些请求没有本地范围,但测试脚本有。

Postman 中的变量作用域可能是一个令人生畏的话题,并不是每个人都熟悉它。 我们强烈建议您在继续之前阅读 Postman 文档中的变量范围

正如上面提到的,有不同的变量范围,每个都有一个目的,可以用来为您的 Postman 文档提供更多的灵活性。 根据 Postman 文档,有一个关于如何计算变量值的重要说明:

如果在两个不同的作用域中声明了同名变量,则使用作用域最窄的变量中存储的值。例如,有一个名为 username 的全局变量和一个名为 username 的局部变量,则在请求运行时使用本地值。

以下是 Postman Client 和 API Fuzzing 支持的变量范围的总结:

  • 全局环境(全局)范围是一个特殊的预定义环境,可在整个工作空间中使用。我们也可以将全局环境作用域称为全局作用域。Postman 客户端允许将全局环境导出为 JSON 文件,该文件可与 API Fuzzing 一起使用。
  • 环境范围是用户在 Postman 客户端中创建的一组命名变量。Postman 客户端支持单个活动环境以及全局环境。在活动用户创建的环境中定义的变量优先于在全局环境中定义的变量。Postman 客户端允许将您的环境导出为 JSON 文件,该文件可与 API Fuzzing 一起使用。
  • 集合范围是在给定集合中声明的一组变量。集合变量可用于声明它们的集合以及嵌套的请求或集合。在集合范围内定义的变量优先于全局环境范围和环境范围。 Postman 客户端可以将一个或多个集合导出到 JSON 文件中,该 JSON 文件包含选定的集合、请求和集合变量。
  • API Fuzzing 范围是 API Fuzzing 添加的新范围,允许用户提供额外的变量,或覆盖在其他支持的范围中定义的变量。Postman 不支持此范围。API Fuzzing 范围变量使用自定义 JSON 文件格式提供。
    • 覆盖环境或集合中定义的值
    • 从脚本定义变量
    • 从不受支持的数据范围定义单行数据
  • 数据范围是一组变量,其名称和值来自 JSON 或 CSV 文件。像 NewmanPostman Collection Runner 这样的 Postman 集合运行程序在集合中执行请求的次数,与条目具有 JSON 或 CSV 文件的次数一样多。这些变量的一个很好的用例是使用 Postman 中的脚本自动化测试。API Fuzzing 支持从 CSV 或 JSON 文件中读取数据。
  • 本地范围是在 Postman 脚本中定义的变量。API Fuzzing 支持 Postman 脚本和扩展脚本中定义的变量。您仍然可以通过在受支持的范围之一或我们的自定义 JSON 格式中定义脚本定义的变量来为它们提供值。

API Fuzzing 并不支持所有范围,也不支持脚本中定义的变量。下表按范围从最广到最窄排序。

范围 Postman API Fuzzing 说明
全局环境 Yes Yes 特殊的预定义环境
环境 Yes Yes 命名环境
集合 Yes Yes 在您的 postman 集合中定义
API Fuzzing 范围 No Yes API Fuzzing 添加的自定义范围
数据 Yes No CSV 或 JSON 格式的外部文件
本地 Yes No 脚本中定义的变量

有关如何在不同范围内定义变量和导出变量的更多详细信息,请参见:

从 Postman 客户端导出

Postman 客户端允许您导出不同的文件格式,例如,您可以导出 Postman 集合或 Postman 环境。导出的环境可以是全局环境(始终可用),也可以是您之前创建的任何自定义环境。当您导出 Postman 集合时,它可能只包含集合和局部范围变量的声明;不包括环境范围的变量。

要获得环境范围变量的声明,您必须在当时导出给定的环境。每个导出的文件仅包含来自所选环境的变量。

有关在不同支持范围内导出变量的更多详细信息,请参阅:

API Fuzzing 范围,自定义 JSON 文件格式

我们自定义的 JSON 文件格式是一个 JSON 对象,其中每个对象属性代表一个变量名,属性值代表变量值。该文件可以使用您喜欢的文本编辑器创建,也可以由您流水线中的早期作业生成。

此示例在 API Fuzzing 范围内定义了两个变量 base_urltoken

{
  "base_url": "http://127.0.0.1/",
  "token": "Token 84816165151"
}
将作用域与 API Fuzzing 结合使用

极狐GitLab 15.1 及更高版本支持范围:全局、环境、集合和 API Fuzzing。极狐GitLab 15.0 及更早版本,仅支持集合和 API Fuzzing 范围。

下表提供了将范围文件/URL 映射到 API Fuzzing 配置变量的快速参考:

范围 如何提供
全局环境 FUZZAPI_POSTMAN_COLLECTION_VARIABLES
环境 FUZZAPI_POSTMAN_COLLECTION_VARIABLES
集合 FUZZAPI_POSTMAN_COLLECTION
API Fuzzing 范围 FUZZAPI_POSTMAN_COLLECTION_VARIABLES
数据 不支持
本地 不支持

Postman Collection 文档自动包含任何集合范围的变量。Postman Collection 提供了配置变量 FUZZAPI_POSTMAN_COLLECTION。此变量可以设置为单个导出的 Postman Collection

来自其他范围的变量通过 FUZZAPI_POSTMAN_COLLECTION_VARIABLES 配置变量提供。在 15.1 及更高版本中,配置变量支持逗号 (,) 分隔的文件列表。 15.0 及更早版本仅支持一个文件。提供的文件的顺序并不重要,因为文件提供了所需的范围信息。

配置变量 FUZZAPI_POSTMAN_COLLECTION_VARIABLES 可以设置为:

未定义的 Postman 变量

API Fuzzing engine 有可能找不到您的 Postman 集合文件正在使用的所有变量引用。有些情况是:

  • 您正在使用数据或局部范围变量,如前所述,API Fuzzing 不支持这些范围。因此,假设这些变量的值没有通过 API Fuzzing 范围提供,那么数据和局部范围变量的值是未定义的。
  • 变量名称输入错误,并且名称与定义的变量不匹配。
  • Postman 客户端支持 API Fuzzing 不支持的新动态变量。

在可能的情况下,API Fuzzing 遵循与 Postman 客户端在处理未定义变量时相同的行为。变量引用的文本保持不变,并且没有文本替换。同样的行为也适用于任何不受支持的动态变量。

例如,如果 Postman collection 中的请求定义引用了变量 {{full_url}} 并且未找到该变量,则它保持不变,值为 {{full_url}}

动态 Postman 变量

除了用户可以在不同范围级别定义的变量之外,Postman 还具有一组称为动态变量的预定义变量。动态变量已经定义,它们的名称以美元符号 ($) 为前缀,例如,$guid。动态变量可以像任何其他变量一样使用,并且在 Postman 客户端中,它们在请求/收集运行期间产生随机值。

API Fuzzing 和 Postman 之间的一个重要区别是 API Fuzzing 为相同动态变量的每次使用返回相同的值。这与 Postman 客户端行为不同,后者在每次使用相同的动态变量时返回一个随机值。换句话说,API Fuzzing 对动态变量使用静态值,而 Postman 使用随机值。

扫描过程中支持的动态变量有:

变量
$guid 611c2e81-2ccb-42d8-9ddc-2d0bfa65c1b4
$isoTimestamp 2020-06-09T21:10:36.177Z
$randomAbbreviation PCI
$randomAbstractImage http://no-a-valid-host/640/480/abstract
$randomAdjective auxiliary
$randomAlphaNumeric a
$randomAnimalsImage http://no-a-valid-host/640/480/animals
$randomAvatarImage https://no-a-valid-host/path/to/some/image.jpg
$randomBankAccount 09454073
$randomBankAccountBic EZIAUGJ1
$randomBankAccountIban MU20ZPUN3039684000618086155TKZ
$randomBankAccountName Home Loan Account
$randomBitcoin 3VB8JGT7Y4Z63U68KGGKDXMLLH5
$randomBoolean true
$randomBs killer leverage schemas
$randomBsAdjective viral
$randomBsBuzz repurpose
$randomBsNoun markets
$randomBusinessImage http://no-a-valid-host/640/480/business
$randomCatchPhrase Future-proofed heuristic open architecture
$randomCatchPhraseAdjective Business-focused
$randomCatchPhraseDescriptor bandwidth-monitored
$randomCatchPhraseNoun superstructure
$randomCatsImage http://no-a-valid-host/640/480/cats
$randomCity Spinkahaven
$randomCityImage http://no-a-valid-host/640/480/city
$randomColor fuchsia
$randomCommonFileExt wav
$randomCommonFileName well_modulated.mpg4
$randomCommonFileType audio
$randomCompanyName Grady LLC
$randomCompanySuffix Inc
$randomCountry Kazakhstan
$randomCountryCode MD
$randomCreditCardMask 3622
$randomCurrencyCode ZMK
$randomCurrencyName Pound Sterling
$randomCurrencySymbol £
$randomDatabaseCollation utf8_general_ci
$randomDatabaseColumn updatedAt
$randomDatabaseEngine Memory
$randomDatabaseType text
$randomDateFuture Tue Mar 17 2020 13:11:50 GMT+0530 (India Standard Time)
$randomDatePast Sat Mar 02 2019 09:09:26 GMT+0530 (India Standard Time)
$randomDateRecent Tue Jul 09 2019 23:12:37 GMT+0530 (India Standard Time)
$randomDepartment Electronics
$randomDirectoryPath /usr/local/bin
$randomDomainName trevor.info
$randomDomainSuffix org
$randomDomainWord jaden
$randomEmail Iva.Kovacek61@no-a-valid-host.com
$randomExampleEmail non-a-valid-user@example.net
$randomFashionImage http://no-a-valid-host/640/480/fashion
$randomFileExt war
$randomFileName neural_sri_lanka_rupee_gloves.gdoc
$randomFilePath /home/programming_chicken.cpio
$randomFileType application
$randomFirstName Chandler
$randomFoodImage http://no-a-valid-host/640/480/food
$randomFullName Connie Runolfsdottir
$randomHexColor #47594a
$randomImageDataUri data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20baseProfile%3D%22full%22%20width%3D%22undefined%22%20height%3D%22undefined%22%3E%20%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20fill%3D%22grey%22%2F%3E%20%20%3Ctext%20x%3D%220%22%20y%3D%2220%22%20font-size%3D%2220%22%20text-anchor%3D%22start%22%20fill%3D%22white%22%3Eundefinedxundefined%3C%2Ftext%3E%20%3C%2Fsvg%3E
$randomImageUrl http://no-a-valid-host/640/480
$randomIngverb navigating
$randomInt 494
$randomIP 241.102.234.100
$randomIPV6 dbe2:7ae6:119b:c161:1560:6dda:3a9b:90a9
$randomJobArea Mobility
$randomJobDescriptor Senior
$randomJobTitle International Creative Liaison
$randomJobType Supervisor
$randomLastName Schneider
$randomLatitude 55.2099
$randomLocale ny
$randomLongitude 40.6609
$randomLoremLines Ducimus in ut mollitia.\nA itaque non.\nHarum temporibus nihil voluptas.\nIste in sed et nesciunt in quaerat sed.
$randomLoremParagraph Ab aliquid odio iste quo voluptas voluptatem dignissimos velit. Recusandae facilis qui commodi ea magnam enim nostrum quia quis. Nihil est suscipit assumenda ut voluptatem sed. Esse ab voluptas odit qui molestiae. Rem est nesciunt est quis ipsam expedita consequuntur.
$randomLoremParagraphs Voluptatem rem magnam aliquam ab id aut quaerat. Placeat provident possimus voluptatibus dicta velit non aut quasi. Mollitia et aliquam expedita sunt dolores nam consequuntur. Nam dolorum delectus ipsam repudiandae et ipsam ut voluptatum totam. Nobis labore labore recusandae ipsam quo.
$randomLoremSentence Molestias consequuntur nisi non quod.
$randomLoremSentences Et sint voluptas similique iure amet perspiciatis vero sequi atque. Ut porro sit et hic. Neque aspernatur vitae fugiat ut dolore et veritatis. Ab iusto ex delectus animi. Voluptates nisi iusto. Impedit quod quae voluptate qui.
$randomLoremSlug eos-aperiam-accusamus, beatae-id-molestiae, qui-est-repellat
$randomLoremText Quisquam asperiores exercitationem ut ipsum. Aut eius nesciunt. Et reiciendis aut alias eaque. Nihil amet laboriosam pariatur eligendi. Sunt ullam ut sint natus ducimus. Voluptas harum aspernatur soluta rem nam.
$randomLoremWord est
$randomLoremWords vel repellat nobis
$randomMACAddress 33:d4:68:5f:b4:c7
$randomMimeType audio/vnd.vmx.cvsd
$randomMonth February
$randomNamePrefix Dr.
$randomNameSuffix MD
$randomNatureImage http://no-a-valid-host/640/480/nature
$randomNightlifeImage http://no-a-valid-host/640/480/nightlife
$randomNoun bus
$randomPassword t9iXe7COoDKv8k3
$randomPeopleImage http://no-a-valid-host/640/480/people
$randomPhoneNumber 700-008-5275
$randomPhoneNumberExt 27-199-983-3864
$randomPhrase You can't program the monitor without navigating the mobile XML program!
$randomPrice 531.55
$randomProduct Pizza
$randomProductAdjective Unbranded
$randomProductMaterial Steel
$randomProductName Handmade Concrete Tuna
$randomProtocol https
$randomSemver 7.0.5
$randomSportsImage http://no-a-valid-host/640/480/sports
$randomStreetAddress 5742 Harvey Streets
$randomStreetName Kuhic Island
$randomTransactionType payment
$randomTransportImage http://no-a-valid-host/640/480/transport
$randomUrl https://no-a-valid-host.net
$randomUserAgent Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.9.8; rv:15.6) Gecko/20100101 Firefox/15.6.6
$randomUserName Jarrell.Gutkowski
$randomUUID 6929bb52-3ab2-448a-9796-d6480ecad36b
$randomVerb navigate
$randomWeekday Thursday
$randomWord withdrawal
$randomWords Samoa Synergistic sticky copying Grocery
$timestamp 1562757107
示例:全局范围

在这个例子中,从 Postman 客户端,全局范围被导出,作为global-scope.json,通过 FUZZAPI_POSTMAN_COLLECTION_VARIABLES 配置变量提供给 API Fuzzing。

以下是使用 FUZZAPI_POSTMAN_COLLECTION_VARIABLES 的示例:

stages:
     - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick-10
  FUZZAPI_POSTMAN_COLLECTION: postman-collection.json
  FUZZAPI_POSTMAN_COLLECTION_VARIABLES: global-scope.json
  FUZZAPI_TARGET_URL: http://test-deployment/
示例:环境范围

在此示例中,环境范围从 Postman 客户端导出为 environment-scope.json,并通过 FUZZAPI_POSTMAN_COLLECTION_VARIABLES 配置变量提供给 API Fuzzing。

以下是使用 FUZZAPI_POSTMAN_COLLECTION_VARIABLES 的示例:

stages:
  - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick
  FUZZAPI_POSTMAN_COLLECTION: postman-collection.json
  FUZZAPI_POSTMAN_COLLECTION_VARIABLES: environment-scope.json
  FUZZAPI_TARGET_URL: http://test-deployment/
示例:集合范围

集合范围变量包含在导出的 Postman Collection 文件中,并通过 FUZZAPI_POSTMAN_COLLECTION 配置变量提供。

以下是使用 FUZZAPI_POSTMAN_COLLECTION 的示例:

stages:
  - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick
  FUZZAPI_POSTMAN_COLLECTION: postman-collection.json
  FUZZAPI_TARGET_URL: http://test-deployment/
  FUZZAPI_POSTMAN_COLLECTION_VARIABLES: variable-collection-dictionary.json
示例:API Fuzzing 范围

API Fuzzing Scope 用于两个主要目的,定义 API Fuzzing 不支持的数据和局部范围变量,以及更改在另一个范围中定义的现有变量的值。 API Fuzzing Scope 是通过 FUZZAPI_POSTMAN_COLLECTION_VARIABLES 配置变量提供的。

以下是使用 FUZZAPI_POSTMAN_COLLECTION_VARIABLES 的示例:

stages:
  - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick
  FUZZAPI_POSTMAN_COLLECTION: postman-collection.json
  FUZZAPI_POSTMAN_COLLECTION_VARIABLES: api-fuzzing-scope.json
  FUZZAPI_TARGET_URL: http://test-deployment/

文件 api-fuzzing-scope.json 使用我们的自定义 JSON 文件格式。此 JSON 是具有属性键值对的对象。键是变量的名称,值是变量的值。例如:

{
  "base_url": "http://127.0.0.1/",
  "token": "Token 84816165151"
}
示例:多个范围

在此示例中,配置了全局范围、环境范围和集合范围。第一步是导出我们的多个范围。

  • 全局范围导出为 global-scope.json
  • 环境范围导出为 environment-scope.json
  • 将包含集合范围的 Postman Collection 导出为 postman-collection.json

Postman Collection 使用 FUZZAPI_POSTMAN_COLLECTION 变量提供,而其他范围使用 FUZZAPI_POSTMAN_COLLECTION_VARIABLES 提供。API Fuzzing 可以使用每个文件中提供的数据来识别提供的文件与哪个范围匹配。

stages:
  - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick
  FUZZAPI_POSTMAN_COLLECTION: postman-collection.json
  FUZZAPI_POSTMAN_COLLECTION_VARIABLES: global-scope.json,environment-scope.json
  FUZZAPI_TARGET_URL: http://test-deployment/
示例:更改变量值

使用导出范围时,通常必须更改变量的值才能与 API Fuzzing 一起使用。例如,一个集合范围的变量可能包含一个名为 api_version 且值为 v2 的变量,而您的测试需要一个值为 v1 的变量。无需修改导出的集合来更改值,API Fuzzing 范围可用于更改其值。这是因为 API Fuzzing 范围优先于所有其他范围。

集合范围变量包含在导出的 Postman Collection 文件中,并通过 FUZZAPI_POSTMAN_COLLECTION 配置变量提供。

API Fuzzing 范围是通过 FUZZAPI_POSTMAN_COLLECTION_VARIABLES 配置变量提供的,但首先,我们必须创建文件。文件 api-fuzzing-scope.json 使用我们的自定义 JSON 文件格式。此 JSON 是具有属性键值对的对象。键是变量的名称,值是变量的值。例如:

{
  "api_version": "v1"
}

我们的 CI 定义:

stages:
  - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick
  FUZZAPI_POSTMAN_COLLECTION: postman-collection.json
  FUZZAPI_POSTMAN_COLLECTION_VARIABLES: api-fuzzing-scope.json
  FUZZAPI_TARGET_URL: http://test-deployment/
示例:更改具有多个范围的变量值

使用导出范围时,通常必须更改变量的值才能与 API Fuzzing 一起使用。例如,环境范围可能包含名为 api_version 的变量,其值为 v2,而您的测试需要值为 v1。可以使用 API Fuzzing 范围,而不是修改导出的文件来更改值。这是可行的,因为 API Fuzzing 范围优先于所有其他范围。

在此示例中,配置了全局范围、环境范围、集合范围和 API Fuzzing 范围。第一步是导出和创建我们的各种范围。

  • 全局范围导出为 global-scope.json
  • 环境范围导出为 environment-scope.json
  • 将包含集合范围的 Postman Collection 导出为 postman-collection.json

API Fuzzing 范围通过使用我们的自定义 JSON 文件格式,创建文件 api-fuzzing-scope.json 来使用。此 JSON 是具有属性键值对的对象。键是变量的名称,值是变量的值。例如:

{
  "api_version": "v1"
}

Postman Collection 使用 FUZZAPI_POSTMAN_COLLECTION 变量提供,而其他范围使用 FUZZAPI_POSTMAN_COLLECTION_VARIABLES 提供。API Fuzzing 可以使用每个文件中提供的数据来识别提供的文件与哪个范围匹配。

stages:
  - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick
  FUZZAPI_POSTMAN_COLLECTION: postman-collection.json
  FUZZAPI_POSTMAN_COLLECTION_VARIABLES: global-scope.json,environment-scope.json,api-fuzzing-scope.json
  FUZZAPI_TARGET_URL: http://test-deployment/

API fuzzing 配置

API fuzzing 行为可以通过 CI/CD 变量进行更改。

从 13.12 及更高版本开始,默认的 API 模糊测试配置文件是 .gitlab/gitlab-api-fuzzing-config.yml。在 14.0 及更高版本中,API 模糊测试配置文件必须位于仓库的 .gitlab 目录中,而不是仓库的根目录中。

caution在将这些更改合并到默认分支之前,应在合并请求中测试极狐GitLab 安全扫描工具的所有自定义。不这样做会产生意想不到的结果,包括大量误报。

身份验证

通过将身份验证令牌作为 header 或 cookie 提供来处理身份验证。您可以提供执行身份验证流程或计算令牌的脚本。

HTTP 基本身份验证

HTTP 基本身份验证是一种内置于 HTTP 协议的身份验证方法,并与传输层安全性 (TLS) 结合使用。

我们建议您为密码(例如,TEST_API_PASSWORD创建一个 CI/CD 变量,并设置隐藏。您可以从项目页面的 设置 > CI/CD变量 部分中创建 CI/CD 变量。 由于对隐藏变量的限制,您应该在将密码添加为变量之前对密码进行 Base64 编码。

最后,将两个 CI/CD 变量添加到您的 .gitlab-ci.yml 文件中:

  • FUZZAPI_HTTP_USERNAME:用于身份验证的用户名。
  • FUZZAPI_HTTP_PASSWORD_BASE64:用于身份验证的 Base64 编码密码。
stages:
    - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick-10
  FUZZAPI_HAR: test-api-recording.har
  FUZZAPI_TARGET_URL: http://test-deployment/
  FUZZAPI_HTTP_USERNAME: testuser
  FUZZAPI_HTTP_PASSWORD_BASE64: $TEST_API_PASSWORD

原始密码

如果您不想对密码进行 Base64 编码(或者如果您使用的是 15.3 或更早版本),您可以提供原始密码 FUZZAPI_HTTP_PASSWORD,而不是使用 FUZZAPI_HTTP_PASSWORD_BASE64

Bearer Tokens

Bearer tokens 由多种不同的身份验证机制使用,包括 OAuth2 和 JSON Web 令牌 (JWT)。Bearer tokens 使用 Authorization HTTP header 传输。要将 Bearer tokens 与 API 模糊测试一起使用,您需要以下条件之一:

  • 一个不会过期的令牌
  • 一种生成持续测试长度的令牌的方法
  • API fuzzing 可以调用以生成令牌的 Python 脚本
令牌不会过期

如果 Bearer tokens 没有过期,请使用 FUZZAPI_OVERRIDES_ENV 变量来提供它。此变量的内容是一个 JSON 片段,它提供 header 和 cookie,以添加到 API 模糊测试的传出 HTTP 请求。

按照以下步骤为 Bearer tokens 提供 FUZZAPI_OVERRIDES_ENV

  1. 创建 CI/CD 变量,例如 TEST_API_BEARERAUTH,值为 {"headers":{" Authorization":"Bearer dXNlcm5hbWU6cGFzc3dvcmQ="}}(替换您的令牌)。您可以从极狐GitLab 项目页面的 设置 > CI/CD变量 部分中创建 CI/CD 变量。

  2. .gitlab-ci.yml 文件中,将 FUZZAPI_OVERRIDES_ENV 设置为您刚刚创建的变量:

    stages:
      - fuzz
    
    include:
      - template: API-Fuzzing.gitlab-ci.yml
    
    variables:
      FUZZAPI_PROFILE: Quick-10
      FUZZAPI_OPENAPI: test-api-specification.json
      FUZZAPI_TARGET_URL: http://test-deployment/
      FUZZAPI_OVERRIDES_ENV: $TEST_API_BEARERAUTH
    
  3. 要验证身份验证是否有效,请运行 API 模糊测试并查看模糊日志和测试 API 的应用程序日志。有关覆盖命令的更多信息,请参阅覆盖部分

在测试运行时生成的令牌

如果必须生成 Bearer tokens 并且在测试期间不会过期,您可以向 API 模糊测试提供包含令牌的文件。先前的阶段和作业,或 API 模糊测试作业的一部分,可以生成此文件。

API fuzzing 期望接收具有以下结构的 JSON 文件:

{
  "headers" : {
    "Authorization" : "Bearer dXNlcm5hbWU6cGFzc3dvcmQ="
  }
}

该文件可以由前一阶段生成,并通过 FUZZAPI_OVERRIDES_FILE CI/CD 变量提供给 API fuzzing。

.gitlab-ci.yml 文件中设置 FUZZAPI_OVERRIDES_FILE

stages:
     - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_TARGET_URL: http://test-deployment/
  FUZZAPI_OVERRIDES_FILE: api-fuzzing-overrides.json

要验证身份验证是否有效,请运行 API 模糊测试并查看模糊日志和测试 API 的应用程序日志。

令牌的有效期很短

如果必须生成 Bearer tokens 并在扫描完成之前过期,您可以为 API fuzzer 提供程序或脚本以在提供的时间间隔内执行。提供的脚本在安装了 Python 3 和 Bash 的 Alpine Linux 容器中运行。如果 Python 脚本需要额外的包,它必须检测到这一点并在运行时安装这些包。

该脚本必须创建一个 JSON 文件,其中包含特定格式的不记名令牌:

{
  "headers" : {
    "Authorization" : "Bearer dXNlcm5hbWU6cGFzc3dvcmQ="
  }
}

您必须提供三个 CI/CD 变量,每个变量都设置为正确操作:

  • FUZZAPI_OVERRIDES_FILE:提供的命令生成的 JSON 文件。
  • FUZZAPI_OVERRIDES_CMD:生成 JSON 文件的命令。
  • FUZZAPI_OVERRIDES_INTERVAL:运行命令的间隔(以秒为单位)。

例如:

stages:
     - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick-10
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_TARGET_URL: http://test-deployment/
  FUZZAPI_OVERRIDES_FILE: api-fuzzing-overrides.json
  FUZZAPI_OVERRIDES_CMD: renew_token.py
  FUZZAPI_OVERRIDES_INTERVAL: 300

要验证身份验证是否有效,请运行 API 模糊测试并查看模糊日志和测试 API 的应用程序日志。

API 模糊测试配置文件

极狐GitLab 提供了配置文件 gitlab-api-fuzzing-config.yml。 它包含几个执行特定数量测试的测试配置文件。每个配置文件的运行时间随着测试数量的增加而增加。

配置文件 模糊测试(每个参数)
Quick-10 10
Medium-20 20
Medium-50 50
Long-100 100

可用的 CI/CD 变量

CI/CD 变量 描述
SECURE_ANALYZERS_PREFIX 指定要从中下载分析器的 Docker registry 基本地址。
FUZZAPI_VERSION 指定 API Fuzzing 容器版本。默认为 2
FUZZAPI_IMAGE_SUFFIX 指定容器镜像后缀。默认为无。
FUZZAPI_API_PORT 指定 API Fuzzing engine 使用的通信端口号。默认为 5500。引入于 15.5 版本。
FUZZAPI_TARGET_URL API 测试目标的基本 URL。
FUZZAPI_CONFIG 废弃于 13.12 版本,替换为默认的 .gitlab/gitlab-api-fuzzing-config.yml。API 模糊测试配置文件。
FUZZAPI_PROFILE 测试期间使用的配置文件。默认为 Quick-10
FUZZAPI_EXCLUDE_PATHS 从测试中排除 API URL 路径。
FUZZAPI_EXCLUDE_URLS 从测试中排除 API URL。引入于 14.10 版本。
FUZZAPI_EXCLUDE_PARAMETER_ENV 包含排除参数的 JSON 字符串。引入于 14.10 版本。
FUZZAPI_EXCLUDE_PARAMETER_FILE 包含排除参数的 JSON 文件的路径。引入于 14.10 版本。
FUZZAPI_OPENAPI OpenAPI 规范文件或 URL。
FUZZAPI_OPENAPI_RELAXED_VALIDATION 放宽文件验证。默认为禁用。引入于 14.7 版本。
FUZZAPI_OPENAPI_ALL_MEDIA_TYPES 生成请求时使用所有支持的媒体类型而不是一种。 导致测试持续时间更长。默认为禁用。引入于 14.10 版本。
FUZZAPI_OPENAPI_MEDIA_TYPES 冒号 (:) 分隔的媒体类型接受测试。默认为禁用。引入于 14.10 版本。
FUZZAPI_HAR HTTP 存档 (HAR) 文件。
FUZZAPI_GRAPHQL GraphQL 端点的路径,例如 /api/graphql。引入于 15.4 版本。
FUZZAPI_GRAPHQL_SCHEMA JSON 格式的 GraphQL schema 的 URL 或文件名。引入于 15.4 版本。
FUZZAPI_POSTMAN_COLLECTION Postman Collection 文件。
FUZZAPI_POSTMAN_COLLECTION_VARIABLES 用于提取 Postman 变量值的 JSON 文件的路径。对逗号分隔 (,) 文件的支持引入于 15.1 版本。
FUZZAPI_OVERRIDES_FILE 包含覆盖的 JSON 文件的路径。
FUZZAPI_OVERRIDES_ENV 包含要覆盖的 header 的 JSON 字符串。
FUZZAPI_OVERRIDES_CMD 覆盖命令。
FUZZAPI_OVERRIDES_CMD_VERBOSE 当设置为任何值时。它显示覆盖命令输出作为作业输出的一部分。引入于 14.8 版本。
FUZZAPI_PRE_SCRIPT 在扫描会话开始之前运行用户命令或脚本。
FUZZAPI_POST_SCRIPT 扫描会话完成后运行用户命令或脚本。
FUZZAPI_OVERRIDES_INTERVAL 以秒为单位运行覆盖命令的频率。默认为 0(一次)。
FUZZAPI_HTTP_USERNAME HTTP 身份验证的用户名。
FUZZAPI_HTTP_PASSWORD HTTP 身份验证的密码。
FUZZAPI_HTTP_PASSWORD_BASE64 HTTP 身份验证密码,Base64 编码。引入于 15.4 版本。
FUZZAPI_HTTP_PASSWORD_BASE64 HTTP 身份验证密码,Base64 编码。引入于 15.4 版本。

覆盖

API Fuzzing 提供了一种在请求中添加或覆盖特定项目的方法,例如:

  • Headers
  • Cookies
  • Query string
  • Form data
  • JSON nodes
  • XML nodes

您可以使用它来注入语义版本标头、身份验证等。身份验证部分包括为此目的使用覆盖的示例。

覆盖使用 JSON 文档,其中每种类型的覆盖由 JSON 对象表示:

{
  "headers": {
    "header1": "value",
    "header2": "value"
  },
  "cookies": {
    "cookie1": "value",
    "cookie2": "value"
  },
  "query":      {
    "query-string1": "value",
    "query-string2": "value"
  },
  "body-form":  {
    "form-param1": "value",
    "form-param2": "value"
  },
  "body-json":  {
    "json-path1": "value",
    "json-path2": "value"
  },
  "body-xml" :  {
    "xpath1":    "value",
    "xpath2":    "value"
  }
}

设置单个 header 的示例:

{
  "headers": {
    "Authorization": "Bearer dXNlcm5hbWU6cGFzc3dvcmQ="
  }
}

同时设置 header 和 cookie 的示例:

{
  "headers": {
    "Authorization": "Bearer dXNlcm5hbWU6cGFzc3dvcmQ="
  },
  "cookies": {
    "flags": "677"
  }
}

设置 body-form 覆盖的示例用法:

{
  "body-form":  {
    "username": "john.doe"
  }
}

当请求正文只有表单数据内容时,覆盖引擎使用 body-form

设置 body-json 覆盖的示例用法:

{
  "body-json":  {
    "$.credentials.access-token": "iddqd!42.$"
  }
}

请注意,对象 body-json 中的每个 JSON 属性名称都设置为 JSON 路径 表达式。JSON 路径表达式 $.credentials.access-token 标识要使用值 iddqd!42.$ 覆盖的节点。当请求正文只有 JSON 内容时,覆盖引擎使用 body-json

例如,如果正文设置为以下 JSON:

{
    "credentials" : {
        "username" :"john.doe",
        "access-token" : "non-valid-password"
    }
}

改为:

{
    "credentials" : {
        "username" :"john.doe",
        "access-token" : "iddqd!42.$"
    }
}

这是设置 body-xml 覆盖的示例。 第一个条目覆盖 XML 属性,第二个条目覆盖 XML 元素:

{
  "body-xml" :  {
    "/credentials/@isEnabled": "true",
    "/credentials/access-token/text()" : "iddqd!42.$"
  }
}

请注意,对象 body-xml 中的每个 JSON 属性名称都设置为 XPath v2 表达式。XPath 表达式 /credentials/@isEnabled 标识要使用值 true 覆盖的属性节点。XPath 表达式 /credentials/access-token/text() 标识要使用值 iddqd!42.$ 覆盖的元素节点。当请求正文只有 XML 内容时,覆盖引擎使用 body-xml

例如,如果正文设置为以下 XML:

<credentials isEnabled="false">
  <username>john.doe</username>
  <access-token>non-valid-password</access-token>
</credentials>

改为:

<credentials isEnabled="true">
  <username>john.doe</username>
  <access-token>iddqd!42.$</access-token>
</credentials>

您可以将此 JSON 文档作为文件或环境变量提供。您还可以提供一个命令来生成 JSON 文档。该命令可以间隔运行以支持过期的值。

使用文件

要将覆盖 JSON 作为文件提供,设置了 FUZZAPI_OVERRIDES_FILE CI/CD 变量。该路径是相对于作业当前工作目录的。

这是一个示例 .gitlab-ci.yml

stages:
     - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_TARGET_URL: http://test-deployment/
  FUZZAPI_OVERRIDES_FILE: api-fuzzing-overrides.json

使用 CI/CD 变量

要将覆盖 JSON 作为文件提供,设置了 FUZZAPI_OVERRIDES_FILE CI/CD 变量。该路径是相对于作业当前工作目录的。

这是一个示例 .gitlab-ci.yml

stages:
     - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_TARGET_URL: http://test-deployment/
  FUZZAPI_OVERRIDES_ENV: '{"headers":{"X-API-Version":"2"}}'

在此示例 .gitlab-ci.yml 中,SECRET_OVERRIDES 变量提供 JSON。这是在 UI 中定义的群组或实例级别 CI/CD 变量

stages:
     - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_TARGET_URL: http://test-deployment/
  FUZZAPI_OVERRIDES_ENV: $SECRET_OVERRIDES

使用命令

如果必须在到期时生成或重新生成该值,您可以为 API fuzzer 提供一个程序或脚本以在指定的时间间隔内执行。提供的脚本在安装了 Python 3 和 Bash 的 Alpine Linux 容器中运行。

您必须将环境变量 FUZZAPI_OVERRIDES_CMD 设置为您要执行的程序或脚本。提供的命令会创建之前定义的覆盖 JSON 文件。

您可能想要安装其他脚本运行时,例如 NodeJS 或 Ruby,或者您可能需要为您的 overrides 命令安装依赖项。在这种情况下,我们建议将 FUZZAPI_PRE_SCRIPT 设置为提供这些先决条件的脚本的文件路径。FUZZAPI_PRE_SCRIPT 提供的脚本在分析器启动之前执行一次。

有关安装 Alpine Linux 软件包的信息,请参阅 Alpine Linux 软件包管理页面。

您必须提供三个 CI/CD 变量,每个变量都设置为正确操作:

  • FUZZAPI_OVERRIDES_FILE:由提供的命令生成的文件。
  • FUZZAPI_OVERRIDES_CMD:覆盖负责定期生成覆盖 JSON 文件的命令。
  • FUZZAPI_OVERRIDES_INTERVAL:以秒为单位运行命令的间隔。

可选:

  • FUZZAPI_PRE_SCRIPT:在分析器启动之前安装运行时或依赖项的脚本。
caution要在 Alpine Linux 中执行脚本,您必须首先使用命令 chmod 设置执行权限。例如,为每个人设置 script.py 的执行权限,使用命令:chmod a+x script.py。 如果需要,您可以使用已设置的执行权限对您的 script.py 进行版本控制。
stages:
     - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_TARGET_URL: http://test-deployment/
  FUZZAPI_OVERRIDES_FILE: api-fuzzing-overrides.json
  FUZZAPI_OVERRIDES_CMD: renew_token.py
  FUZZAPI_OVERRIDES_INTERVAL: 300

调试覆盖

引入于 14.8 版本。

默认情况下,覆盖命令的输出是隐藏的。如果覆盖命令返回非零退出代码,则该命令将显示为作业输出的一部分。或者,您可以将变量 FUZZAPI_OVERRIDES_CMD_VERBOSE 设置为任何值,以便在生成时显示覆盖命令输出。这在测试覆盖脚本时很有用,但之后应该禁用它,因为它会减慢测试速度。

还可以将脚本中的消息写入日志文件,当作业完成或失败时收集该日志文件。日志文件必须在特定位置创建并遵循命名约定。

在正常运行作业期间脚本意外失败的情况下,向覆盖脚本添加一些基本日志记录非常有用。日志文件作为作业的产物自动包含在内,允许您在作业完成后下载它。

按照我们的示例,我们在环境变量 FUZZAPI_OVERRIDES_CMD 中提供了 renew_token.py。请注意脚本中:

  • 日志文件保存在环境变量 CI_PROJECT_DIR 指示的位置。
  • 日志文件名应该匹配 gl-*.log
#!/usr/bin/env python

# Example of an overrides command

# Override commands can update the overrides json file
# with new values to be used.  This is a great way to
# update an authentication token that will expire
# during testing.

import logging
import json
import os
import requests
import backoff

# [1] Store log file in directory indicated by env var CI_PROJECT_DIR
working_directory = os.environ.get( 'CI_PROJECT_DIR')
overrides_file_name = os.environ.get('FUZZAPI_OVERRIDES_FILE', 'api-fuzzing-overrides.json')
overrides_file_path = os.path.join(working_directory, overrides_file_name)

# [2] File name should match the pattern: gl-*.log
log_file_path = os.path.join(working_directory, 'gl-user-overrides.log')

# Set up logger
logging.basicConfig(filename=log_file_path, level=logging.DEBUG)

# Use `backoff` decorator to retry in case of transient errors.
@backoff.on_exception(backoff.expo,
                      (requests.exceptions.Timeout,
                       requests.exceptions.ConnectionError),
                       max_time=30)
def get_auth_response():
    authorization_url = 'https://authorization.service/api/get_api_token'
    return requests.get(
        f'{authorization_url}',
        auth=(os.environ.get('AUTH_USER'), os.environ.get('AUTH_PWD'))
    )

# In our example, access token is retrieved from a given endpoint
try:

    # Performs a http request, response sample:
    # { "Token" : "b5638ae7-6e77-4585-b035-7d9de2e3f6b3" }
    response = get_auth_response()

    # Check that the request is successful. may raise `requests.exceptions.HTTPError`
    response.raise_for_status()

    # Gets JSON data
    response_body = response.json()

# If needed specific exceptions can be caught
# requests.ConnectionError                  : A network connection error problem occurred
# requests.HTTPError                        : HTTP request returned an unsuccessful status code. [Response.raise_for_status()]
# requests.ConnectTimeout                   : The request timed out while trying to connect to the remote server
# requests.ReadTimeout                      : The server did not send any data in the allotted amount of time.
# requests.TooManyRedirects                 : The request exceeds the configured number of maximum redirections
# requests.exceptions.RequestException      : All exceptions that related to Requests
except json.JSONDecodeError as json_decode_error:
    # logs errors related decoding JSON response
    logging.error(f'Error, failed while decoding JSON response. Error message: {json_decode_error}')
    raise
except requests.exceptions.RequestException as requests_error:
    # logs  exceptions  related to `Requests`
    logging.error(f'Error, failed while performing HTTP request. Error message: {requests_error}')
    raise
except Exception as e:
    # logs any other error
    logging.error(f'Error, unknown error while retrieving access token. Error message: {e}')
    raise

# computes object that holds overrides file content.
# It uses data fetched from request
overrides_data = {
    "headers": {
        "Authorization": f"Token {response_body['Token']}"
    }
}

# log entry informing about the file override computation
logging.info("Creating overrides file: %s" % overrides_file_path)

# attempts to overwrite the file
try:
    if os.path.exists(overrides_file_path):
        os.unlink(overrides_file_path)

    # overwrites the file with our updated dictionary
    with open(overrides_file_path, "wb+") as fd:
        fd.write(json.dumps(overrides_data).encode('utf-8'))
except Exception as e:
    # logs any other error
    logging.error(f'Error, unknown error when overwriting file {overrides_file_path}. Error message: {e}')
    raise

# logs informing override has finished successfully
logging.info("Override file has been updated")

# end

在覆盖命令示例中,Python 脚本依赖于 backoff 库。为了确保在执行 Python 脚本之前安装了库,FUZZAPI_PRE_SCRIPT 设置为将安装覆盖命令的依赖项的脚本。 例如,以下脚本 user-pre-scan-set-up.sh

#!/bin/bash

# user-pre-scan-set-up.sh
# Ensures python dependencies are installed

echo "**** install python dependencies ****"

python3 -m ensurepip
pip3 install --no-cache --upgrade \
    pip \
    requests \
    backoff

echo "**** python dependencies installed ****"

# end

您必须更新配置以将 FUZZAPI_PRE_SCRIPT 设置为我们新的 user-pre-scan-set-up.sh 脚本。例如:

stages:
     - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_TARGET_URL: http://test-deployment/
  FUZZAPI_PRE_SCRIPT: user-pre-scan-set-up.sh
  FUZZAPI_OVERRIDES_FILE: api-fuzzing-overrides.json
  FUZZAPI_OVERRIDES_CMD: renew_token.py
  FUZZAPI_OVERRIDES_INTERVAL: 300

在前面的示例中,您可以使用脚本 user-pre-scan-set-up.sh 来安装新的运行时或应用程序,稍后您可以在覆盖命令中使用这些运行时或应用程序。

排除路径

引入于 14.0 版本。

在测试 API 时,排除某些路径会很有用。例如,您可能会排除对身份验证服务或旧版本 API 的测试。要排除路径,请使用 FUZZAPI_EXCLUDE_PATHS CI/CD 变量。这个变量在您的 .gitlab-ci.yml 文件中指定。要排除多个路径,请使用 ; 字符分隔条目。在提供的路径中,您可以使用单字符通配符 ?* 作为多字符通配符。

要验证路径是否已排除,请查看作业输出的 Tested OperationsExcluded Operations 部分。您不应该在 Tested Operations 下看到任何排除的路径。

2021-05-27 21:51:08 [INF] API Fuzzing: --[ Tested Operations ]-------------------------
2021-05-27 21:51:08 [INF] API Fuzzing: 201 POST http://target:7777/api/users CREATED
2021-05-27 21:51:08 [INF] API Fuzzing: ------------------------------------------------
2021-05-27 21:51:08 [INF] API Fuzzing: --[ Excluded Operations ]-----------------------
2021-05-27 21:51:08 [INF] API Fuzzing: GET http://target:7777/api/messages
2021-05-27 21:51:08 [INF] API Fuzzing: POST http://target:7777/api/messages
2021-05-27 21:51:08 [INF] API Fuzzing: ------------------------------------------------

排除路径的示例

此示例不包括 /auth 资源。这不排除子资源(/auth/child)。

variables:
  FUZZAPI_EXCLUDE_PATHS: /auth

为了排除 /auth 和子资源 (/auth/child),我们使用通配符。

variables:
  FUZZAPI_EXCLUDE_PATHS: /auth*

要排除多个路径,我们可以使用 ; 字符。在这个例子中,我们排除了 /auth*/v1/*

variables:
  FUZZAPI_EXCLUDE_PATHS: /auth*;/v1/*

排除参数

引入于 14.10 版本。

在测试 API 时,您可能希望从测试中排除参数(查询字符串、标题或正文元素)。这可能是需要的,因为参数总是会导致失败、减慢测试速度或其他原因。要排除参数,您可以使用以下变量之一:FUZZAPI_EXCLUDE_PARAMETER_ENVFUZZAPI_EXCLUDE_PARAMETER_FILE

FUZZAPI_EXCLUDE_PARAMETER_ENV 允许提供包含排除参数的 JSON 字符串。如果 JSON 很短且不会经常更改,这是一个不错的选择。另一个选项是变量 FUZZAPI_EXCLUDE_PARAMETER_FILE。此变量设置为可以检入存储库的文件路径,由另一个作业创建为产物,或在运行时使用 FUZZAPI_PRE_SCRIPT 从预脚本生成。

使用 JSON 文档排除参数

JSON 文档包含一个 JSON 对象,该对象使用特定属性来识别应排除的参数。 您可以提供以下属性以在扫描过程中排除特定参数:

  • headers:使用此属性排除特定的 headers。该属性的值是要排除的 headers 名称数组。名称不区分大小写。
  • cookies:使用此属性的值排除特定的 cookie。该属性的值是要排除的 cookie 名称数组。名称区分大小写。
  • query:使用此属性从查询字符串中排除特定字段。该属性的值是要排除的查询字符串中的字段名称数组。名称区分大小写。
  • body-form:使用此属性可从使用媒体类型 application/x-www-form-urlencoded 的请求中排除特定字段。该属性的值是要排除的正文中的字段名称数组。名称区分大小写。
  • body-json:使用此属性可以从使用媒体类型 application/json 的请求中排除特定的 JSON 节点。该属性的值是一个数组,数组的每个条目都是一个 [JSON Path] (https://goessner.net/articles/JsonPath/) 表达式。
  • body-xml:使用此属性可以从使用媒体类型 application/xml 的请求中排除特定的 XML 节点。该属性的值是一个数组,数组的每个条目都是一个 XPath v2 表达式。

以下 JSON 文档是排除参数的预期结构示例。

{
  "headers": [
    "header1",
    "header2"
  ],
  "cookies": [
    "cookie1",
    "cookie2"
  ],
  "query": [
    "query-string1",
    "query-string2"
  ],
  "body-form": [
    "form-param1",
    "form-param2"
  ],
  "body-json": [
    "json-path-expression-1",
    "json-path-expression-2"
  ],
  "body-xml" : [
    "xpath-expression-1",
    "xpath-expression-2"
  ]
}

示例

排除单个 header

要排除 header Upgrade-Insecure-Requests,请将 header 属性的值设置为具有标头名称的数组:[ "Upgrade-Insecure-Requests" ]。例如,JSON 文档如下所示:

{
  "headers": [ "Upgrade-Insecure-Requests" ]
}

Header 名称不区分大小写,因此标头名称 UPGRADE-INSECURE-REQUESTS 等价于 Upgrade-Insecure-Requests

要排除 header Authorization 和 cookie PHPSESSIDcsrftoken,请将 headers 属性的值设置为标头名称为 [ "Authorization" ] 的数组,并将 cookies 属性的值设置为具有 cookie 的名称 [ "PHPSESSID", "csrftoken" ]。例如,JSON 文档如下所示:

{
  "headers": [ "Authorization" ],
  "cookies": [ "PHPSESSID", "csrftoken" ]
}
排除 body-form 参数

要在使用 application/x-www-form-urlencoded 的请求中排除 password 字段,请将 body-form 属性的值设置为字段名称为 [ "password" ] 的数组。 例如,JSON 文档如下所示:

{
  "body-form":  [ "password" ]
}

当请求使用内容类型 application/x-www-form-urlencoded时,排除参数使用 body-form

使用 JSON 路径排除特定 JSON 节点

要在根对象中排除 schema 属性,请将 body-json 属性的值设置为具有 JSON 路径表达式 [ "$.schema" ] 的数组。

JSON Path 表达式使用特殊语法来识别 JSON 节点:$ 指的是 JSON 文档的根,. 指的是当前对象(在我们的例子中是根对象),而文本 schema 指的是一个 属性名称。因此,JSON 路径表达式 $.schema 引用了根对象中的属性 schema。例如,JSON 文档如下所示:

{
  "body-json": [ "$.schema" ]
}

当请求使用内容类型 application/json 时,排除参数使用 body-jsonbody-json 中的每个条目都应该是一个 JSON 路径表达式。在 JSON 路径中,$*. 等字符具有特殊含义。

使用 JSON 路径排除多个 JSON 节点

要在根级别排除 users 数组的每个条目上的属性 password,请将 body-json 属性的值设置为具有 JSON 路径表达式 [ "$.users[*].paswword “ ]

JSON 路径表达式以 $ 开头表示根节点,并使用 . 表示当前节点。然后,它使用 users 来引用属性并使用字符 [] 将索引包含在要使用的数组中,而不是提供数字作为索引,您可以使用 * 来指定任何 指数。在索引引用之后,我们找到.,它现在引用数组中任何给定的选定索引,前面有一个属性名称password

例如,JSON 文档如下所示:

{
  "body-json": [ "$.users[*].paswword" ]
}

当请求使用内容类型 application/json 时,排除参数使用 body-jsonbody-json 中的每个条目都应该是一个 JSON 路径表达式。在 JSON 路径中,$*. 等字符具有特殊含义。

排除 XML 属性

要排除位于根元素 credentials 中的名为 isEnabled 的属性,请将 body-xml 属性的值设置为具有 XPath 表达式 [ "/credentials/@isEnabled" ] 的数组。

XPath 表达式 /credentials/@isEnabled/ 开头表示 XML 文档的根,然后是单词 credentials,表示要匹配的元素的名称。 它使用 / 来引用前一个 XML 元素的节点,使用字符 @ 表示名称 isEnable 是一个属性。

例如,JSON 文档如下所示:

{
  "body-xml": [
    "/credentials/@isEnabled"
  ]
}

当请求使用内容类型 application/xml 时,排除参数使用 body-xmlbody-xml 中的每个条目都应该是一个 XPath v2 表达式。在 XPath 表达式中,诸如@/:[] 等字符具有特殊含义。

排除 XML 元素的文本

要排除根节点 credentials 中包含的 username 元素的文本,请将 body-xml 属性的值设置为具有 XPath 表达式 [/credentials/username/text()" ] 的数组。

在 XPath 表达式 /credentials/username/text() 中,第一个字符 / 表示根 XML 节点,然后在它之后表示 XML 元素的名称 credentials。类似地,字符 / 指代当前元素,后跟新 XML 元素的名称 username。最后一部分有一个引用当前元素的/,并使用一个称为text() 的XPath 函数来标识当前元素的文本。

例如,JSON 文档如下所示:

{
  "body-xml": [
    "/credentials/username/text()"
  ]
}

当请求使用内容类型 application/xml 时,排除参数使用 body-xmlbody-xml 中的每个条目都应该是一个 XPath v2 表达式。在 XPath 表达式中,诸如 @/:[] 等字符具有特殊含义。

排除 XML 元素

要排除根节点 credentials 中包含的元素 username,请将 body-xml 属性的值设置为具有 XPath 表达式 [/credentials/username" ] 的数组。

在 XPath 表达式 /credentials/username 中,第一个字符 / 指的是根 XML 节点,然后在它之后表示 XML 元素的名称 credentials。类似地,字符 / 指代当前元素,后跟新 XML 元素的名称 username

例如,JSON 文档如下所示:

{
  "body-xml": [
    "/credentials/username"
  ]
}

当请求使用内容类型 application/xml 时,排除参数使用 body-xmlbody-xml 中的每个条目都应该是一个 XPath v2 表达式。在 XPath 表达式中,诸如 @/:[] 等字符具有特殊含义。

使用命名空间排除 XML 节点

要排除在命名空间 s 中定义并包含在 credentials 根节点中的 XML 元素 login,请将 body-xml 属性的值设置为具有 XPath 表达式 [ "/credentials/s:login”]

在 XPath 表达式 /credentials/s:login 中,第一个字符 / 表示根 XML 节点,然后在它之后表示 XML 元素的名称 credentials。类似地,字符 / 指代当前元素,后跟新 XML 元素的名称 s:login。 请注意,name 包含字符 :,该字符将命名空间与节点名称分开。

命名空间名称应该在作为正文请求一部分的 XML 文档中定义。您可以查看规范文档 HAR、OpenAPI 或 Postman Collection 文件中的命名空间。

{
  "body-xml": [
    "/credentials/s:login"
  ]
}

当请求使用内容类型 application/xml 时,排除参数使用 body-xmlbody-xml 中的每个条目都应该是一个 XPath v2 表达式。在 XPath 表达式中,诸如 @/:[] 等字符具有特殊含义。

使用 JSON 字符串

要提供排除 JSON 文档,请使用 JSON 字符串设置变量 FUZZAPI_EXCLUDE_PARAMETER_ENV。在以下示例中,.gitlab-ci.ymlFUZZAPI_EXCLUDE_PARAMETER_ENV 变量设置为 JSON 字符串:

stages:
     - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_TARGET_URL: http://test-deployment/
  FUZZAPI_EXCLUDE_PARAMETER_ENV: '{ "headers": [ "Upgrade-Insecure-Requests" ] }'

使用文件

要提供排除 JSON 文档,请使用 JSON 文件路径设置变量 FUZZAPI_EXCLUDE_PARAMETER_FILE。文件路径是相对于作业当前工作目录的。在以下示例 .gitlab-ci.yml 文件中,FUZZAPI_EXCLUDE_PARAMETER_FILE 变量设置为 JSON 文件路径:

stages:
     - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_PROFILE: Quick
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_TARGET_URL: http://test-deployment/
  FUZZAPI_EXCLUDE_PARAMETER_FILE: api-fuzzing-exclude-parameters.json

api-fuzzing-exclude-parameters.json 是一个 JSON 文档,遵循排除参数文档的结构。

排除 URL

引入于 14.10 版本。

作为按路径排除的替代方法,您可以使用 FUZZAPI_EXCLUDE_URLS CI/CD 变量按 URL 中的任何其他组件进行过滤。这个变量可以在您的 .gitlab-ci.yml 文件中设置。该变量可以存储多个值,以逗号 (,) 分隔。每个值都是一个正则表达式。因为每个条目都是一个正则表达式,所以像 .* 这样的条目会排除所有 URL,因为它是一个匹配所有内容的正则表达式。

在您的作业输出中,您可以检查是否有任何 URL 与 FUZZAPI_EXCLUDE_URLS 中提供的任何正则表达式匹配。匹配操作列在 排除操作 部分。排除操作 中列出的操作不应列在 测试操作 部分中。例如,作业输出的以下部分:

2021-05-27 21:51:08 [INF] API Fuzzing: --[ Tested Operations ]-------------------------
2021-05-27 21:51:08 [INF] API Fuzzing: 201 POST http://target:7777/api/users CREATED
2021-05-27 21:51:08 [INF] API Fuzzing: ------------------------------------------------
2021-05-27 21:51:08 [INF] API Fuzzing: --[ Excluded Operations ]-----------------------
2021-05-27 21:51:08 [INF] API Fuzzing: GET http://target:7777/api/messages
2021-05-27 21:51:08 [INF] API Fuzzing: POST http://target:7777/api/messages
2021-05-27 21:51:08 [INF] API Fuzzing: ------------------------------------------------
noteFUZZAPI_EXCLUDE_URLS 中的每个值都是一个正则表达式。诸如 .*$ 之类的字符在正则表达式中具有特殊的含义。

示例

排除 URL 和子资源

以下示例不包括 URL http://target/api/auth 及其子资源。

stages:
  - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_TARGET_URL: http://target/
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_EXCLUDE_URLS: http://target/api/auth
排除两个 URL 并允许其子资源

排除 URL http://target/api/buyhttp://target/api/sell 但允许扫描它们的子资源,例如:http://target/api/buy/toy http://target/api/sell/chair 您可以使用值 http://target/api/buy/$,http://target/api/sell/$。该值使用两个正则表达式,每个正则表达式由一个 , 字符分隔。因此,它包含 http://target/api/buy$http://target/api/sell$。在每个正则表达式中,结尾的 $ 字符指出匹配的 URL 应该在哪里结束。

stages:
  - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_TARGET_URL: http://target/
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_EXCLUDE_URLS: http://target/api/buy/$,http://target/api/sell/$
排除两个 URL 及其子资源

为了排除 URL:http://target/api/buyhttp://target/api/sell,以及它们的子资源。为了提供多个 URL,我们使用 , 字符,如下所示:

stages:
  - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_TARGET_URL: http://target/
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_EXCLUDE_URLS: http://target/api/buy,http://target/api/sell
使用正则表达式排除 URL

为了完全排除 https://target/api/v1/user/createhttps://target/api/v2/user/create 或任何其他版本(v3v4 和更多)。我们可以使用 https://target/api/v.*/user/create$,在前面的正则表达式中 . 表示任意字符,* 表示零次或多次,另外 $ 表示 URL 应该在那里结束。

为了完全排除 https://target/api/v1/user/createhttps://target/api/v2/user/create 或任何其他版本(v3v4 和更多)。我们可以使用 https://target/api/v.*/user/create$。在前面的正则表达式中:

  • . 表示任何字符。
  • * 表示零次或多次。
  • $ 表示 URL 应该在那里结束。
stages:
  - fuzz

include:
  - template: API-Fuzzing.gitlab-ci.yml

variables:
  FUZZAPI_TARGET_URL: http://target/
  FUZZAPI_OPENAPI: test-api-specification.json
  FUZZAPI_EXCLUDE_URLS: https://target/api/v.*/user/create$

Header Fuzzing

由于许多技术堆栈会出现大量误报,因此默认情况下禁用 header 模糊测试。启用 header 模糊测试后,您必须指定要包含在模糊测试中的 headers 列表。

默认配置文件中的每个配置文件都有一个 GeneralFuzzingCheck 条目。此检查执行 header 模糊测试。在 Configuration 部分下,您必须更改 HeaderFuzzingHeaders 设置以启用 header 模糊测试。

此片段显示了 Quick-10 配置文件的默认配置,其中禁用了 header 模糊测试:

- Name: Quick-10
  DefaultProfile: Empty
  Routes:
  - Route: *Route0
    Checks:
    - Name: FormBodyFuzzingCheck
      Configuration:
        FuzzingCount: 10
        UnicodeFuzzing: true
    - Name: GeneralFuzzingCheck
      Configuration:
        FuzzingCount: 10
        UnicodeFuzzing: true
        HeaderFuzzing: false
        Headers:
    - Name: JsonFuzzingCheck
      Configuration:
        FuzzingCount: 10
        UnicodeFuzzing: true
    - Name: XmlFuzzingCheck
      Configuration:
        FuzzingCount: 10
        UnicodeFuzzing: true

HeaderFuzzing 是一个布尔值,用于打开和关闭 header 模糊测试。默认设置为 false 表示关闭。要打开 header 模糊测试,请将此设置更改为 true

    - Name: GeneralFuzzingCheck
      Configuration:
        FuzzingCount: 10
        UnicodeFuzzing: true
        HeaderFuzzing: true
        Headers:

Headers 是要进行模糊测试的 headers 列表。只有列出的 header 是模糊的。要模糊 API 使用的 header,请使用语法为它添加一个条目 - Name: HeaderName。例如,要对自定义 header X-Custom 进行模糊测试,请添加 - Name: X-Custom

    - Name: GeneralFuzzingCheck
      Configuration:
        FuzzingCount: 10
        UnicodeFuzzing: true
        HeaderFuzzing: true
        Headers:
          - Name: X-Custom

您现在有一个配置来模糊 header X-Custom。使用相同的符号列出其他 headers:

    - Name: GeneralFuzzingCheck
      Configuration:
        FuzzingCount: 10
        UnicodeFuzzing: true
        HeaderFuzzing: true
        Headers:
          - Name: X-Custom
          - Name: X-AnotherHeader

根据需要对每个配置文件重复此配置。

运行您的第一次扫描

正确配置后,CI/CD 流水线包含一个 fuzz 阶段和一个 apifuzzer_fuzzapifuzzer_fuzz_dnd 作业。仅当提供无效配置时,作业才会失败。在正常操作期间,即使在模糊测试期间识别出故障,作业也始终成功。

故障显示在带有套件名称的 安全 流水线选项卡上。在针对仓库默认分支进行测试时,模糊测试错误也会显示在安全与合规性的漏洞报告页面上。

为了防止报告的故障数量过多,API 模糊扫描器限制了它报告的故障数量。

查看模糊故障

API Fuzzing 分析器生成一个 JSON 报告,该报告被收集并用于将故障填充到极狐GitLab 漏洞屏幕中。Fuzzing 错误显示为严重性为未知的漏洞。

API fuzzing 发现的故障需要手动调查,并且与特定的漏洞类型无关。他们需要调查以确定它们是否是安全问题,以及是否应该修复它们。请参阅处理误报,了解有关您可以进行配置更改以限制报告的误报数量的信息。

查看 API Fuzzing 漏洞的详细信息

引入于 13.7 版本。

API Fuzzing 检测到的故障发生在实时 Web 应用程序中,需要手动调查以确定它们是否是漏洞。Fuzzing 故障作为严重性未知的漏洞包含在内。为了便于调查模糊测试故障,提供了有关发送和接收的 HTTP 消息的详细信息以及所做修改的描述。

请按照以下步骤查看模糊测试故障的详细信息:

  1. 您可以查看项目中的故障或合并请求:

    • 在项目中,转到项目的 安全与合规 > 漏洞报告 页面。 此页面仅显示来自默认分支的所有漏洞。
    • 在合并请求中,转到合并请求的 安全 部分并选择 展开 按钮。API Fuzzing 故障可在标记为 API Fuzzing 检测到 N 个潜在漏洞 的部分中找到。选择标题,显示故障详情。
  2. 选择故障的标题以显示故障的详细信息。详情如下表所述。

    字段 描述
    Description 故障描述,包括修改内容。
    Project 检测到漏洞的命名空间和项目。
    Method 用于检测漏洞的 HTTP 方法。
    URL 检测到漏洞的 URL。
    Request 导致故障的 HTTP 请求。
    Unmodified Response 来自未修改请求的响应。是正常工作响应的样子。
    Actual Response 从模糊请求收到的响应。
    Evidence 我们如何确定发生了故障。
    Identifiers 用于查找此故障的模糊检查。
    Severity 发现的严重性始终是未知的。
    Scanner Type 用于执行测试的扫描器。

安全仪表盘

Fuzzing 错误显示为严重性为未知的漏洞。安全仪表盘是了解您的组、项目和流水线中所有安全漏洞的好地方。有关详细信息,请参阅安全仪表盘文档

与漏洞交互

Fuzzing 错误显示为严重性为未知的漏洞。 一旦发现故障,您就可以与之交互。阅读有关如何解决漏洞的更多信息。

处理误报

误报可以通过两种方式处理:

  • 关闭产生误报的检查。这可以防止检查产生任何故障。示例检查是 JSON 模糊检查和表单正文模糊检查。
  • Fuzzing 检查有几种检测故障的方法,称为 Asserts,也可以关闭和配置。例如,API fuzzer 默认使用 HTTP 状态代码来帮助识别什么时候是真正的问题。如果 API 在测试期间返回 500 错误,则会产生错误。这并不总是需要的,因为一些框架经常返回 500 错误。

关闭检查

检查执行特定类型的测试,并且可以为特定配置文件打开和关闭。默认配置文件定义了几个您可以使用的配置文件。配置文件中的配置文件定义列出了扫描期间活动的所有检查。要关闭特定检查,请将其从配置文件的配置文件定义中删除。配置文件在配置文件的 Profiles 部分定义。

示例配置文件定义:

Profiles:
  - Name: Quick-10
    DefaultProfile: Quick
    Routes:
      - Route: *Route0
        Checks:
          - Name: FormBodyFuzzingCheck
            Configuration:
              FuzzingCount: 10
              UnicodeFuzzing: true
          - Name: GeneralFuzzingCheck
            Configuration:
              FuzzingCount: 10
              UnicodeFuzzing: true
          - Name: JsonFuzzingCheck
            Configuration:
              FuzzingCount: 10
              UnicodeFuzzing: true
          - Name: XmlFuzzingCheck
            Configuration:
              FuzzingCount: 10
              UnicodeFuzzing: true

要关闭 General Fuzzing Check,您可以删除以下行:

- Name: GeneralFuzzingCheck
  Configuration:
    FuzzingCount: 10
    UnicodeFuzzing: true

这会产生以下 YAML:

- Name: Quick-10
  DefaultProfile: Quick
  Routes:
    - Route: *Route0
      Checks:
        - Name: FormBodyFuzzingCheck
          Configuration:
            FuzzingCount: 10
            UnicodeFuzzing: true
        - Name: JsonFuzzingCheck
          Configuration:
            FuzzingCount: 10
            UnicodeFuzzing: true
        - Name: XmlFuzzingCheck
          Configuration:
            FuzzingCount: 10
            UnicodeFuzzing: true

关闭 Assertion 进行检查

Assertion 检测检查产生的测试中的错误。许多检查支持多个 assertions,例如日志分析、响应分析和状态代码。当发现故障时,提供使用的 assertions。要确定哪些 assertions 是默认开启的,请参阅配置文件中的检查默认配置。该部分称为 Checks

此示例显示了 FormBody 模糊检查:

Checks:
  - Name: FormBodyFuzzingCheck
    Configuration:
      FuzzingCount: 30
      UnicodeFuzzing: true
    Assertions:
      - Name: LogAnalysisAssertion
      - Name: ResponseAnalysisAssertion
      - Name: StatusCodeAssertion

在这里您可以看到默认情况下启用了三个 assertions。误报的常见来源是 StatusCodeAssertion。要关闭它,请在 Profiles 部分修改其配置。这个例子只提供了另外两个 assertions(LogAnalysisAssertionResponseAnalysisAssertion)。这可以防止 FormBodyFuzzingCheck 使用 StatusCodeAssertionyaml Profiles: - Name: Quick-10 DefaultProfile: Quick Routes: - Route: *Route0 Checks: - Name: FormBodyFuzzingCheck Configuration: FuzzingCount: 10 UnicodeFuzzing: true Assertions: - Name: LogAnalysisAssertion - Name: ResponseAnalysisAssertion - Name: GeneralFuzzingCheck Configuration: FuzzingCount: 10 UnicodeFuzzing: true - Name: JsonFuzzingCheck Configuration: FuzzingCount: 10 UnicodeFuzzing: true - Name: XmlInjectionCheck Configuration: FuzzingCount: 10 UnicodeFuzzing: true

在离线环境中运行 API 模糊测试

对于通过 Internet 对外部资源进行有限、受限或间歇性访问的环境中的私有化部署实例,需要进行一些调整才能使 Web API Fuzz 测试作业成功运行。

步骤:

  1. 在本地容器 registry 中托管 Docker 镜像。
  2. SECURE_ANALYZERS_PREFIX 设置为本地容器 registry。

API Fuzzing 的 Docker 镜像必须从公共 registry 中提取(下载),然后推送(导入)到本地 registry 中。极狐GitLab 容器镜像库可用于在本地托管 Docker 镜像。这个过程可以使用一个特殊的模板来执行。有关说明,请参阅将 Docker 镜像加载到您的离线主机上

一旦 Docker 镜像在本地托管,SECURE_ANALYZERS_PREFIX 变量就会设置为本地镜像库的位置。必须设置该变量,以便连接 /api-security:2 产生有效的镜像位置。

例如,为以下镜像 registry.gitlab.cn/security-products/api-security:2 设置了一个镜像库:

SECURE_ANALYZERS_PREFIX: "registry.gitlab.cn/security-products"

note设置 SECURE_ANALYZERS_PREFIX 会更改所有极狐GitLab 安全模板的 Docker 镜像库位置。

有关详细信息,请参阅离线环境