- Web API ファジングの実行時
- Web API ファジングの有効化
- APIファジングの設定
- 最初のスキャンの実行
- ファジングフォルトの表示
- 誤検出への対処
- オフライン環境でのAPIファジングの実行
- パフォーマンス・チューニングとテスト速度
-
トラブルシューティング
- APIファジングのジョブがN時間後にタイムアウトします。
- API Fuzzingジョブの完了に時間がかかりすぎる
- エラー:
Error waiting for API Fuzzing '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.
Error, the OpenAPI document is not valid. Errors were found during validation of the document using the published OpenAPI schema
Failed to start scanner session (version header not found)
-
Application cannot determine the base URL for the target API
- 無効なスキーマで OpenAPI を使用
No operation in the OpenAPI document is consuming any supported media type
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.
ERROR: Job failed: failed to pull image
- サポートまたは改善要求
- 用語解説
ウェブ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ファジングテンプレートは
build
、test
、deploy
、fuzz
ステージをfuzz
定義します。fuzz
ステージはfuzz
デフォルトで最後に実行されます。定義済みのステージは非推奨となり、API-Fuzzing.latest.gitlab-ci.yml
テンプレートから削除されました。将来のGitLabバージョンで削除する予定です。
パイプラインが毎回同じWebサーバーにデプロイされるように設定されている場合、別のパイプラインがまだ実行されている間にパイプラインを実行すると、あるパイプラインが別のパイプラインのコードを上書きするという競合状態を引き起こす可能性があります。スキャンするAPIは、ファジングスキャン期間中は変更しないようにします。APIへの変更は、ファジングスキャナーからのものだけにしてください。スキャン中に(ユーザー、スケジュールされたタスク、データベースの変更、コードの変更、他のパイプライン、または他のスキャナーによって)APIに加えられた変更は、不正確な結果を引き起こす可能性があります。
Web API ファジングスキャンは、以下の方法で実行できます:
- OpenAPI 仕様- バージョン 2 および 3.
- GraphQL スキーマ
- HTTPアーカイブ (HAR)
- Postmanコレクション- バージョン2.0または2.1
これらのメソッドを使ったプロジェクトの例があります:
- OpenAPI v2 仕様プロジェクトの例
- Example HTTP Archive(HAR) プロジェクト
- Postman コレクション・プロジェクトの例
- GraphQL プロジェクトの例
- SOAP プロジェクトの例
- Seleniumを使った認証トークン
Web API ファジングの有効化
要件
- 以下のWeb APIタイプのいずれか:
- REST API
- SOAP
- GraphQL
- フォームボディ、JSON、またはXML
- テストするAPIを提供する以下のアセットのいずれか:
- OpenAPI v2またはv3のAPI定義
- テストする API リクエストの HTTP アーカイブ(HAR)
- Postman コレクション v2.0 または v2.1
運用サーバーに対してファズテストを実行しないでください。APIが実行できるあらゆる機能を実行できるだけでなく、APIのバグを誘発する可能性があります。これには、データの変更や削除などのアクションが含まれます。テストサーバーに対してのみファジングを実行してください。
Web APIファジングを有効にするには
- API fuzzing テンプレートを
.gitlab-ci.yml
ファイルに含めます。 -
GitLab 13.10以降では、Web 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の設定スニペットを生成します:
- 左のサイドバーで「検索」または「移動」を選択してあなたのプロジェクトを検索します。
- セキュア > セキュリティ設定を選択します。
- API Fuzzing] の行で、[Enable API Fuzzing] を選択します。
- フィールドを入力します。詳細については、利用可能なCI/CD変数を参照してください。
- Generate code snippet を選択します。モーダルが開き、フォームで選択したオプションに対応する YAML スニペットが表示されます。
- 以下のいずれかを行いましょう:
- スニペットをクリップボードにコピーするには、「コードのみをコピー」を選択します。
- スニペットをプロジェクトの
.gitlab-ci.yml
ファイルに追加するには、Copy code を選択し、.gitlab-ci.yml
ファイルを開きます。パイプラインエディターが開きます。- スニペットを
.gitlab-ci.yml
ファイルに貼り付けます。 -
Lintタブを選択し、編集した
.gitlab-ci.yml
ファイルが有効であることを確認します。 - [Edit] タブを 選択 し、 [Commit changes] を** 選択 **します。
- スニペットを
スニペットが.gitlab-ci.yml
ファイルにコミットされると、パイプラインに API Fuzzing ジョブが含まれます。
OpenAPIの仕様
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/json
とapplication/xml
)、テストはJSONを使って実行され、次にXMLを使って同じテストが実行されます。
異なるメディアタイプ(たとえば、application/json
とapplication/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-urlencoded
とmultipart/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_TYPES
とFUZZAPI_OPENAPI_MEDIA_TYPES
でメディアタイプの扱い方を決めることができます。これらの設定は互いに排他的です。両方が有効な場合、API Fuzzingはエラーを報告します。
OpenAPI 仕様による Web API ファジングの設定
OpenAPI仕様を使ってGitLabでAPIファジングを設定するには:
-
.gitlab-ci.yml
ファイルにfuzz
ステージを追加します。 -
API-Fuzzing.gitlab-ci.yml
テンプレート を.gitlab-ci.yml
ファイルに含めます。 -
.gitlab-ci.yml
ファイルにFUZZAPI_PROFILE
CI/CD 変数を追加して、プロファイルを指定します。プロファイルは、テストの実行回数を指定します。選択したプロファイルはQuick-10
に置き換えてください。詳細については、APIファジングプロファイルを参照してください。variables: FUZZAPI_PROFILE: Quick-10
-
OpenAPI Specification の場所を指定します。ファイルまたは URL で指定できます。
FUZZAPI_OPENAPI
変数を追加して場所を指定します。 -
ターゲット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アーカイブフォーマットを参照してください。
HAR ファイルを使った Web API ファジングの設定
HAR ファイルを使用する API ファジングを設定します:
-
.gitlab-ci.yml
ファイルにfuzz
ステージを追加します。 -
API-Fuzzing.gitlab-ci.yml
テンプレート を.gitlab-ci.yml
ファイルに含めます。 -
.gitlab-ci.yml
ファイルにFUZZAPI_PROFILE
CI/CD 変数を追加して、プロファイルを指定します。プロファイルは、テストの実行回数を指定します。選択したプロファイルはQuick-10
に置き換えてください。詳細については、APIファジングプロファイルを参照してください。variables: FUZZAPI_PROFILE: Quick-10
-
HAR仕様の場所を指定します。ファイルまたはURLで指定できます。URLのサポートはGitLab 13.10以降で導入されました。
FUZZAPI_HAR
変数を追加して場所を指定してください。 -
ターゲット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エンドポイントをクエリできます。
テスト対象のAPIに関する情報を提供するGraphQLエンドポイントURLを使用するようにAPI Fuzzingを設定するには、以下の手順に従います:
-
.gitlab-ci.yml
ファイルにAPI-Fuzzing.gitlab-ci.yml
テンプレート を含めます。 -
例えば
/api/graphql
のように、GraphQL エンドポイントのパスを指定します。FUZZAPI_GRAPHQL
変数を追加してパスを指定します。 -
ターゲット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スキーマファイルを使用します:
-
.gitlab-ci.yml
ファイルにAPI-Fuzzing.gitlab-ci.yml
テンプレート を含めます。 -
例えば
/api/graphql
のように、GraphQL エンドポイントのパスを指定します。FUZZAPI_GRAPHQL
変数を追加してパスを指定します。 -
GraphQLスキーマファイルの場所を指定します。ファイルのパスまたは URL として場所を指定できます。
FUZZAPI_GRAPHQL_SCHEMA
変数を追加して場所を指定します。 -
ターゲット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定義を抽出し、テストを実行するためにそれらを使用します。
Postman コレクションファイルによる Web API ファジングの設定
Postman Collectionファイルを使用するAPIファジングを設定します:
-
.gitlab-ci.yml
ファイルにfuzz
ステージを追加します。 -
API-Fuzzing.gitlab-ci.yml
テンプレート を.gitlab-ci.yml
ファイルに含めます。 -
.gitlab-ci.yml
ファイルにFUZZAPI_PROFILE
CI/CD 変数を追加して、プロファイルを指定します。プロファイルは、テストの実行回数を指定します。選択したプロファイルはQuick-10
に置き換えてください。詳細については、APIファジングプロファイルを参照してください。variables: FUZZAPI_PROFILE: Quick-10
-
Postman Collection仕様の場所を指定します。ファイルまたはURLで指定できます。URL サポートは GitLab 13.10 以降で導入されました。
FUZZAPI_POSTMAN_COLLECTION
変数を追加して場所を指定します。 -
ターゲット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 の変数
Postman クライアントの変数
Postman では開発者がリクエストの様々な部分で使えるプレースホルダを定義できます。変数の使い方で説明したように、これらのプレースホルダは変数と呼ばれます。変数を使ってリクエストやスクリプトに値を保存したり再利用したりできます。たとえば、コレクションを編集してドキュメントに変数を追加できます:
あるいは、環境変数を追加することもできます:
URLやヘッダーなどのセクションで変数を使うことができます:
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 ファイルの名前と値を持つ変数のグループです。NewmanやPostman 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_url
とtoken
を定義しています:
{
"base_url": "http://127.0.0.1/",
"token": "Token 84816165151"
}
API Fuzzing でのスコープの使用
GitLab15.1以降では、global、environment、collection、GitLab 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はランダムな値を使います。
スキャン処理中にサポートされる動的変数は以下の通りです:
変数 | 値 |
---|---|
$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 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
ディレクトリになければなりません。
認証
認証は、認証トークンをヘッダまたはクッキーとして提供することで処理されます。認証フローを実行したりトークンを計算したりするスクリプトを提供することができます。
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
でベアラートークンを提供してください:
-
CI/CD 変数、例えば
TEST_API_BEARERAUTH
を作成し、値を{"headers":{"Authorization":"Bearer dXNlcm5hbWU6cGFzc3dvcmQ="}}
とします(トークンを代入してください)。CI/CD変数はGitLabプロジェクトページのSettings > CI/CDの Variablesセクションから作成できます。 -
.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
-
認証が機能していることを確認するには、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
を提供します。このファイルには、特定の数のテストを実行するいくつかのテストプロファイルが含まれています。テストの数が増えるにつれて、それぞれのプロファイルの実行時間は長くなります。
プロファイル | ファズテスト(パラメータごと) |
---|---|
クイック10 | 10 |
ミディアム-20 | 20 |
中-50 | 50 |
ロング100 | 100 |
利用可能な CI/CD 変数
CI/CD 変数 | 説明 |
---|---|
SECURE_ANALYZERS_PREFIX | アナライザをダウンロードするDockerレジストリのベースアドレスを指定します。 |
FUZZAPI_VERSION | API Fuzzingコンテナのバージョンを指定します。デフォルトは2 。 |
FUZZAPI_IMAGE_SUFFIX | コンテナイメージのサフィックスを指定します。デフォルトはnone。 |
FUZZAPI_API_PORT | API Fuzzingエンジンが使用する通信ポート番号を指定します。デフォルトは5500 。 GitLab 15.5で導入。 |
FUZZAPI_TARGET_URL | APIテスト対象のベースURL。 |
FUZZAPI_CONFIG | GitLab 13.12 で非推奨となり、デフォルトの.gitlab/gitlab-api-fuzzing-config.yml に置き換えられました。API Fuzzing設定ファイル。 |
FUZZAPI_PROFILE | テスト中に使用する設定プロファイル。デフォルトはQuick-10 。 |
FUZZAPI_EXCLUDE_PATHS | API 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_OPENAPI | OpenAPI仕様ファイルまたは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_HAR | HTTP アーカイブ(HAR) ファイル。 |
FUZZAPI_GRAPHQL | GraphQLエンドポイントへのパス、例えば/api/graphql 。GitLab 15.4で導入されました。 |
FUZZAPI_GRAPHQL_SCHEMA | JSON形式のGraphQLスキーマのURLまたはファイル名。GitLab 15.4で導入。 |
FUZZAPI_POSTMAN_COLLECTION | Postman コレクションファイル。 |
FUZZAPI_POSTMAN_COLLECTION_VARIABLES | Postman変数の値を抽出する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_USERNAME | HTTP認証のユーザー名。 |
FUZZAPI_HTTP_PASSWORD | HTTP認証のパスワード |
FUZZAPI_HTTP_PASSWORD_BASE64 | Base64エンコードされた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.yml
、FUZZAPI_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.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ファザーが指定された間隔で実行するプログラムまたはスクリプトを提供することができます。提供されたスクリプトは、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
:アナライザが起動する前にランタイムまたは依存関係をインストールするスクリプト。
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 Operations
と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: ------------------------------------------------
除外パスの例
この例では/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-REQUESTS
はUpgrade-Insecure-Requests
と等価です。
ヘッダと二つのクッキーの両方を除きます。
ヘッダAuthorization
とクッキーPHPSESSID
とcsrftoken
を除外するには、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: ------------------------------------------------
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/buy
とhttp://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/buy
とhttp://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/create
とhttps://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
セクションで、HeaderFuzzing
とHeaders
の設定を変更して、ヘッダー・ファジングを有効にする必要があります。
このスニペットは、ヘッダーファジングを無効にした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メッセージに関する詳細な情報が、行われた修正の説明とともに提供されます。
ファジング障害の詳細を表示するには、次の手順に従います:
-
プロジェクトやマージリクエストのフォールトを見ることができます:
- プロジェクトで、プロジェクトのセキュリティ > 脆弱性レポートページに移動します。このページには、デフォルトブランチからのすべての脆弱性のみが表示されます。
- マージリクエストでは、マージリクエストのセキュリティセクションに移動し、展開ボタンを選択します。API Fuzzing フォルトは、API Fuzzing detected N potential vulnerabilitiesというラベルの付いたセクションで利用できます。タイトルを選択すると、フォルトの詳細が表示されます。
-
フォルトのタイトルを選択すると、フォルトの詳細が表示されます。これらの詳細については、以下の表で説明します。
項目 説明 説明 何が変更されたかを含むフォルトの説明。 プロジェクト 脆弱性が検出された名前空間とプロジェクト。 方法 脆弱性の検出に使用される 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
) だけを提供しています。これにより、FormBodyFuzzingCheck
がStatusCodeAssertion
を使用することを防ぎます:
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テストジョブを正常に実行するためにいくつかの調整が必要です。
ステップ
- ローカルのコンテナレジストリにDockerイメージをホストします。
-
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"
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秒の大部分を占めているのです。
このイシューに対して、チームは次のことを決定するかもしれません:
- マルチCPUランナーの使用。マルチCPUランナーを使うことで、API Fuzzingが実行する作業を並列化することができます。これはテスト時間を短縮するのに役立ちますが、テストにかかるオペレーションが長いため、高CPUマシンに移行せずにテストを10分未満にするのはまだ問題があるかもしれません。
- CPU数とコストのトレードオフ。
- このオペレーションを API ファジング・テストから除外してください。これは最も単純ですが、セキュリティテストのカバレッジにギャップがあるという欠点があります。
- このオペレーションを機能ブランチの API ファジングテストから除外し、デフォルトブランチのテストには含めます。
- API Fuzzingテストを複数のジョブに分割します。
チームの要件が5-7分の範囲にあると仮定すると、これらの解決策を組み合わせて、許容可能なテスト時間を達成することが考えられます。
パフォーマンス問題へのアドレス
以下のセクションでは、API Fuzzingのパフォーマンス問題に対処するためのさまざまなオプションについて説明します:
マルチCPUランナーの使用
API FuzzingでマルチCPUランナーを使うことで、最も簡単にパフォーマンスを向上させることができます。この表はJava Spring Boot REST APIのベンチマークで収集された統計情報です。このベンチマークでは、ターゲットとAPI Fuzzingは単一のRunnerインスタンスを共有しています。
CPU数 | リクエスト/秒 |
---|---|
1CPU(共有ランナー) | 75 |
4 CPU | 255 |
8 CPU | 400 |
この表からわかるように、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_PATHS
とFUZZAPI_EXCLUDE_URLS
を使ってテストを複数のジョブに分割することができます。テストを分割する場合、apifuzzer_fuzz
のジョブを無効にし、それを識別名のついた二つのジョブで置き換えるのが良いパターンです。この例では2つのジョブがあり、それぞれのジョブはAPIのバージョンをテストしているので、名前はそれを反映しています。しかし、このテクニックはAPIのバージョンに限らず、どんな状況にも適用できます。
apifuzzer_v1
とapifuzzer_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以上のバージョンでイシューが発生している場合は、以下の情報をサポートまでご連絡ください:
- このトラブルシューティングのセクションを参照し、イシューをDynamic Analysis Teamにエスカレーションするよう依頼してください。
- ジョブの完全なコンソール出力。
- ジョブのアーティファクトとして利用可能な
gl-api-security-scanner.log
ファイル。ジョブの詳細ページの右側のパネルで、Browseボタンを選択します。 -
.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環境で、他のサービスがコンテナにマッピングされてポートの競合を引き起こしている場合によく発生します。
解決策を進める前に、そのポートがすでに使用されているためにエラーメッセージが表示されたことを確認することが重要です。これが原因であることを確認するには
-
ジョブコンソールに移動します。
-
アーティファクト
gl-api-security-scanner.log
を探します。ダウンロード] を選択してすべてのアーティファクトをダウンロードしてからファイルを検索するか、[参照]を選択して直接検索を開始できます。 -
ファイル
gl-api-security-scanner.log
をテキストエディタで開きます。 -
ポートがすでに使用されていたためにエラーメッセージが表示された場合は、ファイルに以下のようなメッセージが表示されているはずです:
-
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://[::]:5500
やhttp://127.0.0.1:5500
などです。エラーメッセージの残りの部分が同じであれば、そのポートはすでに使われていると考えてもよいでしょう。
ポートが既に取られているという証拠が見つからなかった場合、ジョブコンソール出力に表示された同じエラーメッセージをアドレスとする他のトラブルシューティングのセクションもチェックしてください。これ以上の選択肢がない場合は、サポートを受けるか、適切なルートで改善を要求してください。
ポートが既に取られていたためにイシューが発生したことを確認したら、GitLab 15.5をインストールしてください。その後、GitLab 15.5以降では設定変数FUZZAPI_API_PORT
が導入されました。この設定変数により、スキャナバックグラウンドコンポーネントの固定ポート番号を設定することができます。
解決方法
-
.gitlab-ci.yml
ファイルが設定変数FUZZAPI_API_PORT
を定義していることを確認してください。 -
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仕様について
- 検証エラーを特定します。
- Swagger Editorを使用して、仕様のバリデーションの問題を特定します。Swagger Editorの視覚的な性質により、変更すべき内容を理解しやすくなります。
- あるいは、ログ出力をチェックしてスキーマ検証の警告を探すこともできます。これらの警告には、
OpenAPI 2.0 schema validation error
やOpenAPI 3.0.x schema validation error
などのメッセージが先頭に付きます。各検証の失敗により、location
やdescription
などの追加情報が提供されます。JSON スキーマ検証メッセージは複雑な場合があり、エディターがスキーマドキュメントの検証に役立ちます。
- 使用しているフレームワーク/技術スタックのOpenAPI世代のドキュメントをレビューしてください。正しいOpenAPIドキュメントを作成するために必要な変更を特定します。
- バリデーションの問題が解決したら、パイプラインを再実行します。
手動で作成したOpenAPI仕様の場合
- 検証エラーを特定します。
- 最も簡単な解決策は、ビジュアルツールを使用してOpenAPIドキュメントを編集し、検証することです。例えば、Swagger Editorはスキーマエラーと可能な解決策をハイライトします。
- あるいは、ログ出力をチェックして、スキーマ検証の警告を探すこともできます。これらの警告には、
OpenAPI 2.0 schema validation error
やOpenAPI 3.0.x schema validation error
などのメッセージが先頭に付けられています。各検証の失敗により、location
やdescription
などの追加情報が提供されます。それぞれの検証失敗を修正し、OpenAPI ドキュメントを再提出してください。JSON スキーマの検証メッセージは複雑な場合があります。
- バリデーションの問題が解決したら、パイプラインを再実行します。
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 ジョブの前に実行する必要があります。
- テストターゲットのデプロイジョブを変更し、プロジェクトのルートにある
environment_url.txt
ファイルにベース URL を追加します。 -
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.
解決方法
- OpenAPI仕様のセクションでサポートされているメディアタイプをレビューしてください。
- 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シェルがあり、影響を受けるサーバーに接続できるマシンから:
- 最新リリースの
zip
またはtar.gz
ファイルをダウンロードし、https://github.com/drwetter/testssl.sh/releasesから展開します。 -
./testssl.sh --log https://specs
を実行してください。 - ログファイルをサポートチケットに添付してください。
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
です。
-
DOCKER_AUTH_CONFIG
データの決定方法 を読んで、DOCKER_AUTH_CONFIG
の変数値の計算方法を理解してください。設定変数DOCKER_AUTH_CONFIG
には、適切な認証情報を提供するためのDocker JSON設定が含まれています。例えば、非公開コンテナレジストリregistry.example.com
に認証情報aGVsbG8gd29ybGQK
でアクセスする場合、Docker JSONは以下のようになります:{ "auths": { "registry.example.com": { "auth": "aGVsbG8gd29ybGQK" } } }
- CI/CD 変数として
DOCKER_AUTH_CONFIG
を追加します。設定変数を.gitlab-ci.yml
ファイルに直接追加する代わりに、プロジェクトCI/CD 変数を作成する必要があります。 -
ジョブを再実行すると、静的に定義された認証情報が非公開コンテナレジストリ
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
という名前のジョブアーティファクトとして利用可能なスキャナログファイル。
用語解説
- アサート:アサーションは、チェックがフォールトをトリガーするために使用する検出モジュールです。多くのアサーションには設定があります。チェックは複数のアサーションを使用できます。例えば、ログ解析、レスポンス解析、およびステータス・コードは、チェックで一緒に使用される一般的なアサーションです。複数のアサーションを持つ検査では、アサーションのオンとオフを切り替えることができます。
- チェック:特定の種類のテストを実行したり、脆弱性の種類のチェックを実行したりします。例えば、JSON ファジングチェックは JSON ペイロードのファジングテストを実行します。APIファザーは複数のチェックで構成されています。チェックはプロファイルでオンまたはオフにできます。
- 障害:ファジングの間、アサートによって識別された失敗は、フォルトと呼ばれます。フォルトは、セキュリティの脆弱性なのか、非セキュリティの問題なのか、あるいは、誤検出なのかを判断するために調査されます。フォールトは、調査されるまでは、既知の脆弱性のタイプを持っていません。脆弱性のタイプの例としては、SQL インジェクションや Denial of Service があります。
- プロファイル:設定ファイルには 1 つ以上のテストプロファイル、あるいはサブ設定があります。機能ブランチ用のプロファイルと、メインブランチ用の特別なテスト用のプロファイルがあるかもしれません。