ウェブAPIファズテスト

Web APIファジングはAPIオペレーションパラメーターのファズテストを行います。ファズテストでは、オペレーションパラメータに予期しない値を設定し、APIバックエンドで予期しない動作やエラーを引き起こします。これは、他の QA プロセスが見逃す可能性のあるバグや潜在的なセキュリティ問題を発見するのに役立ちます。

GitLab Secureの他のセキュリティスキャナと独自のテストプロセスに加えて、ファズテストを使用することをお勧めします。GitLab CI/CDを使っている場合は、CI/CDワークフローの一環としてファズテストを実行することができます。

概要については、Web API Fuzzingをご覧ください。

Web API ファジングの実行時

Web API ファジングはfuzz CI/CD パイプラインのステージで fuzz実行されます。fuzz APIファジングが最新のコードをスキャンすることを保証するために、CI/CDパイプラインはステージの1つ前のステージで変更をテスト環境にデプロイする必要が fuzzあります。

APIファジングテンプレートに以下の変更が加えられたことに注意してください:

  • GitLab 14.0以降では、.gitlab-ci.yml ファイルでfuzz ステージを定義する必要があります。
  • GitLab 13.12以前では、APIファジングテンプレートはbuildtestdeployfuzz ステージを fuzz定義します。fuzz ステージは fuzzデフォルトで最後に実行されます。定義済みのステージは非推奨となり、API-Fuzzing.latest.gitlab-ci.yml テンプレートから削除されました。将来のGitLabバージョンで削除する予定です。

パイプラインが毎回同じWebサーバーにデプロイされるように設定されている場合、別のパイプラインがまだ実行されている間にパイプラインを実行すると、あるパイプラインが別のパイプラインのコードを上書きするという競合状態を引き起こす可能性があります。スキャンするAPIは、ファジングスキャン期間中は変更しないようにします。APIへの変更は、ファジングスキャナーからのものだけにしてください。スキャン中に(ユーザー、スケジュールされたタスク、データベースの変更、コードの変更、他のパイプライン、または他のスキャナーによって)APIに加えられた変更は、不正確な結果を引き起こす可能性があります。

Web API ファジングスキャンは、以下の方法で実行できます:

これらのメソッドを使ったプロジェクトの例があります:

Web API ファジングの有効化

要件

  • 以下の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ファジングを有効にするには

GitLab 14.0以降では、APIファジング設定ファイルはリポジトリのルートではなく、リポジトリの.gitlab ディレクトリになければなりません。

Web API ファジング設定フォーム

GitLab 13.10で導入されました

APIファジング設定フォームは、プロジェクトのAPIファジング設定を作成または変更するのに役立ちます。このフォームでは、最も一般的なAPIファジングオプションの値を選択することができ、GitLab CI/CD設定に貼り付けることができるYAMLスニペットをビルドします。

UIでWeb APIファジングを設定

API Fuzzingの設定スニペットを生成します:

  1. 左のサイドバーで「検索」または「移動」を選択してあなたのプロジェクトを検索します。
  2. セキュア > セキュリティ設定を選択します。
  3. API Fuzzing] の行で、[Enable API Fuzzing] を選択します。
  4. フィールドを入力します。詳細については、利用可能なCI/CD変数を参照してください。
  5. Generate code snippet を選択します。モーダルが開き、フォームで選択したオプションに対応する YAML スニペットが表示されます。
  6. 以下のいずれかを行いましょう:
    1. スニペットをクリップボードにコピーするには、「コードのみをコピー」を選択します。
    2. スニペットをプロジェクトの.gitlab-ci.yml ファイルに追加するには、Copy code を選択し、.gitlab-ci.yml ファイルを開きます。パイプラインエディターが開きます。
      1. スニペットを.gitlab-ci.yml ファイルに貼り付けます。
      2. Lintタブを選択し、編集した.gitlab-ci.yml ファイルが有効であることを確認します。
      3. [Edit] タブを 選択 し、 [Commit changes] を** 選択 **します。

スニペットが.gitlab-ci.yml ファイルにコミットされると、パイプラインに API Fuzzing ジョブが含まれます。

OpenAPIの仕様

  • OpenAPI 仕様 v3.0 のサポートが GitLab 13.9 で導入されました。
  • YAMLフォーマットによるOpenAPI仕様のサポートがGitLab 14.0から導入されました。
  • OpenAPI Specification v3.1のサポートがGitLab 14.2から導入されました。
  • メディアタイプapplication/xml の生成サポートが GitLab 14.8 で導入されました。
  • メディアタイプの選択機能がGitLab 14.10から導入されました。

OpenAPI仕様(以前のSwagger仕様)は、REST APIのためのAPI記述フォーマットです。このセクションでは、テスト対象のAPIに関する情報を提供するOpenAPI Specificationを使用してAPIファジングを設定する方法を示します。OpenAPI仕様は、ファイルシステムのリソースまたはURLとして提供されます。JSON と YAML の両方の OpenAPI フォーマットがサポートされています。

API ファジングでは、リクエスト・ボディを生成するために 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 は、リストされたメディアタイプをチェックし、サポートされているメディアタイプごとにサンプルデータの生成を試みます。

  • GitLab 14.10以降では、デフォルトの動作として、サポートされているメディアタイプの中から1つを選択して使用します。最初にサポートされたメディアタイプがリストから選ばれます。この動作は設定可能です。
  • GitLab 14.9以前では、デフォルトの動作はサポートされている全てのメディアタイプを使ってテストを行います。つまり、2つのメディアタイプがリストされている場合(例えば、application/jsonapplication/xml )、テストはJSONを使って実行され、次にXMLを使って同じテストが実行されます。

異なるメディアタイプ(たとえば、application/jsonapplication/xml )を使用して同じオペレーション(たとえば、POST /user )をテストすることは、必ずしも望ましいことではありません。例えば、ターゲットのアプリケーショ ンがリクエストのコンテントタイプに関係なく同じコードを実行する場合、テストセッションを終了するのに時間がかかり、ターゲットのアプリケー ションによってはリクエストボディに関連する脆弱性を重複して報告するかもしれません。

環境FUZZAPI_OPENAPI_ALL_MEDIA_TYPES 変数によって、与えられたオペレーションに対するリクエストを生成するときに、1つのメディアタイプではなく、サポートされているすべてのメディアタイプを使うかどうかを指定 FUZZAPI_OPENAPI_ALL_MEDIA_TYPESできます。FUZZAPI_OPENAPI_ALL_MEDIA_TYPES 環境変数が FUZZAPI_OPENAPI_ALL_MEDIA_TYPES任意の値に設定されている場合、API Fuzzingは指定されたオペレーションで1つのメディアタイプではなく、サポートされているすべてのメディアタイプのリクエストを生成しようとします。これにより、提供されたメディアタイプごとにテストが繰り返されるため、テストに時間がかかるようになります。

あるいは、このFUZZAPI_OPENAPI_MEDIA_TYPES 変数を使ってテストするメディアタイプのリストを指定 FUZZAPI_OPENAPI_MEDIA_TYPESします。FUZZAPI_OPENAPI_MEDIA_TYPES 複数のメディアタイプを提供すると、選択されたメディアタイプごとにテストが実行されるため、テストに時間がかかります。環境変数 FUZZAPI_OPENAPI_MEDIA_TYPESがメディアタイプのリストに設定されているときは、 リクエストを作成するときにリストされたメディアタイプだけが含まれます。

FUZZAPI_OPENAPI_MEDIA_TYPES 、複数のメディアタイプはコロン(:)で区切る必要があります。例えば、リクエスト生成をメディアタイプapplication/x-www-form-urlencodedmultipart/form-data に制限するには、環境変数FUZZAPI_OPENAPI_MEDIA_TYPESapplication/x-www-form-urlencoded:multipart/form-dataに設定します。このリストでサポートされているメディアタイプだけがリクエスト作成時に 含まれますが、サポートされていないメディアタイプは常にスキップされます。メディアタイプのテキストは異なるセクションを含むかもしれません。例えば、application/vnd.api+json; charset=UTF-8type "/" [tree "."] subtype ["+" suffix]* [";" parameter]の複合です。 リクエスト生成時にメディアタイプをフィルタするとき、パラメータは考慮 されません。

環境変数FUZZAPI_OPENAPI_ALL_MEDIA_TYPESFUZZAPI_OPENAPI_MEDIA_TYPES でメディアタイプの扱い方を決めることができます。これらの設定は互いに排他的です。両方が有効な場合、API Fuzzingはエラーを報告します。

OpenAPI 仕様による Web API ファジングの設定

OpenAPI仕様を使ってGitLabでAPIファジングを設定するには:

  1. .gitlab-ci.yml ファイルにfuzz ステージを追加します。

  2. API-Fuzzing.gitlab-ci.yml テンプレート.gitlab-ci.yml ファイルに含めます

  3. .gitlab-ci.yml ファイルにFUZZAPI_PROFILE CI/CD 変数を追加して、プロファイルを指定します。プロファイルは、テストの実行回数を指定します。選択したプロファイルはQuick-10 に置き換えてください。詳細については、APIファジングプロファイルを参照してください。

    variables:
      FUZZAPI_PROFILE: Quick-10
    
  4. OpenAPI Specification の場所を指定します。ファイルまたは 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ファジングのための最小設定です。ここから次のことができます:

APIファジングの設定オプションの詳細については、利用可能なCI/CD変数を参照してください。

HTTPアーカイブ(HAR)

HTTPアーカイブフォーマット(HAR)は、HTTPトランザクションを記録するためのアーカイブファイルフォーマットです。GitLab API ファザーで使用する場合、HAR にはテストするウェブ API を呼び出した記録が含まれていなければなりません。APIファザーはすべてのリクエストを抽出し、テストの実行に使用します。

HARファイルの作成方法を含む詳細については、HTTPアーカイブフォーマットを参照してください。

caution
HAR ファイルには、認証トークン、API キー、セッションクッキーなどの機密情報が含まれている場合があります。リポジトリに追加する前に、HAR ファイルの内容をレビューすることをお勧めします。

HAR ファイルを使った Web API ファジングの設定

HAR ファイルを使用する API ファジングを設定します:

  1. .gitlab-ci.yml ファイルにfuzz ステージを追加します。

  2. API-Fuzzing.gitlab-ci.yml テンプレート.gitlab-ci.yml ファイルに含めます

  3. .gitlab-ci.yml ファイルにFUZZAPI_PROFILE CI/CD 変数を追加して、プロファイルを指定します。プロファイルは、テストの実行回数を指定します。選択したプロファイルはQuick-10 に置き換えてください。詳細については、APIファジングプロファイルを参照してください。

    variables:
      FUZZAPI_PROFILE: Quick-10
    
  4. HAR仕様の場所を指定します。ファイルまたはURLで指定できます。URLのサポートはGitLab 13.10以降で導入されました。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ファジングの設定オプションの詳細については、利用可能なCI/CD変数を参照してください。

GraphQL スキーマ

GraphQL SchemaのサポートはGitLab 15.4で導入されました。

GraphQLはAPIのクエリ言語であり、REST APIに代わるものです。API FuzzingはGraphQLエンドポイントのテストを複数の方法でサポートしています:

  • GraphQL Schemaを使ったテスト。GitLab 15.4で導入されました
  • GraphQLクエリの記録(HAR) 。
  • GraphQLクエリを含むPostmanコレクションを使用してテストします。

このセクションでは、GraphQLスキーマを使用してテストする方法を説明します。API FuzzingのGraphQLスキーマサポートは、イントロスペクションをサポートするエンドポイントからスキーマをクエリできます。GraphiQLのようなツールが動作するように、イントロスペクションはデフォルトで有効になっています。

API FuzzingのGraphQLエンドポイントURLによるスキャン

API FuzzingのGraphQLサポートは、スキーマのGraphQLエンドポイントをクエリできます。

note
このメソッドが正しく動作するためには、GraphQLエンドポイントがイントロスペクションクエリをサポートしている必要があります。

テスト対象のAPIに関する情報を提供するGraphQLエンドポイントURLを使用するようにAPI Fuzzingを設定するには、以下の手順に従います:

  1. .gitlab-ci.yml ファイルにAPI-Fuzzing.gitlab-ci.yml テンプレート含めます

  2. 例えば/api/graphql のように、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 スキーマファイルによる API ファジング

API FuzzingはGraphQLスキーマファイルを使用して、introspectionが無効になっているGraphQLエンドポイントを理解し、テストすることができます。GraphQL スキーマ ファイルを使用するには、introspection JSON 形式である必要があります。GraphQL スキーマは、オンラインのサードパーティツール(https://transform.tools/graphql-to-introspection-json)を使用して introspection JSON フォーマットに変換できます。

API Fuzzingを設定するには、テスト対象のAPIに関する情報を提供するGraphQlスキーマファイルを使用します:

  1. .gitlab-ci.yml ファイルにAPI-Fuzzing.gitlab-ci.yml テンプレート含めます

  2. 例えば/api/graphql のように、GraphQL エンドポイントのパスを指定します。FUZZAPI_GRAPHQL 変数を追加してパスを指定します。

  3. GraphQLスキーマファイルの場所を指定します。ファイルのパスまたは URL として場所を指定できます。FUZZAPI_GRAPHQL_SCHEMA 変数を追加して場所を指定します。

  4. ターゲットAPIインスタンスのベースURLも必要です。FUZZAPI_TARGET_URL 変数かenvironment_url.txt ファイルを使って指定してください。

    プロジェクトのルートにあるenvironment_url.txt ファイルに URL を追加すると、動的環境でのテストに最適です。詳細については、ドキュメントの動的環境ソリューションのセクションを参照してください。

GraphQLスキーマファイルを使用する完全な設定例:

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スキーマファイルの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 API Clientは、開発者やテスターが様々なタイプのAPIを呼び出すために使用する一般的なツールです。API定義をPostman Collectionファイルとしてエクスポートし、API Fuzzingで使用することができます。エクスポートする際は、サポートされているPostman Collectionのバージョン(v2.0またはv2.1)を選択してください。

GitLab APIファザーで使用する場合、Postmanコレクションには有効なデータでテストするWeb APIの定義が含まれている必要があります。APIファザーはすべてのAPI定義を抽出し、テストを実行するためにそれらを使用します。

caution
Postman Collectionファイルには、認証トークン、APIキー、セッションクッキーなどの機密情報が含まれている可能性があります。リポジトリに追加する前に、Postman Collectionファイルの内容をレビューすることをお勧めします。

Postman コレクションファイルによる Web API ファジングの設定

Postman Collectionファイルを使用するAPIファジングを設定します:

  1. .gitlab-ci.yml ファイルにfuzz ステージを追加します。

  2. API-Fuzzing.gitlab-ci.yml テンプレート.gitlab-ci.yml ファイルに含めます

  3. .gitlab-ci.yml ファイルにFUZZAPI_PROFILE CI/CD 変数を追加して、プロファイルを指定します。プロファイルは、テストの実行回数を指定します。選択したプロファイルはQuick-10 に置き換えてください。詳細については、APIファジングプロファイルを参照してください。

    variables:
      FUZZAPI_PROFILE: Quick-10
    
  4. Postman Collection仕様の場所を指定します。ファイルまたはURLで指定できます。URL サポートは GitLab 13.10 以降で導入されました。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ファジングの設定オプションの詳細については、利用可能なCI/CD変数を参照してください。

Postman の変数

  • GitLab15.1でPostman環境ファイルフォーマットのサポートが導入されました。
  • GitLab 15.1で複数の変数ファイルのサポートが導入されました。
  • Postman変数スコープをサポートしました:Global と Environment が GitLab 15.1 で導入されました。
Postman クライアントの変数

Postman では開発者がリクエストの様々な部分で使えるプレースホルダを定義できます。変数の使い方で説明したように、これらのプレースホルダは変数と呼ばれます。変数を使ってリクエストやスクリプトに値を保存したり再利用したりできます。たとえば、コレクションを編集してドキュメントに変数を追加できます:

Edit collection variable tab View

あるいは、環境変数を追加することもできます:

Edit environment variables View

URLやヘッダーなどのセクションで変数を使うことができます:

Edit request using variables View

Postmanは素敵なUXを体験できる基本的なクライアントツールから、スクリプトでAPIをテストしたり、二次リクエストをトリガーする複雑なコレクションを作成したり、途中で変数を設定したりできる、より複雑なエコシステムに成長しました。Postmanエコシステムのすべての機能がサポートされているわけではありません。例えば、スクリプトはサポートされていません。Postmanサポートの主な焦点は、Postmanクライアントで使用されるPostmanコレクション定義と、ワークスペース、環境、コレクション自体で定義された関連変数を取り込むことです。

Postmanは異なるスコープで変数を作成できます。それぞれのスコープは、Postmanツールでの可視性のレベルが異なります。例えば、すべてのオペレーション定義とワークスペースから見える_グローバル環境_スコープに変数を作成できます。また、特定の_環境_スコープに変数を作成し、その特定の環境が選択されているときのみ表示・使用されるようにすることもできます。例えば Postman エコシステムでは、Postman クライアントでリクエストを作成することができます。

Postman の変数スコープは難しいトピックで、誰もが知っているわけではありません。先に進む前に Postman ドキュメントの変数スコープを読むことを強くお勧めします。

上述したように、変数スコープには様々なものがあり、それぞれに目的があり、Postmanドキュメントに柔軟性を持たせるために使用することができます。Postmanのドキュメントにあるように、変数の値がどのように計算されるかについて重要な注意があります:

同じ名前の変数が2つの異なるスコープで宣言されている場合、最も狭いスコープの変数に格納されている値が使用されます。例えば、グローバル変数username 名とローカル変数名が usernameある場合、リクエストが実行されるときにはローカル変数の値が使われます。

以下はPostmanクライアントとAPI Fuzzingがサポートする変数のスコープをまとめたものです:

  • グローバル環境(Global)スコープはワークスペース全体で利用できる特別な事前定義された環境です。_グローバル環境_スコープを_グローバル_スコープと呼ぶこともあります。Postman Clientではグローバル環境をJSONファイルにエクスポートすることができ、API Fuzzingで使用することができます。
  • 環境スコープとは、ユーザーが Postman クライアントで作成した、名前付きの変数グループのことです。Postman クライアントはグローバル環境とともに1つのアクティブ環境をサポートします。ユーザーが作成したアクティブ環境で定義された変数は、グローバル環境で定義された変数よりも優先されます。Postman クライアントでは、API Fuzzing で使用できる JSON ファイルに環境をエクスポートできます。
  • コレクションスコープとは、あるコレクションで宣言された変数のグループのことです。コレクション変数は宣言されたコレクションと、ネストされたリクエストやコレクションで使用できます。コレクションスコープで定義された変数は_グローバル環境_スコープや_環境_スコープよりも優先されます。この JSON ファイルには選択されたコレクション、リクエスト、コレクション変数が含まれます。
  • API Fuzzing スコープはAPI Fuzzing によって追加された新しいスコープで、ユーザーが追加の変数を提供したり、他のサポートされているスコープで定義された変数を上書きしたりすることができます。このスコープは Postman ではサポートされていません。API Fuzzing Sc_ope の_変数はカスタム JSON ファイル形式で提供されます。
    • 環境またはコレクションで定義された値をオーバーライドします。
    • スクリプトからの変数の定義
    • サポートされていない_データ・スコープから_1行のデータを定義
  • データスコープとは、JSON や CSV ファイルの名前と値を持つ変数のグループです。NewmanPostman Collection Runnerのような Postman コレクションランナーは、JSON や CSV ファイルがある回数だけコレクション内のリクエストを実行します。これらの変数の良いユースケースは、Postman のスクリプトを使ってテストを自動化することです。API Fuzzing は CSV や JSON ファイルからの読み込みをサポートしていません
  • ローカルスコープはPostmanスクリプトで定義された変数です。API FuzzingはPostmanスクリプト、ひいてはスクリプトで定義された変数をサポートしていません。スクリプトで定義された変数の値は、サポートされているスコープ、またはカスタムJSONフォーマットで定義することができます。

すべてのスコープがAPI Fuzzingでサポートされているわけではなく、スクリプトで定義された変数はサポートされていません。以下の表は、最も広いスコープから最も狭いスコープにソートされています。

スコープポストマンAPIファジングコメント
グローバル環境はいはい特別な事前定義環境
環境はいはい指定環境
コレクションはいはいpostmanコレクションで定義
API ファジングの範囲なしはいAPI Fuzzingで追加されたカスタムスコープ
データはいなしCSVまたはJSON形式の外部ファイル
ローカルはいなしスクリプトで定義された変数

異なるスコープで変数を定義し、変数をエクスポートする方法の詳細については、以下を参照してください:

Postman クライアントからのエクスポート

Postman Client では様々なファイル形式でエクスポートできます。例えば、Postman コレクションや Postman 環境をエクスポートできます。エクスポートする環境はグローバル環境(常に利用可能)でも、以前に作成したカスタム環境でもかまいません。Postman コレクションをエクスポートする場合、コレクションと _ローカル_スコープ変数の宣言のみを含むことができます。

_環境_スコープ変数の宣言を得るには、その時点で指定された環境をエクスポートする必要があります。エクスポートされたファイルには、選択した環境の変数のみが含まれます。

サポートされるスコープが異なる変数のエクスポートの詳細については、こちらを参照してください:

APIファジングスコープ、カスタムJSONファイル形式

カスタムJSONファイルフォーマットは、各オブジェクトプロパティが変数名を表し、プロパティ値が変数値を表すJSONオブジェクトです。このファイルはお好みのテキストエディタを使用して作成することもできますし、パイプライン内の以前のジョブで作成することもできます。

この例ではAPI Fuzzingスコープで2つの変数base_urltoken を定義しています:

{
  "base_url": "http://127.0.0.1/",
  "token": "Token 84816165151"
}
API Fuzzing でのスコープの使用

GitLab15.1以降ではglobalenvironmentcollectionGitLab API Fuzzing_のスコープがサポートされています。GitLab 15.0以前では、_collectionと _GitLab_API Fuzzingのスコープのみをサポートしています。

以下の表はAPI Fuzzingの設定変数とスコープファイル/URLのマッピングのクイックリファレンスです:

スコープ提供方法
グローバル環境fuzzapi_postman_collection_variables
環境fuzzapi_postman_collection_variables
コレクションファザピ_ポストマン_コレクション
API ファジングの範囲fuzzapi_postman_collection_variables
データ未対応
ローカル未対応

Postman Collection ドキュメントには、_コレクションに_スコープされた変数が自動的に含まれます。Postman Collection は設定変数FUZZAPI_POSTMAN_COLLECTION で提供されます。この変数はエクスポートされた1つのPostmanコレクションに設定できます。

他のスコープの変数はFUZZAPI_POSTMAN_COLLECTION_VARIABLES 設定変数を通して提供されます。この設定変数は、GitLab 15.1以降ではカンマ(,)区切りのファイルリストをサポートしています。GitLab 15.0とそれ以前では、単一のファイルのみをサポートしています。ファイルが必要なスコープ情報を提供するので、提供されるファイルの順番は重要ではありません。

設定変数FUZZAPI_POSTMAN_COLLECTION_VARIABLES

未定義のPostman変数

API Fuzzingエンジンが、Postmanコレクションファイルが使用しているすべての変数参照を見つけられない可能性があります。以下のようなケースが考えられます:

  • _データ_または_ローカル_スコープの変数を使用しており、前述のようにこれらのスコープはAPI Fuzzingではサポートされていません。したがって、これらの変数の値がAPI Fuzzingスコープを通して提供されていないと仮定すると、データと_ローカル_スコープ変数の値は未定義です。
  • 変数名の入力に誤りがあり、定義されている変数と名前が一致しません。
  • Postman ClientがAPI Fuzzingではサポートされていない新しい動的変数をサポートしました。

可能な限り、API Fuzzingは未定義の変数を扱うときにPostman Clientと同じ動作に従います。変数参照のテキストはそのままで、テキストの置換はありません。また、サポートされていない動的変数についても同じ動作が適用されます。

例えば、Postman コレクションのリクエスト定義が変数を{{full_url}} 参照していて、その変数が見つから なかった場合、その変数は変更されずに . {{full_url}}

動的な Postman 変数

ユーザーが様々なスコープレベルで定義できる変数に加えて、Postman には_動的_変数と呼ばれる定義済みの変数があります。動的変数はすでに定義されており、その名前の先頭にはドル記号 ($) が付きます。インスタンスでは$guidとなります。_動的_変数は他の変数と同じように使うことができ、Postmanクライアントではリクエスト/コレクションの実行中にランダムな値を生成します。

API FuzzingとPostmanの重要な違いは、API Fuzzingは同じ動的変数を使うたびに同じ値を返すことです。これは同じ動的変数の使用ごとにランダムな値を返すPostman Clientの動作とは異なります。言い換えると、API Fuzzingは動的変数に静的な値を使うのに対し、Postmanはランダムな値を使います。

スキャン処理中にサポートされる動的変数は以下の通りです:

変数
$guid611c2e81-2ccb-42d8-9ddc-2d0bfa65c1b4
$isoTimestamp2020-06-09T21:10:36.177Z
$randomAbbreviationPCI
$randomAbstractImagehttp://no-a-valid-host/640/480/abstract
$randomAdjectiveauxiliary
$randomAlphaNumerica
$randomAnimalsImagehttp://no-a-valid-host/640/480/animals
$randomAvatarImagehttps://no-a-valid-host/path/to/some/image.jpg
$randomBankAccount09454073
$randomBankAccountBicEZIAUGJ1
$randomBankAccountIbanMU20ZPUN3039684000618086155TKZ
$randomBankAccountNameHome Loan Account
$randomBitcoin3VB8JGT7Y4Z63U68KGGKDXMLLH5
$randomBooleantrue
$randomBskiller leverage schemas
$randomBsAdjectiveviral
$randomBsBuzzrepurpose
$randomBsNounmarkets
$randomBusinessImagehttp://no-a-valid-host/640/480/business
$randomCatchPhraseFuture-proofed heuristic open architecture
$randomCatchPhraseAdjectiveBusiness-focused
$randomCatchPhraseDescriptorbandwidth-monitored
$randomCatchPhraseNounsuperstructure
$randomCatsImagehttp://no-a-valid-host/640/480/cats
$randomCitySpinkahaven
$randomCityImagehttp://no-a-valid-host/640/480/city
$randomColorfuchsia
$randomCommonFileExtwav
$randomCommonFileNamewell_modulated.mpg4
$randomCommonFileTypeaudio
$randomCompanyNameGrady LLC
$randomCompanySuffixInc
$randomCountryKazakhstan
$randomCountryCodeMD
$randomCreditCardMask3622
$randomCurrencyCodeZMK
$randomCurrencyNamePound Sterling
$randomCurrencySymbol£
$randomDatabaseCollationutf8_general_ci
$randomDatabaseColumnupdatedAt
$randomDatabaseEngineMemory
$randomDatabaseTypetext
$randomDateFutureTue Mar 17 2020 13:11:50 GMT+0530 (India Standard Time)
$randomDatePastSat Mar 02 2019 09:09:26 GMT+0530 (India Standard Time)
$randomDateRecentTue Jul 09 2019 23:12:37 GMT+0530 (India Standard Time)
$randomDepartmentElectronics
$randomDirectoryPath/usr/local/bin
$randomDomainNametrevor.info
$randomDomainSuffixorg
$randomDomainWordjaden
$randomEmailIva.Kovacek61@no-a-valid-host.com
$randomExampleEmailnon-a-valid-user@example.net
$randomFashionImagehttp://no-a-valid-host/640/480/fashion
$randomFileExtwar
$randomFileNameneural_sri_lanka_rupee_gloves.gdoc
$randomFilePath/home/programming_chicken.cpio
$randomFileTypeapplication
$randomFirstNameChandler
$randomFoodImagehttp://no-a-valid-host/640/480/food
$randomFullNameConnie Runolfsdottir
$randomHexColor#47594a
$randomImageDataUridata: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
$randomImageUrlhttp://no-a-valid-host/640/480
$randomIngverbnavigating
$randomInt494
$randomIP241.102.234.100
$randomIPV6dbe2:7ae6:119b:c161:1560:6dda:3a9b:90a9
$randomJobAreaMobility
$randomJobDescriptorSenior
$randomJobTitleInternational Creative Liaison
$randomJobTypeSupervisor
$randomLastNameSchneider
$randomLatitude55.2099
$randomLocaleny
$randomLongitude40.6609
$randomLoremLinesDucimus in ut mollitia.\nA itaque non.\nHarum temporibus nihil voluptas.\nIste in sed et nesciunt in quaerat sed.
$randomLoremParagraphAb 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.
$randomLoremParagraphsVoluptatem 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.
$randomLoremSentenceMolestias consequuntur nisi non quod.
$randomLoremSentencesEt 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.
$randomLoremSlugeos-aperiam-accusamus, beatae-id-molestiae, qui-est-repellat
$randomLoremTextQuisquam 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.
$randomLoremWordest
$randomLoremWordsvel repellat nobis
$randomMACAddress33:d4:68:5f:b4:c7
$randomMimeTypeaudio/vnd.vmx.cvsd
$randomMonthFebruary
$randomNamePrefixDr.
$randomNameSuffixMD
$randomNatureImagehttp://no-a-valid-host/640/480/nature
$randomNightlifeImagehttp://no-a-valid-host/640/480/nightlife
$randomNounbus
$randomPasswordt9iXe7COoDKv8k3
$randomPeopleImagehttp://no-a-valid-host/640/480/people
$randomPhoneNumber700-008-5275
$randomPhoneNumberExt27-199-983-3864
$randomPhraseYou can't program the monitor without navigating the mobile XML program!
$randomPrice531.55
$randomProductPizza
$randomProductAdjectiveUnbranded
$randomProductMaterialSteel
$randomProductNameHandmade Concrete Tuna
$randomProtocolhttps
$randomSemver7.0.5
$randomSportsImagehttp://no-a-valid-host/640/480/sports
$randomStreetAddress5742 Harvey Streets
$randomStreetNameKuhic Island
$randomTransactionTypepayment
$randomTransportImagehttp://no-a-valid-host/640/480/transport
$randomUrlhttps://no-a-valid-host.net
$randomUserAgentMozilla/5.0 (Macintosh; U; Intel Mac OS X 10.9.8; rv:15.6) Gecko/20100101 Firefox/15.6.6
$randomUserNameJarrell.Gutkowski
$randomUUID6929bb52-3ab2-448a-9796-d6480ecad36b
$randomVerbnavigate
$randomWeekdayThursday
$randomWordwithdrawal
$randomWordsSamoa Synergistic sticky copying Grocery
$timestamp1562757107
例グローバルスコープ

この例では _グローバル_スコープをPostman Clientから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 Clientから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ファジングの範囲

API Fuzzing Scopeは主に2つの目的で使われます。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_スコープが他のすべてのスコープより優先されるためです。

_コレクション_スコープ変数はエクスポートされた Postman Collection ファイルに含まれ、FUZZAPI_POSTMAN_COLLECTION 設定変数を通して提供されます。

API Fuzzing Scope は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ファジングの設定

APIファジングの動作はCI/CD変数で変更できます。

GitLab 13.12以降では、デフォルトのAPIファジング設定ファイルは.gitlab/gitlab-api-fuzzing-config.yml 。 GitLab 14.0以降では、APIファジング設定ファイルはリポジトリのルートではなく、リポジトリの.gitlab ディレクトリになければなりません。

caution
GitLab セキュリティスキャンツールのすべてのカスタマイズは、デフォルトブランチに変更をマージする前にマージリクエストでテストしてください。これを怠ると、多数の偽陽性を含む予期しない結果をもたらす可能性があります。

認証

認証は、認証トークンをヘッダまたはクッキーとして提供することで処理されます。認証フローを実行したりトークンを計算したりするスクリプトを提供することができます。

HTTP ベーシック認証

HTTPベーシック認証は、HTTPプロトコルに組み込まれた認証方式で、トランスポートレイヤーセキュリティ(TLS)と組み合わせて使用されます。

パスワード用のCI/CD変数(例えば、TEST_API_PASSWORD )を作成し、それをマスクするように設定することをお勧めします。CI/CD変数は、GitLabプロジェクトのページのSettings > CI/CDのVariablesセクションから作成できます。マスクされた変数には制限があるため、パスワードを変数として追加する前にBase64エンコードする必要があります。

最後に、.gitlab-ci.yml ファイルに CI/CD 変数を2つ追加します:

  • 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エンコードしたくない場合(あるいはGitLab 15.3以前を使っている場合)、FUZZAPI_HTTP_PASSWORD_BASE64 を使う代わりに生のパスワードFUZZAPI_HTTP_PASSWORD を指定することができます。

ベアラ・トークン

ベアラートークンは、OAuth2 や JSON Web Tokens(JWT) など、さまざまな認証メカニズムで使用されます。ベアラートークンはAuthorization HTTP ヘッダを使用して送信されます。API ファジングでベアラ・トークンを使用するには、以下のいずれかが必要です:

  • 有効期限のないトークン
  • テスト期間中にトークンを生成する方法
  • APIファジングがトークンを生成するために呼び出すPythonスクリプト
トークンの有効期限はありません

ベアラートークンの有効期限がない場合は、FUZZAPI_OVERRIDES_ENV 変数を使用して提供します。この変数の内容は、APIファジングの送信HTTPリクエストに追加するヘッダーとクッキーを提供するJSONスニペットです。

以下の手順に従って、FUZZAPI_OVERRIDES_ENVでベアラートークンを提供してください:

  1. CI/CD 変数、例えばTEST_API_BEARERAUTH作成し、値を{"headers":{"Authorization":"Bearer dXNlcm5hbWU6cGFzc3dvcmQ="}} とします(トークンを代入してください)。CI/CD変数はGitLabプロジェクトページのSettings > CI/CDの Variablesセクションから作成できます。

  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 のアプリケーション・ログをレビューします。オーバーライド・コマンドの詳細については、オーバーライドのセクションを参照してください。

テスト実行時に生成されるトークン

ベアラートークンを生成する必要があり、テスト中に有効期限が切れない場合は、トークンを含むファイルを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 のアプリケーションログをレビューしてください。

トークンの有効期限が短い

スキャンが完了する前にベアラートークンを生成し、期限切れにする必要がある場合、APIファザーが指定した間隔で実行するプログラムやスクリプトを提供することができます。提供されたスクリプトは、Python 3とBashがインストールされたAlpine Linuxコンテナで実行されます。Pythonスクリプトが追加パッケージを必要とする場合は、それを検出し、実行時にパッケージをインストールする必要があります。

スクリプトは、特定の形式でベアラートークンを含むJSONファイルを作成する必要があります:

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

3つの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 を提供します。このファイルには、特定の数のテストを実行するいくつかのテストプロファイルが含まれています。テストの数が増えるにつれて、それぞれのプロファイルの実行時間は長くなります。

プロファイルファズテスト(パラメータごと)
クイック1010
ミディアム-2020
中-5050
ロング100100

利用可能な CI/CD 変数

CI/CD 変数説明
SECURE_ANALYZERS_PREFIXアナライザをダウンロードするDockerレジストリのベースアドレスを指定します。
FUZZAPI_VERSIONAPI Fuzzingコンテナのバージョンを指定します。デフォルトは2
FUZZAPI_IMAGE_SUFFIXコンテナイメージのサフィックスを指定します。デフォルトはnone。
FUZZAPI_API_PORTAPI Fuzzingエンジンが使用する通信ポート番号を指定します。デフォルトは5500 。 GitLab 15.5で導入
FUZZAPI_TARGET_URLAPIテスト対象のベースURL。
FUZZAPI_CONFIGGitLab 13.12 で非推奨となり、デフォルトの.gitlab/gitlab-api-fuzzing-config.yml に置き換えられました。API Fuzzing設定ファイル。
FUZZAPI_PROFILEテスト中に使用する設定プロファイル。デフォルトはQuick-10
FUZZAPI_EXCLUDE_PATHSAPI URL パスをテストから除外します。
FUZZAPI_EXCLUDE_URLSテストからAPI URLを除外GitLab 14.10 で導入されました
FUZZAPI_EXCLUDE_PARAMETER_ENV除外されたパラメータを含むJSON文字列。GitLab 14.10 で導入
FUZZAPI_EXCLUDE_PARAMETER_FILE除外されたパラメータを含むJSONファイルへのパス。GitLab 14.10から導入。
FUZZAPI_OPENAPIOpenAPI仕様ファイルまたはURL。
FUZZAPI_OPENAPI_RELAXED_VALIDATIONドキュメント検証を緩和します。デフォルトは無効。GitLab 14.7 で導入。GitLabチームメンバーはこの機密イシューで詳細をご覧いただけます:https://gitlab.com/gitlab-org/gitlab/-/issues/345950.
FUZZAPI_OPENAPI_ALL_MEDIA_TYPESリクエストを生成する際に、1つのメディアタイプではなく、サポートされているすべてのメディアタイプを使用します。テスト時間が長くなります。デフォルトは無効です。GitLab 14.10 で導入
FUZZAPI_OPENAPI_MEDIA_TYPESコロン (:) 区切りのメディアタイプ。デフォルトは無効。GitLab 14.10 で導入
FUZZAPI_HARHTTP アーカイブ(HAR) ファイル。
FUZZAPI_GRAPHQLGraphQLエンドポイントへのパス、例えば/api/graphql 。GitLab 15.4で導入されました
FUZZAPI_GRAPHQL_SCHEMAJSON形式のGraphQLスキーマのURLまたはファイル名。GitLab 15.4で導入
FUZZAPI_POSTMAN_COLLECTIONPostman コレクションファイル。
FUZZAPI_POSTMAN_COLLECTION_VARIABLESPostman変数の値を抽出するJSONファイルへのパス。カンマ区切り (,) ファイルのサポートは GitLab 15.1 で導入されました。
FUZZAPI_OVERRIDES_FILEオーバーライドを含むJSONファイルへのパス。
FUZZAPI_OVERRIDES_ENVオーバーライドするヘッダーを含む JSON 文字列。
FUZZAPI_OVERRIDES_CMDコマンドを上書きします。
FUZZAPI_OVERRIDES_CMD_VERBOSE任意の値に設定するとジョブ出力の一部としてオーバーライドコマンド出力を表示します。GitLab 14.8で導入されました
FUZZAPI_PRE_SCRIPTスキャンセッションが始まる前にユーザーコマンドやスクリプトを実行します。
FUZZAPI_POST_SCRIPTスキャン セッション終了後にユーザー コマンドまたはスクリプトを実行します。
FUZZAPI_OVERRIDES_INTERVALオーバーライド コマンドを実行する頻度を秒単位で指定します。デフォルトは0 (1 回) です。
FUZZAPI_HTTP_USERNAMEHTTP認証のユーザー名。
FUZZAPI_HTTP_PASSWORDHTTP認証のパスワード
FUZZAPI_HTTP_PASSWORD_BASE64Base64エンコードされたHTTP認証用のパスワード。GitLab 15.4で導入

オーバーライド

API Fuzzingは、リクエストに特定の項目を追加したり上書きしたりするメソッドを提供します:

  • ヘッダー
  • クッキー
  • クエリ文字列
  • フォームデータ
  • JSONノード
  • XMLノード

これを使用して、セマンティック・バージョン・ヘッダや認証などを注入できます。認証のセクションには、オーバーライドの使用例が記載されています。

オーバーライドは 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"
  }
}

単一のヘッダーを設定する例:

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

ヘッダーとクッキーの両方を設定する例:

{
  "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 Path式に設定されます。JSON Path 式$.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 属性をオーバーライドし、2 番目のエントリは 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 を CI/CD 変数として提供するには、FUZZAPI_OVERRIDES_ENV 変数を使用します。これにより、JSON をマスクして保護できる変数として配置できます。

この例では、.gitlab-ci.ymlFUZZAPI_OVERRIDES_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_OVERRIDES_ENV: '{"headers":{"X-API-Version":"2"}}'

この例では、.gitlab-ci.ymlSECRET_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ファザーが指定された間隔で実行するプログラムまたはスクリプトを提供することができます。提供されたスクリプトは、Python 3とBashがインストールされたLinuxコンテナで実行されます。

実行したいプログラムまたはスクリプトに環境変数FUZZAPI_OVERRIDES_CMD を設定する必要があります。提供されるコマンドは、先に定義したオーバーライドJSONファイルを作成します。

NodeJSやRubyのような他のスクリプト・ランタイムをインストールしたい場合や、overridesコマンドの依存関係をインストールする必要がある場合があります。この場合、FUZZAPI_PRE_SCRIPT これらの前提条件を提供するスクリプトのファイル・パスに FUZZAPI_PRE_SCRIPT設定することをお勧めします。FUZZAPI_PRE_SCRIPT で指定したスクリプトは FUZZAPI_PRE_SCRIPT、アナライザが起動する前に一度だけ実行されます。

Alpine Linuxパッケージのインストールについては、Alpine Linuxパッケージ管理ページを参照してください。

3つの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.必要であれば、](https://www.gnu.org/software/coreutils/manual/html_node/chmod-invocation.html) に実行権限を設定した状態でバージョンアップしてください。
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

デバッグのオーバーライド

GitLab 14.8で導入されました

デフォルトではoverridesコマンドの出力は非表示です。overridesコマンドが0以外の終了コードを返した場合、コマンドはジョブ出力の一部として表示されます。オプションで、変数FUZZAPI_OVERRIDES_CMD_VERBOSE を任意の値に設定して、overrides コマンド出力を生成時に表示できます。これは、overrides スクリプトをテストするときに便利ですが、テストが遅くなるため、テスト後は無効にしてください。

ジョブが完了または失敗したときに収集されるログファイルに、スクリプトからのメッセージを書き込むこともできます。ログファイルは特定の場所に作成し、命名規則に従う必要があります。

オーバーライド・スクリプトに基本的なロギングを追加しておくと、ジョブの標準的な実行中にスクリプトが予期せず失敗した場合に便利です。ログファイルはジョブのアーティファクトとして自動的に含まれるため、ジョブ終了後にダウンロードできます。

この例では、renew_token.py を環境変数FUZZAPI_OVERRIDES_CMD に指定しています。スクリプトの中で2つのことに注目してください:

  • ログファイルは環境変数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

overrides コマンドの例では、Python スクリプトはbackoff ライブラリに依存しています。Python スクリプトを実行する前にライブラリがインストールされていることを確認するために、FUZZAPI_PRE_SCRIPT は overrides コマンドの依存関係をインストールするスクリプトに設定されます。例えば、次のスクリプト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 を使って新しいランタイムやアプリケーションをインストールし、後で overrides コマンドで使用することもできました。

除外パス

GitLab 14.0 で導入されました

APIをテストする際に、特定のパスを除外すると便利です。例えば、認証サービスや古いバージョンのAPIのテストを除外することができます。パスを除外するには、FUZZAPI_EXCLUDE_PATHS CI/CD 変数を使います。この変数は.gitlab-ci.yml ファイルで指定します。複数のパスを除外するには、; 文字を使用してエントリを区切ります。提供されたパスでは、1文字のワイルドカード? と複数文字のワイルドカード* を使用できます。

パスが除外されていることを確認するには、ジョブ出力の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/*

パラメータの除外

GitLab 14.10で導入されました

APIのテスト中に、あるパラメータ(クエリ文字列、ヘッダ、ボディ要素)をテストから除外したいことがあるかもしれません。これは、あるパラメータが常に失敗を引き起こしたり、テストが遅くなったり、その他の理由で必要になることがあります。パラメータを除外するには、次の変数のいずれかを使用します:FUZZAPI_EXCLUDE_PARAMETER_ENV あるいはFUZZAPI_EXCLUDE_PARAMETER_FILE

FUZZAPI_EXCLUDE_PARAMETER_ENV では、除外するパラメータを含む JSON 文字列を指定できます。これは、JSONが短く、頻繁に変更できない場合に有効なオプションです。もう1つのオプションは、変数FUZZAPI_EXCLUDE_PARAMETER_FILE です。この変数は、リポジトリにチェックインするか、アーティファクトとして他のジョブによって作成されるか、FUZZAPI_PRE_SCRIPT を使用してプリスクリプトから実行時に生成されるファイルパスに設定されます。

JSONドキュメントを使用したパラメータの除外

JSON ドキュメントには、特定のプロパティを使用して除外するパラメータを識別する JSON オブジェクトが含まれます。スキャン処理中に特定のパラメータを除外するには、以下のプロパティを指定します:

  • headers:特定のヘッダを除外するには、このプロパティを使用します。プロパティの値は、除外するヘッダ名の配列です。名前の大文字と小文字は区別されません。
  • cookies:特定のクッキーを除外するには、このプロパティの値を使用します。このプロパティの値は、除外するクッキー名の配列です。名前の大文字と小文字は区別されます。
  • query:クエリ文字列から特定のフィールドを除外するには、このプロパティを使用します。プロパティの値は、除外するクエリ文字列のフィールド名の配列です。名前の大文字と小文字は区別されます。
  • body-form:このプロパティを使用して、メディア・タイプapplication/x-www-form-urlencoded を使用する要求から特定のフィールドを除外します。このプロパティの値は、除外する本文のフィールド名の配列です。名前の大文字と小文字は区別されます。
  • body-json:このプロパティを使用して、メディアタイプapplication/json を使用するリクエストから特定の JSON ノードを除外します。プロパティの値は配列で、配列の各エントリはJSON Path式です。
  • 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"
  ]
}

使用例

単一ヘッダの除外

ヘッダUpgrade-Insecure-Requests を除外するには、header プロパティの値を、ヘッダ名:[ "Upgrade-Insecure-Requests" ] を持つ配列に設定します。例えば、JSONドキュメントは以下のようになります:

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

ヘッダー名は大文字と小文字を区別しないので、ヘッダー名UPGRADE-INSECURE-REQUESTSUpgrade-Insecure-Requests と等価です。

ヘッダと二つのクッキーの両方を除きます。

ヘッダAuthorization とクッキーPHPSESSIDcsrftoken を除外するには、headers プロパティの値をヘッダ名[ "Authorization" ] の配列に設定し、cookies プロパティの値をクッキー名[ "PHPSESSID", "csrftoken" ]の配列に設定します。例えば、JSONドキュメントは次のようになります:

{
  "headers": [ "Authorization" ],
  "cookies": [ "PHPSESSID", "csrftoken" ]
}
body-form パラメータの除外

application/x-www-form-urlencoded を使用する要求でpassword フィールドを除外するには、body-form プロパティの値をフィールド名[ "password" ] の配列に設定します。例えば、JSONドキュメントは以下のようになります:

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

exclude パラメータは、要求がコンテンツ・タイプapplication/x-www-form-urlencoded を使用している場合、body-form を使用します。

JSON Path を使用した特定の JSON ノードの除外

ルート・オブジェクトのschema プロパティを除外するには、body-json プロパティの値を、JSON Path 式[ "$.schema" ] を持つ配列に設定します。

JSON パス式は、JSON ノードを識別するために特別な構文を使用します。$ は JSON ドキュメントのルートを指し、. は現在のオブジェクト (この場合はルート オブジェクト) を指し、schema というテキストはプロパティ名を指します。したがって、JSON パス式$.schema は、ルート オブジェクトのプロパティschema を参照します。インスタンスのJSONドキュメントは次のようになります:

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

リクエストがコンテンツタイプapplication/json を使用する場合、 exclude パラメータはbody-json を使用します。body-json の各エントリは、JSON Path 式であることが期待されます。JSON Path では、$*. などの文字が特別な意味を持ちます。

JSON Path を使用した複数の JSON ノードの除外

ルートレベルの配列users の各エントリでプロパティpassword を除外するには、body-json プロパティの値を、JSON Path 式[ "$.users[*].paswword" ] を持つ配列に設定します。

JSON Path 式は、$ で開始してルート・ノードを参照し、. を使用して現在のノードを参照します。次に、users を使用してプロパティを参照し、[] という文字を使用して、使用する配列のインデックスを囲みます。インデックスとして数値を指定する代わりに、* を使用して任意のインデックスを指定します。インデックス参照の後、. が見つかります。これは、配列内の任意の選択されたインデックスを参照するもので、その前にプロパティ名passwordが付きます。

インスタンスのJSONドキュメントは次のようになります:

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

リクエストがコンテンツタイプapplication/json を使用する場合、 exclude パラメータはbody-json を使用します。body-json の各エントリは、JSON Path 式であることが期待されます。$*. などの JSON Path 文字は特別な意味を持ちます。

XML 属性の除外

ルート要素credentials にあるisEnabled という名前の属性を除外するには、body-xml プロパティの値を、XPath 式[ "/credentials/@isEnabled" ] を持つ配列に設定します。

XPath 式/credentials/@isEnabled は、XML 文書のルートを示す/ で始まり、マッチさせる要素の名前を示すcredentials が続きます。前の XML 要素のノードを参照するために/ を使用し、名前isEnable が属性であることを示すために文字@ を使用します。

インスタンスのJSONドキュメントは次のようになります:

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

リクエストがコンテントタイプapplication/xml を使用する場合、 exclude パラメータはbody-xml を使用します。body-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 を使用している場合、 exclude パラメータはbody-xml を使用します。body-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 を使用している場合、 exclude パラメータはbody-xml を使用します。body-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が続きます。:この文字は、名前空間とノード名を分離します。

名前空間名は、ボディ・リクエストの一部である XML ドキュメントで定義されている必要があります。名前空間は、仕様ドキュメント HAR、OpenAPI、または Postman Collection ファイルで確認できます。

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

リクエストがコンテントタイプapplication/xml を使用している場合、 exclude パラメータはbody-xml を使用します。body-xml の各エントリは、XPath v2 式であることが期待されます。XPath 式では、@/:[] などの文字が特別な意味を持ちます。

JSON 文字列の使用

除外JSONドキュメントを提供するには、変数FUZZAPI_EXCLUDE_PARAMETER_ENV にJSON文字列を設定します。以下の例では、.gitlab-ci.yml,FUZZAPI_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ドキュメントを提供するには、変数FUZZAPI_EXCLUDE_PARAMETER_FILE にJSONファイルパスを設定します。ファイルパスは、ジョブの現在の作業ディレクトリからの相対パスです。次の例.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 は、exclude パラメータ文書の構造に従った JSON 文書です。

除外URL

GitLab 14.10で導入されました

パスで除外する代わりに、FUZZAPI_EXCLUDE_URLS CI/CD変数を使ってURL内の他のコンポーネントでフィルタリングすることができます。この変数は.gitlab-ci.yml ファイルで設定できます。この変数にはカンマ(,)で区切られた複数の値を格納することができます。各値は正規表現です。各エントリは正規表現なので、.* のようなエントリは、すべてにマッチする正規表現であるため、すべての URL を除外します。

ジョブ出力では、FUZZAPI_EXCLUDE_URLS から指定された正規表現に一致する URL があるかどうかを確認できます。一致するオペレーションは、[除外されたオペレーション]セクションにリストされています。Excluded 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: ------------------------------------------------
note
FUZZAPI_EXCLUDE_URLS の各値は正規表現です。.*$ などの文字はFUZZAPI_EXCLUDE_URLS正規FUZZAPI_EXCLUDE_URLS表現で特別な意味を持ちます。

使用例

URLと子リソースの除外

次の例は、URLhttp://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
2つのURLを除外し、その子リソースを許可します。

http://target/api/buyhttp://target/api/sell のURLを除外し、その子リソースのスキャンを許可するには、インスタンス:http://target/api/buy/toy またはhttp://target/api/sell/chair.http://target/api/buy/$,http://target/api/sell/$という値を使用できます。この値は、, 文字で区切られた 2 つの正規表現を使用しています。したがって、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とその子リソースの除外

http://target/api/buyhttp://target/api/sell のURLとその子リソースを除外します。複数の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 またはその他のバージョン (v3,v4, and more) を正確に除外するには、https://target/api/v.*/user/create$を使用します。前の正規表現では

  • . は任意の文字を示します。
  • * は0回以上を表します。
  • $ は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$

ヘッダーファジング

ヘッダファジングは、多くのテクノロジースタックで発生する多くの誤検出のため、デフォルトでは無効になっています。ヘッダファジングが有効な場合は、ファジングに含めるヘッダのリストを指定する必要があります。

デフォルト設定ファイルの各プロファイルには、GeneralFuzzingCheck のエントリがあります。このチェックはヘッダーファジングを実行します。Configuration セクションで、HeaderFuzzingHeaders の設定を変更して、ヘッダー・ファジングを有効にする必要があります。

このスニペットは、ヘッダーファジングを無効にしたQuick-10 プロファイルのデフォルト設定を示しています:

- 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 はヘッダーファジングのオンとオフを切り替えるブール値です。デフォルトの設定はfalse で off です。ヘッダーファジングをオンにするには、この設定をtrue に変更します:

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

Headers はファジングするヘッダのリストです。リストされたヘッダーのみがファジングされます。APIで使用されるヘッダをファジングするには、- Name: HeaderName の構文を使用して、そのヘッダのエントリを追加します。たとえば、カスタムヘッダX-Custom をファジングするには、- Name: X-Custom を追加します:

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

これで、ヘッダX-Custom をファジングする設定ができました。追加のヘッダを列挙するために同じ記法を使います:

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

必要に応じて、各プロファイルに対してこの設定を繰り返します。

最初のスキャンの実行

正しく設定されている場合、CI/CDパイプラインはfuzz ステージとapifuzzer_fuzz またはapifuzzer_fuzz_dnd ジョブを含んでいます。ジョブが失敗するのは、無効な設定が提供されたときだけです。典型的なオペレーションでは、ファズテストの間に欠陥が特定されたとしても、ジョブは常に成功します。

フォルトはスイート名とともにセキュリティパイプラインタブに表示されます。リポジトリのデフォルトブランチに対してテストする場合、ファジングのフォルトはセキュリティとコンプライアンスの脆弱性レポートページにも表示されます。

報告されるフォルトの数が過剰になるのを防ぐために、API ファジングスキャナは報告するフォルトの数を制限します。

ファジングフォルトの表示

API Fuzzing アナライザーは JSON レポートを作成し、それを集めてGitLab の脆弱性画面にフォールトを入力するのに使います。ファジングのフォールトは深刻度が Unknown の脆弱性として表示されます。

APIファジングが見つけたフォールトは手動での調査が必要で、特定の脆弱性のタイプとは関連づけられません。これらはセキュリティのイシューかどうか、そして、修正されるべきかどうかを判断するために調査が必要です。報告される偽陽性の数を制限するための設定変更については、偽陽性の取り扱いを参照してください。

API Fuzzing 脆弱性の詳細を見る

GitLab 13.7 で導入されました。

API Fuzzingによって検出されたフォールトはライブのウェブアプリケーションで発生し、脆弱性かどうかを判断するために手動による調査が必要です。ファジングのフォールトは深刻度不明(Unknown)の脆弱性として含まれます。ファジングのフォールトの調査を容易にするために、送受信されたHTTPメッセージに関する詳細な情報が、行われた修正の説明とともに提供されます。

ファジング障害の詳細を表示するには、次の手順に従います:

  1. プロジェクトやマージリクエストのフォールトを見ることができます:

    • プロジェクトで、プロジェクトのセキュリティ > 脆弱性レポートページに移動します。このページには、デフォルトブランチからのすべての脆弱性のみが表示されます。
    • マージリクエストでは、マージリクエストのセキュリティセクションに移動し、展開ボタンを選択します。API Fuzzing フォルトは、API Fuzzing detected N potential vulnerabilitiesというラベルの付いたセクションで利用できます。タイトルを選択すると、フォルトの詳細が表示されます。
  2. フォルトのタイトルを選択すると、フォルトの詳細が表示されます。これらの詳細については、以下の表で説明します。

    項目説明
    説明何が変更されたかを含むフォルトの説明。
    プロジェクト脆弱性が検出された名前空間とプロジェクト。
    方法脆弱性の検出に使用される HTTP メソッド。
    URL脆弱性が検出されたURL。
    リクエスト障害の原因となった HTTP リクエスト。
    変更されていないレスポンス変更されていないリクエストのレスポンスです。これが典型的なレスポンスです。
    実際のレスポンスファジングしたリクエストから受け取ったレスポンス。
    証拠障害が発生したと判断した方法
    識別子この障害を発見するために使用されたファジングチェック。
    深刻度所見の重症度は常に不明です。
    スキャナの種類テストに使用するスキャナ。

セキュリティダッシュボード

ファジングの失敗は、深刻度が「不明(Unknown)」の脆弱性として表示されます。セキュリティダッシュボードは、グループ、プロジェクト、パイプラインのすべてのセキュリティ脆弱性の概要を知るのに良い場所です。詳細については、セキュリティダッシュボードのドキュメントを参照してください。

脆弱性との対話

ファジングのフォールトは深刻度が Unknown の脆弱性として表示されます。フォールトが見つかったら、そのフォールトと対話することができます。脆弱性へのアドレスの取り方についてはこちらをご覧ください。

誤検出への対処

誤検出には2つの方法があります:

  • 誤検出を発生させた検査をオフにします。これにより、そのチェックはフォールトを生成しなくなります。チェックの例としては、JSON ファジングチェックや フォームボディファジングチェックなどがあります。
  • ファジングチェックには、_アサートと_呼ばれる、フォルトが特定されたときに検出するいくつかの方法があります。アサートはオフにしたり設定したりすることもできます。例えば、APIファザーはデフォルトで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

一般的なファジングチェックをオフにするには、以下の行を削除します:

- 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

チェックのアサーションをオフにします

アサーションは、チェックによって生成されたテストのフォールトを検出します。多くの検査では、ログ解析、レスポンス解析、ステータスコードなど、複数のアサーションをサポートしています。フォルトが検出されると、使用されたアサーションが提供されます。デフォルトで有効になっているアサーションを確認するには、設定ファイルの Checks default configuration を参照してください。Checks というセクションがあります。

この例では FormBody ファジングチェックを示します:

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

デフォルトで 3 つのアサーションがオンになっていることがわかります。よくある誤検出の原因はStatusCodeAssertion です。これをオフにするには、Profiles セクションの設定を変更してください。この例では、他の2つのアサーション (LogAnalysisAssertion,ResponseAnalysisAssertion) だけを提供しています。これにより、FormBodyFuzzingCheckStatusCodeAssertionを使用することを防ぎます:

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ファジングの実行

インターネットを通じた外部リソースへのアクセスが制限されている、制限されている、または断続的な環境にある自己管理GitLabインスタンスでは、Web API Fuzzテストジョブを正常に実行するためにいくつかの調整が必要です。

ステップ

  1. ローカルのコンテナレジストリにDockerイメージをホストします。
  2. SECURE_ANALYZERS_PREFIX をローカル・コンテナ・レジストリに設定します。

API Fuzzing用のDockerイメージは、公開レジストリからプル(ダウンロード)し、ローカルレジストリにプッシュ(インポート)する必要があります。Dockerイメージをローカルにホストするには、GitLabコンテナレジストリを使用します。このプロセスは特別なテンプレートを使って実行できます。手順についてはオフラインホストへのDockerイメージのロードを参照してください。

Dockerイメージがローカルにホストされると、SECURE_ANALYZERS_PREFIX 変数にローカルレジストリの場所が設定されます。この変数は、/api-security:2 を連結すると有効なイメージの場所になるように設定する必要があります。

例えば、以下の行はregistry.gitlab.com/security-products/api-security:2 というイメージのレジストリを設定します:

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

note
SECURE_ANALYZERS_PREFIX を設定すると、すべてのGitLab SecureテンプレートのDockerイメージレジストリの場所が変更されます。

詳細については、オフライン環境を参照してください。

パフォーマンス・チューニングとテスト速度

API Fuzzing のような、API ファズテストを実行するセキュリティツールは、実行中のアプリケーションのインスタンスにリクエストを送信することによってテストを実行します。リクエストはファジングエンジンによって変異され、アプリケーションに存在するかもしれない予期せぬ振る舞いを引き起こします。APIファジングテストの速度は以下に依存します:

  • ファジングツールがアプリケーションに送信できる1秒あたりのリクエスト数
  • アプリケーションがリクエストに応答する速度
  • アプリケーションのテストに必要なリクエスト数
    • APIがいくつのオペレーションで構成されているか
    • 各オペレーションに含まれるフィールドの数(JSONボディ、ヘッダー、クエリ文字列、クッキーなど)

このパフォーマンスガイドのアドバイスに従ってもAPI Fuzzingテストのジョブが予想以上に時間がかかる場合は、サポートに連絡してさらなる支援を受けてください。

パフォーマンスの問題の診断

パフォーマンスの問題を解決するための最初のステップは、テスト時間が予想よりも遅い原因となっている貢献者を理解することです。よく見られるイシューは以下のとおりです:

  • API Fuzzingが低速またはシングルCPUのGitLab Runnerで実行されている(GitLab Shared RunnerはシングルCPUです)
  • アプリケーションが低速/シングル CPU インスタンスにデプロイされ、テストの負荷に追いついていない場合。
  • アプリケーションに全体的なテスト速度に影響を与える遅いオペレーションが含まれている(1/2 秒以上)
  • アプリケーションに、大量のデータを返すオペレーションが含まれている(> 500K+) 場合。
  • アプリケーションに大量のオペレーションが含まれている (> 40)

アプリケーションに全体的なテスト速度に影響を与える遅いオペレーションが含まれている(1/2 秒以上)

API Fuzzingジョブの出力には、テストしている速度、テストされている各オペレーションの応答速度、サマリー情報などの有用な情報が含まれています。いくつかのサンプル出力を見て、パフォーマンスの問題を追跡する際にどのように使えるか見てみましょう:

API Fuzzing: Loaded 10 operations from: assets/har-large-response/large_responses.har
API Fuzzing:
API Fuzzing: Testing operation [1/10]: 'GET http://target:7777/api/large_response_json'.
API Fuzzing:  - Parameters: (Headers: 4, Query: 0, Body: 0)
API Fuzzing:  - Request body size: 0 Bytes (0 bytes)
API Fuzzing:
API Fuzzing: Finished testing operation 'GET http://target:7777/api/large_response_json'.
API Fuzzing:  - Excluded Parameters: (Headers: 0, Query: 0, Body: 0)
API Fuzzing:  - Performed 767 requests
API Fuzzing:  - Average response body size: 130 MB
API Fuzzing:  - Average call time: 2 seconds and 82.69 milliseconds (2.082693 seconds)
API Fuzzing:  - Time to complete: 14 minutes, 8 seconds and 788.36 milliseconds (848.788358 seconds)

このジョブコンソールの出力スニペットは、見つかったオペレーションの数 (10) から始まり、特定のオペレーションでテストが開始されたことの通知と、オペレーションが完了したことの要約が続きます。要約はこのログ出力の最も興味深い部分です。要約では、API Fuzzingがこのオペレーションとその関連フィールドを完全にテストするのに、767リクエストを要したことがわかります。また、平均応答時間は2秒で、この1つのオペレーションが完了するまでの時間は14分であったこともわかります。

平均応答時間が2秒であることは、この特定のオペレーションがテストに時間がかかることを示す最初の良い指標です。さらに、レスポンスのボディ・サイズがかなり大きいことがわかります。各リクエストで多くのデータを転送することが、2秒の大部分を占めているのです。

このイシューに対して、チームは次のことを決定するかもしれません:

チームの要件が5-7分の範囲にあると仮定すると、これらの解決策を組み合わせて、許容可能なテスト時間を達成することが考えられます。

パフォーマンス問題へのアドレス

以下のセクションでは、API Fuzzingのパフォーマンス問題に対処するためのさまざまなオプションについて説明します:

マルチCPUランナーの使用

API FuzzingでマルチCPUランナーを使うことで、最も簡単にパフォーマンスを向上させることができます。この表はJava Spring Boot REST APIのベンチマークで収集された統計情報です。このベンチマークでは、ターゲットとAPI Fuzzingは単一のRunnerインスタンスを共有しています。

CPU数リクエスト/秒
1CPU(共有ランナー)75
4 CPU255
8 CPU400

この表からわかるように、RunnerのCPU数を増やすことは、テストのスピード/パフォーマンスに大きな影響を与えます。

マルチCPUを使うには、通常、セルフマネージドGitLab RunnerをマルチCPUマシンやクラウドコンピュートインスタンスにデプロイする必要があります。

複数のタイプのGitLab Runnerが使用可能な場合、様々なインスタンスは一般的にジョブ定義でランナーのタイプを選択するために使用できるタグで設定されています。

以下は API Fuzzing のジョブ定義の例で、multi-cpu というタグでtags セクションを追加しています。このジョブはAPI Fuzzingテンプレートに含まれるジョブ定義を自動的に拡張します。

apifuzzer_fuzz:
  tags:
  - multi-cpu

API Fuzzing がランナーで複数の CPU を検出できることを確認するには、完了したジョブのアーティファクトからgl-api-security-scanner.log ファイルをダウンロードしてください。このファイルで文字列Starting work item processor を検索し、レポーターの最大DOP(並列度)を調べます。最大DOPは、ランナーに割り当てられたCPU数以上でなければなりません。設定変数によって強制されない限り、シングルCPU Runnerであっても、値が2より小さくなることはありません。レポートされた値がランナーに割り当てられたCPU数より小さい場合、ランナーのデプロイに何か問題があります。問題を特定できない場合は、サポートにチケットを提出してください。

ログエントリの例

17:00:01.084 [INF] <Peach.Web.Core.Services.WebRunnerMachine> Starting work item processor with 2 max DOP

低速オペレーションの除外

遅いオペレーションが1つまたは2つある場合、チームはそのオペレーションのテストを省略することを決定するかもしれません。オペレーションを除外するには、このセクションで説明するようにFUZZAPI_EXCLUDE_PATHS 設定変数を使用します。

この例では、大量のデータを返すオペレーションがあります。このオペレーションはGET http://target:7777/api/large_response_json です。これを除外するために、FUZZAPI_EXCLUDE_PATHS 設定変数にオペレーションURLのパス部分/api/large_response_jsonを指定します。

オペレーションが除外されていることを確認するには、API Fuzzingジョブを実行し、ジョブコンソール出力をレビューします。テストの最後に含まれるオペレーションと除外されるオペレーションのリストが含まれています。

apifuzzer_fuzz:
  variables:
    FUZZAPI_EXCLUDE_PATHS: /api/large_response_json

オペレーションをテストから除外すると、脆弱性が発見されない可能性があります。{: .alert .alert-warning} {: .alert .alert-warning

テストの複数ジョブへの分割

API Fuzzing ではFUZZAPI_EXCLUDE_PATHSFUZZAPI_EXCLUDE_URLSを使ってテストを複数のジョブに分割することができます。テストを分割する場合、apifuzzer_fuzz のジョブを無効にし、それを識別名のついた二つのジョブで置き換えるのが良いパターンです。この例では2つのジョブがあり、それぞれのジョブはAPIのバージョンをテストしているので、名前はそれを反映しています。しかし、このテクニックはAPIのバージョンに限らず、どんな状況にも適用できます。

apifuzzer_v1apifuzzer_v2 のジョブで使っているルールはAPI Fuzzing テンプレートからコピーしたものです。

# Disable the main apifuzzer_fuzz job
apifuzzer_fuzz:
  rules:
  - if: $CI_COMMIT_BRANCH
    when: never

apifuzzer_v1:
  extends: apifuzzer_fuzz
  variables:
    FUZZAPI_EXCLUDE_PATHS: /api/v1/**
  rules:
    rules:
    - if: $API_FUZZING_DISABLED == 'true' || $API_FUZZING_DISABLED == '1'
      when: never
    - if: $API_FUZZING_DISABLED_FOR_DEFAULT_BRANCH == 'true' &&
            $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
      when: never
    - if: $API_FUZZING_DISABLED_FOR_DEFAULT_BRANCH == '1' &&
            $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
      when: never
    - if: $CI_COMMIT_BRANCH &&
          $CI_GITLAB_FIPS_MODE == "true"
      variables:
          FUZZAPI_IMAGE_SUFFIX: "-fips"
    - if: $CI_COMMIT_BRANCH

apifuzzer_v2:
  variables:
    FUZZAPI_EXCLUDE_PATHS: /api/v2/**
  rules:
    rules:
    - if: $API_FUZZING_DISABLED == 'true' || $API_FUZZING_DISABLED == '1'
      when: never
    - if: $API_FUZZING_DISABLED_FOR_DEFAULT_BRANCH &&
            $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
      when: never
    - if: $CI_COMMIT_BRANCH &&
          $CI_GITLAB_FIPS_MODE == "true"
      variables:
          FUZZAPI_IMAGE_SUFFIX: "-fips"
    - if: $CI_COMMIT_BRANCH

機能ブランチでのオペレーションを除外し、デフォルトブランチでのオペレーションは除外しないこと。

遅いオペレーションがひとつふたつある場合、チームはそのオペレーションのテストを省略するか、 あるいはそのオペレーションを feature ブランチのテストからは除外して default ブランチのテストには含めることにします。オペレーションを除外するには、FUZZAPI_EXCLUDE_PATHS 設定変数を使います。

この例では、大量のデータを返すオペレーションがあります。このオペレーションはGET http://target:7777/api/large_response_json です。このオペレーションを除外するには、FUZZAPI_EXCLUDE_PATHS 設定変数にオペレーションURL/api/large_response_jsonのパス部分を指定します。この設定では、メインのapifuzzer_fuzz ジョブを無効にし、2つの新しいapifuzzer_main ジョブとapifuzzer_branch.は apifuzzer_branch、長いオペレーションを除外し、デフォルト以外のブランチ (たとえば機能ブランチ) でのみ実行するように設定されています。ブランチは apifuzzer_main、デフォルトブランチ (この例ではmain ) でのみ実行されるように設定されています。apifuzzer_branch のジョブは高速に実行され、開発サイクルを短縮できます。一方、apifuzzer_main のジョブはデフォルトブランチのビルドでのみ実行され、実行に時間がかかります。

オペレーションが除外されていることを確認するには、API Fuzzingジョブを実行し、ジョブコンソール出力をレビューします。テストの最後に含まれるオペレーションと除外されるオペレーションのリストが含まれています。

# Disable the main job so we can create two jobs with
# different names
apifuzzer_fuzz:
  rules:
  - if: $CI_COMMIT_BRANCH
    when: never

# API Fuzzing for feature branch work, excludes /api/large_response_json
apifuzzer_branch:
  extends: apifuzzer_fuzz
  variables:
    FUZZAPI_EXCLUDE_PATHS: /api/large_response_json
  rules:
    rules:
    - if: $API_FUZZING_DISABLED == 'true' || $API_FUZZING_DISABLED == '1'
      when: never
    - if: $API_FUZZING_DISABLED_FOR_DEFAULT_BRANCH &&
            $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
      when: never
    - if: $CI_COMMIT_BRANCH &&
          $CI_GITLAB_FIPS_MODE == "true"
      variables:
          FUZZAPI_IMAGE_SUFFIX: "-fips"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      when: never
    - if: $CI_COMMIT_BRANCH

# API Fuzzing for default branch (main in our case)
# Includes the long running operations
apifuzzer_main:
  extends: apifuzzer_fuzz
    rules:
    - if: $API_FUZZING_DISABLED == 'true' || $API_FUZZING_DISABLED == '1'
      when: never
    - if: $API_FUZZING_DISABLED_FOR_DEFAULT_BRANCH &&
            $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
      when: never
    - if: $CI_COMMIT_BRANCH &&
          $CI_GITLAB_FIPS_MODE == "true"
      variables:
          FUZZAPI_IMAGE_SUFFIX: "-fips"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

トラブルシューティング

APIファジングのジョブがN時間後にタイムアウトします。

API Fuzzingジョブがタイムアウトする理由のトップ2は、オペレーションが遅い(1秒以上)ことと、API FuzzingにシングルCPUのランナーを使用していることです(GitLab共有ランナーはシングルCPUです)。さらに問題を診断する前に、出力が分析できるようにジョブを完了させる必要があります。まずマルチCPUランナーから始めて、ジョブが完了して出力がさらにレビューできるようになるまでAPIオペレーションの一部を除外することをお勧めします。

支援については、以下のドキュメント・セクションを参照してください:

API Fuzzingジョブの完了に時間がかかりすぎる

パフォーマンス・チューニングとテスト速度を参照

エラー:Error waiting for API Fuzzing 'http://127.0.0.1:5000' to become available

API Fuzzingアナライザのv1.6.196より前のバージョンには、特定の条件下でバックグラウンドプロセスが失敗するバグが存在します。この問題を解決するには、API Fuzzingアナライザを新しいバージョンに更新してください。

バージョン情報は、apifuzzer_fuzz ジョブの詳細に記載されています。

もしv1.6.196以上のバージョンでイシューが発生している場合は、以下の情報をサポートまでご連絡ください:

  1. このトラブルシューティングのセクションを参照し、イシューをDynamic Analysis Teamにエスカレーションするよう依頼してください。
  2. ジョブの完全なコンソール出力。
  3. ジョブのアーティファクトとして利用可能なgl-api-security-scanner.log ファイル。ジョブの詳細ページの右側のパネルで、Browseボタンを選択します。
  4. .gitlab-ci.yml ファイルのapifuzzer_fuzz ジョブ定義。

エラーメッセージ

  • GitLab 15.6 以降ではError waiting for API Fuzzing 'http://127.0.0.1:5000' to become available
  • GitLab 15.5以前では、Error waiting for API Security 'http://127.0.0.1:5000' to become available

Failed to start session with scanner. Please retry, and if the problem persists reach out to support.

API Fuzzing エンジンは、スキャナアプリケーションコンポーネントとの接続を確立できない場合にエラーメッセージを出力します。エラーメッセージはapifuzzer_fuzz ジョブのジョブ出力ウィンドウに表示されます。この問題の一般的な原因は、バックグラウンドコンポーネントが選択したポートをすでに使用しているため使用できないことです。このエラーは、タイミングが関係する場合(競合状態)、断続的に発生することがあります。このイシューはKubernetes環境で、他のサービスがコンテナにマッピングされてポートの競合を引き起こしている場合によく発生します。

解決策を進める前に、そのポートがすでに使用されているためにエラーメッセージが表示されたことを確認することが重要です。これが原因であることを確認するには

  1. ジョブコンソールに移動します。

  2. アーティファクトgl-api-security-scanner.log を探します。ダウンロード] を選択してすべてのアーティファクトをダウンロードしてからファイルを検索するか、[参照]を選択して直接検索を開始できます。

  3. ファイルgl-api-security-scanner.log をテキストエディタで開きます。

  4. ポートがすでに使用されていたためにエラーメッセージが表示された場合は、ファイルに以下のようなメッセージが表示されているはずです:

  • GitLab 15.5以降では

     Failed to bind to address http://127.0.0.1:5500: address already in use.
  • GitLab 15.4以前の場合:

     Failed to bind to address http://[::]:5000: address already in use.

http://[::]:5000 例えば、http://[::]:5500http://127.0.0.1:5500 などです。エラーメッセージの残りの部分が同じであれば、そのポートはすでに使われていると考えてもよいでしょう。

ポートが既に取られているという証拠が見つからなかった場合、ジョブコンソール出力に表示された同じエラーメッセージをアドレスとする他のトラブルシューティングのセクションもチェックしてください。これ以上の選択肢がない場合は、サポートを受けるか、適切なルートで改善を要求してください。

ポートが既に取られていたためにイシューが発生したことを確認したら、GitLab 15.5をインストールしてください。その後、GitLab 15.5以降では設定変数FUZZAPI_API_PORT が導入されました。この設定変数により、スキャナバックグラウンドコンポーネントの固定ポート番号を設定することができます。

解決方法

  1. .gitlab-ci.yml ファイルが設定変数FUZZAPI_API_PORT を定義していることを確認してください。
  2. FUZZAPI_API_PORT の値を1024以上の任意のポート番号に更新してください。新しい値がGitLabによって使用されていないか確認することをお勧めします。GitLabが使用するポートの一覧はPackage defaultsをご覧ください。

Error, the OpenAPI document is not valid. Errors were found during validation of the document using the published OpenAPI schema

API Fuzzingジョブの開始時に、OpenAPI仕様は公開されたスキーマに対して検証されます。このエラーは、提供されたOpenAPI Specificationに検証エラーがある場合に表示されます。エラーは OpenAPI 仕様書を手動で作成するときや、スキーマを生成するときに発生することがあります。

自動的に生成された OpenAPI 仕様書の検証エラーは、多くの場合、コード注釈の欠落によるものです。

エラーメッセージ

  • GitLab 13.11以降ではError, the OpenAPI document is not valid. Errors were found during validation of the document using the published OpenAPI schema
    • OpenAPI 2.0 schema validation error ...
    • OpenAPI 3.0.x schema validation error ...

解決方法

生成されたOpenAPI仕様について

  1. 検証エラーを特定します。
    1. Swagger Editorを使用して、仕様のバリデーションの問題を特定します。Swagger Editorの視覚的な性質により、変更すべき内容を理解しやすくなります。
    2. あるいは、ログ出力をチェックしてスキーマ検証の警告を探すこともできます。これらの警告には、OpenAPI 2.0 schema validation errorOpenAPI 3.0.x schema validation error などのメッセージが先頭に付きます。各検証の失敗により、locationdescriptionなどの追加情報が提供されます。JSON スキーマ検証メッセージは複雑な場合があり、エディターがスキーマドキュメントの検証に役立ちます。
  2. 使用しているフレームワーク/技術スタックのOpenAPI世代のドキュメントをレビューしてください。正しいOpenAPIドキュメントを作成するために必要な変更を特定します。
  3. バリデーションの問題が解決したら、パイプラインを再実行します。

手動で作成したOpenAPI仕様の場合

  1. 検証エラーを特定します。
    1. 最も簡単な解決策は、ビジュアルツールを使用してOpenAPIドキュメントを編集し、検証することです。例えば、Swagger Editorはスキーマエラーと可能な解決策をハイライトします。
    2. あるいは、ログ出力をチェックして、スキーマ検証の警告を探すこともできます。これらの警告には、OpenAPI 2.0 schema validation errorOpenAPI 3.0.x schema validation error などのメッセージが先頭に付けられています。各検証の失敗により、locationdescriptionなどの追加情報が提供されます。それぞれの検証失敗を修正し、OpenAPI ドキュメントを再提出してください。JSON スキーマの検証メッセージは複雑な場合があります。
  2. バリデーションの問題が解決したら、パイプラインを再実行します。

Failed to start scanner session (version header not found)

API Fuzzing エンジンは、スキャナアプリケーションコンポーネントとの接続を確立できない場合にエラーメッセージを出力します。エラーメッセージはapifuzzer_fuzz ジョブのジョブ出力ウィンドウに表示されます。この問題の一般的な原因は、FUZZAPI_API 変数をデフォルトから変更することです。

エラーメッセージ

  • GitLab 13.11以降ではFailed to start scanner session (version header not found).
  • GitLab 13.10以前では、API Security version header not found. Are you sure that you are connecting to the API Security server?

解決方法

  • .gitlab-ci.yml ファイルからFUZZAPI_API 変数を削除します。この値はAPI Fuzzing CI/CDテンプレートから継承されます。手動で値を設定する代わりに、この方法をお勧めします。
  • 変数を削除できない場合は、APIFuzzing CI/CDテンプレートの最新バージョンでこの値が変更されていないか確認してください。もしそうであれば、.gitlab-ci.yml ファイルの値を更新してください。

Application cannot determine the base URL for the target API

API Fuzzingアナライザは、OpenAPIドキュメントを検査してもターゲットAPIを特定できない場合にエラーメッセージを出力します。このエラーメッセージは、.gitlab-ci.ymlファイルにターゲット API が設定されていない場合、environment_url.txt ファイルにターゲット API が存在しない場合、および OpenAPI ドキュメントを使用してターゲット API を計算できなかった場合に表示されます。

異なるソースをチェックする際、API Fuzzing アナライザがターゲット API を取得しようとする優先順位があります。FUZZAPI_TARGET_URL環境変数が設定されていない場合、API Fuzzing アナライザはenvironment_url.txt ファイルの environment_url.txt使用を試みます。environment_url.txt ファイルが environment_url.txtない場合、API Fuzzing アナライザは OpenAPI ドキュメントのコンテンツとFUZZAPI_OPENAPI で提供された URL (URL が提供されている場合) を使用して、ターゲット API の計算を試みます。

最適なソリューションは、ターゲットAPIがデプロイごとに変更されるかどうかに依存します:

  • ターゲットAPIがデプロイごとに同じである場合(静的環境)は、静的環境ソリューションを使用します。
  • ターゲット API がデプロイごとに変更される場合は、動的環境ソリューションを使用します。

静的環境ソリューション

このソリューションは、ターゲットAPIのURLが変更されない(静的である)パイプラインのためのものです。

環境変数を追加します。

ターゲットAPIが変わらない環境では、FUZZAPI_TARGET_URL 環境変数を使ってターゲットURLを指定することをお勧めします。.gitlab-ci.yml ファイルに、変数FUZZAPI_TARGET_URL を追加してください。この変数には、APIテスト対象のベースURLを設定する必要があります。例えば

stages:
  - fuzz

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

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

動的環境ソリューション

動的環境では、異なるデプロイごとにターゲットAPIが変更されます。この場合、可能な解決策は1つだけではありません。動的環境を扱う場合は、environment_url.txt ファイルを使用することをお勧めします。

environment_url.txtを使用してください。

パイプラインごとにターゲットAPIのURLが変わるような動的環境に対応するため、API Fuzzingでは使用するURLを記述したenvironment_url.txt 。このファイルはリポジトリにチェックインされるのではなく、テスト対象をデプロイするジョブによってパイプライン中に作成され、パイプラインの後のジョブが使用できるアーティファクトとして収集されます。environment_url.txt ファイルを作成するジョブは API Fuzzing ジョブの前に実行する必要があります。

  1. テストターゲットのデプロイジョブを変更し、プロジェクトのルートにあるenvironment_url.txt ファイルにベース URL を追加します。
  2. environment_url.txt をアーティファクトとして収集するテスト ターゲットのデプロイ ジョブを修正します。

使用例:

deploy-test-target:
  script:
    # Perform deployment steps
    # Create environment_url.txt (example)
    - echo http://${CI_PROJECT_ID}-${CI_ENVIRONMENT_SLUG}.example.org > environment_url.txt

  artifacts:
    paths:
      - environment_url.txt

無効なスキーマで OpenAPI を使用

ドキュメントが無効なスキーマで自動生成されたり、タイムリーに手動で編集できない場合があります。そのようなシナリオでは、API Fuzzing は変数FUZZAPI_OPENAPI_RELAXED_VALIDATION を設定することで緩和的な検証を行うことができます。予期せぬ動作を防ぐために、完全に準拠したOpenAPIドキュメントを提供することを推奨します。

非準拠OpenAPIファイルの編集

OpenAPI仕様に準拠していない要素を検出して修正するには、エディタの使用をお勧めします。エディタは一般的に、ドキュメントの検証や、スキーマに準拠した OpenAPI ドキュメントを作成するための提案を行います。推奨されるエディタは以下の通りです:

エディタ|OpenAPI 2.0|OpenAPI 3.0.x|OpenAPI 3.1.x| –| –| –||Swaggerエディタ |{check-circle}|YAML、JSONYAML、JSON|{check-circle}YAML、JSON|{check-circle}JSONYAML、JSON|{dotted-circle} YAML、JSON|{dotted-circle}YAML、JSONYAML, JSON Stoplight Studio {チェック-サークル} YAML, JSON{チェック-サークルYAML、JSON|{チェック-サークル}|Stoplight Studio|{チェック-サークルYAML, JSON{チェック・サークル} YAML, JSON{チェック・サークルYAML、JSON|チェック・サークル

OpenAPIドキュメントが手動で生成されている場合、ドキュメントをエディタに読み込み、非準拠な部分を修正します。ドキュメントが自動的に生成された場合は、それをエディタで読み込んでスキーマのイシューを特定し、アプリケーションに移動して、使用しているフレームワークに基づいて修正を行います。

OpenAPI緩和検証を有効にします

緩和されたバリデーションは、OpenAPIドキュメントがOpenAPI仕様に適合していないけれども、さまざまなツールで利用するのに十分なコンテンツを持っているような場合のためのものです。検証は行われますが、ドキュメントスキーマに関してはそれほど厳密ではありません。

API FuzzingはOpenAPI仕様に完全に準拠していないOpenAPIドキュメントの利用を試みることができます。API Fuzzing アナライザに緩和された検証を行うように指示するには、変数FUZZAPI_OPENAPI_RELAXED_VALIDATION に任意の値を設定します:

stages:
  - fuzz

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

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

No operation in the OpenAPI document is consuming any supported media type

API FuzzingはOpenAPIドキュメントで指定されたメディアタイプを使用してリクエストを生成します。サポートされているメディアタイプがないためにリクエストを作成できない場合は、エラーがスローされます。

エラーメッセージ

  • GitLab 14.10以降の場合、Error, no operation in the OpenApi document is consuming any supported media type. Check 'OpenAPI Specification' to check the supported media types.

解決方法

  1. OpenAPI仕様のセクションでサポートされているメディアタイプをレビューしてください。
  2. OpenAPI ドキュメントを編集して、少なくとも指定されたオペレーションが、サポートされているメディアタイプのどれでも受け入れられるようにします。あるいは、サポートされるメディアタイプを OpenAPI ドキュメントレベルで設定し、すべてのオペレーションに適用することもできます。このステップでは、サポートされているメディアタイプがアプリケーションで受け入れられるように、アプリケーションの変更が必要になるかもしれません。

Error, error occurred trying to download `<URL>`: There was an error when retrieving content from Uri:' <URL>'. Error:The SSL connection could not be established, see inner exception.

API ファジングは、時代遅れのプロトコルや暗号を含む、幅広い TLS 設定に対応しています。幅広いサポートにもかかわらず、接続エラーが発生する場合があります。このエラーは、APIファジングが指定されたURLのサーバーとのセキュアな接続を確立できなかったために発生します。

イシューを解決するには

エラーメッセージのホストが非TLS接続をサポートしている場合は、設定でhttps://http:// に変更してください。たとえば、以下の設定でエラーが発生した場合:

stages:
  - fuzz

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

variables:
  FUZZAPI_TARGET_URL: https://test-deployment/
  FUZZAPI_OPENAPI: https://specs/openapi.json

FUZZAPI_OPENAPI のプレフィックスをhttps:// からhttp:// に変更します:

stages:
  - fuzz

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

variables:
  FUZZAPI_TARGET_URL: https://test-deployment/
  FUZZAPI_OPENAPI: http://specs/openapi.json

URLにアクセスするために非TLS接続を使用できない場合は、サポートチームにお問い合わせください。

testssl.shツールを使用すると、調査を迅速に行うことができます。Bashシェルがあり、影響を受けるサーバーに接続できるマシンから:

  1. 最新リリースのzip またはtar.gz ファイルをダウンロードし、https://github.com/drwetter/testssl.sh/releasesから展開します。
  2. ./testssl.sh --log https://specs を実行してください。
  3. ログファイルをサポートチケットに添付してください。

ERROR: Job failed: failed to pull image

このエラーメッセージは、アクセスに認証が必要な(公開されていない)コンテナレジストリからイメージを取り出したときに発生します。

ジョブコンソールの出力では、エラーは次のようになります:

Running with gitlab-runner 15.6.0~beta.186.ga889181a (a889181a)
  on blue-2.shared.runners-manager.gitlab.com/default XxUrkriX
Resolving secrets
00:00
Preparing the "docker+machine" executor
00:06
Using Docker executor with image registry.gitlab.com/security-products/api-security:2 ...
Starting service registry.example.com/my-target-app:latest ...
Pulling docker image registry.example.com/my-target-app:latest ...
WARNING: Failed to pull image with policy "always": Error response from daemon: Get https://registry.example.com/my-target-app/manifests/latest: unauthorized (manager.go:237:0s)
ERROR: Job failed: failed to pull image "registry.example.com/my-target-app:latest" with specified policies [always]: Error response from daemon: Get https://registry.example.com/my-target-app/manifests/latest: unauthorized (manager.go:237:0s)

エラーメッセージ

  • GitLab 15.9 以前では、ERROR: Job failed: failed to pull image の後にError response from daemon: Get IMAGE: unauthorized.

解決方法

認証情報は、「非公開のコンテナレジストリからイメージにアクセスする」 ドキュメントのセクションで説明した方法を使用します。使用する方法は、コンテナレジストリのプロバイダとその設定によって決まります。クラウドプロバイダー(Azure、Google Could(GCP)、AWS など)などのサードパーティーが提供するコンテナレジストリを使用している場合は、プロバイダーのコンテナレジストリへの認証方法について、プロバイダーのドキュメントを確認してください。

以下の例では、静的に定義された認証情報を使用します。この例では、コンテナレジストリはregistry.example.com で、イメージはmy-target-app:latest です。

  1. DOCKER_AUTH_CONFIG データの決定方法 を読んで、DOCKER_AUTH_CONFIG の変数値の計算方法を理解してください。設定変数DOCKER_AUTH_CONFIG には、適切な認証情報を提供するためのDocker JSON設定が含まれています。例えば、非公開コンテナレジストリregistry.example.com に認証情報aGVsbG8gd29ybGQKでアクセスする場合、Docker JSONは以下のようになります:

    {
        "auths": {
            "registry.example.com": {
                "auth": "aGVsbG8gd29ybGQK"
            }
        }
    }
    
  2. CI/CD 変数としてDOCKER_AUTH_CONFIG を追加します。設定変数を.gitlab-ci.yml ファイルに直接追加する代わりに、プロジェクトCI/CD 変数を作成する必要があります。
  3. ジョブを再実行すると、静的に定義された認証情報が非公開コンテナレジストリregistry.example.com にサインインするために使用され、イメージmy-target-app:latest をプルできるようになります。成功すると、ジョブコンソールに次のような出力が表示されます:

    Running with gitlab-runner 15.6.0~beta.186.ga889181a (a889181a)
      on blue-4.shared.runners-manager.gitlab.com/default J2nyww-s
    Resolving secrets
    00:00
    Preparing the "docker+machine" executor
    00:56
    Using Docker executor with image registry.gitlab.com/security-products/api-security:2 ...
    Starting service registry.example.com/my-target-app:latest ...
    Authenticating with credentials from $DOCKER_AUTH_CONFIG
    Pulling docker image registry.example.com/my-target-app:latest ...
    Using docker image sha256:139c39668e5e4417f7d0eb0eeb74145ba862f4f3c24f7c6594ecb2f82dc4ad06 for registry.example.com/my-target-app:latest with digest registry.example.com/my-target-
    app@sha256:2b69fc7c3627dbd0ebaa17674c264fcd2f2ba21ed9552a472acf8b065d39039c ...
    Waiting for services to be up and running (timeout 30 seconds)...

サポートまたは改善要求

特定の問題についてサポートを受けるには、ヘルプを得るチャンネルをご利用ください。

GitLab.comのGitLabイシュー・トラッカーは、APIセキュリティとAPIファジングに関するバグや機能提案を行うのに適した場所です。API ファジングに関する新しいイシューをオープンするときは、~"Category:API Security" ラベルを使って、適切な担当者が素早くレビューできるようにしましょう。レビュアーがいつレスポンスを受け取るべきかを理解するために、レビュアーレスポンスSLOを参照してください。

自分自身の課題を提出する前に、類似のエントリがないかイシュー・トラッカーを検索してください。絵文字によるリアクションやディスカッションへの参加で、あなたのサポートを示しましょう。

期待通りに動作しない動作が発生した場合は、コンテキスト情報を提供することを検討してください:

  • セルフマネージドインスタンスを使用している場合は GitLab のバージョン。
  • .gitlab-ci.yml ジョブの定義
  • 完全なジョブコンソール出力。
  • gl-api-security-scanner.log という名前のジョブアーティファクトとして利用可能なスキャナログファイル。
caution
サポート・イシューに添付されたデータをサニタイズします。クレデンシャル、パスワード、トークン、キー、シークレットなどの機密情報を削除します。

用語解説

  • アサート:アサーションは、チェックがフォールトをトリガーするために使用する検出モジュールです。多くのアサーションには設定があります。チェックは複数のアサーションを使用できます。例えば、ログ解析、レスポンス解析、およびステータス・コードは、チェックで一緒に使用される一般的なアサーションです。複数のアサーションを持つ検査では、アサーションのオンとオフを切り替えることができます。
  • チェック:特定の種類のテストを実行したり、脆弱性の種類のチェックを実行したりします。例えば、JSON ファジングチェックは JSON ペイロードのファジングテストを実行します。APIファザーは複数のチェックで構成されています。チェックはプロファイルでオンまたはオフにできます。
  • 障害:ファジングの間、アサートによって識別された失敗は、フォルトと呼ばれます。フォルトは、セキュリティの脆弱性なのか、非セキュリティの問題なのか、あるいは、誤検出なのかを判断するために調査されます。フォールトは、調査されるまでは、既知の脆弱性のタイプを持っていません。脆弱性のタイプの例としては、SQL インジェクションや Denial of Service があります。
  • プロファイル:設定ファイルには 1 つ以上のテストプロファイル、あるいはサブ設定があります。機能ブランチ用のプロファイルと、メインブランチ用の特別なテスト用のプロファイルがあるかもしれません。