OWASP ZAP REST APIを使って、Swagger REST APIをテストする(2)使用方法


本記事の経緯

Azure Pipelinesを使って、Swaggerで作成したREST APIのセキュリティテストをしたかったけど、OWASP ZAP周りの情報でズバリ欲しかったものが見当たらなかったので、まとめてみました。

本記事の概要

Swaggerで作成したREST APIを、OWASP ZAP REST APIでテストする方法をまとめました。
本記事は (1)環境構築 の続きです。

使用するソフトウェア

  • Windows 10 + PowerShell 5

OWASP ZAP REST APIのヘルプ

OWASP ZAP REST APIのヘルプは、OWASP ZAPが起動している時に http://localhost:8888/UI にアクセスするとあります。でも正直、分かりにくいです……。

保存されている警告を削除する

OWASP ZAPはテストを実施する度に警告を溜め込んでいくのですが、いつ検知した警告なのか分かりにくいし、アプリを改修して再テストした時に直っていないようにみえてしまって、ちょっと不便です。
なので、テストを実施する前に、溜め込んでいる警告を一旦削除しましょう。

$zap_headers = @{
    'Accept' = 'application/json';
}

$zap_url = "http://localhost:8888/JSON/core/action/deleteAllAlerts/?apikey=<API Key>"
Invoke-RestMethod -Method "GET" -Uri "${zap_url}" -Headers $zap_headers

Swaggerで作成したREST APIをテストする

JSONで記述したSwagger定義ファイルを用意して、以下を実行します。

$zap_headers = @{
    'Accept' = 'application/json';
}

$zap_url = "http://localhost:8888/JSON/openapi/action/importFile/?apikey=<API Key>&file=<Swagger定義ファイル>"
$result = Invoke-RestMethod -Method "GET" -Uri "${zap_url}" -TimeoutSec 600 -Headers $zap_headers

レスポンス $result は以下のようになります。

$result
{
    "importFile": [ エラーメッセージ ]
}

テストは非同期で実施されます。よってこの時点ではまだテストは終わっていません。Swagger定義ファイルの読み込み時に何らかの問題が発生した場合は、レスポンスの importFile にエラーメッセージが格納されます。

テストの状態を調べる

テストがまだ終わっていない時にレポートを作成してしまうと、内容が不正確になります。そういう時は、以下を実行してテストの状態を把握すると便利です。

$zap_headers = @{
    'Accept' = 'application/json';
}

$zap_url = "http://localhost:8888/JSON/pscan/view/recordsToScan/?apikey=<API Key>"
$result = Invoke-RestMethod -Method "GET" -Uri "${zap_url}" -Headers $zap_headers

レスポンス $result は以下のようになります。

$result
{
    "recordsToScan": 残りのテスト数
}

recordsToScan が0であれば、全てのテストは終了しています。

レポートを作成する

検知した警告のレポートをJSONで作成します。

$zap_headers = @{
    'Accept' = 'application/json';
}

$zap_url = "http://localhost:8888/OTHER/core/other/jsonreport/?apikey=<API Key>"
$result = Invoke-RestMethod -Method "GET" -Uri "${zap_url}" -Headers $zap_headers

レスポンス $result は以下のようになります。

$result
{
    "@version": OWASP ZAPのバージョン,
    "@generated": レポート作成日,
    "site": {
        "@name": テスト対象のサイトURL,
        "@host": テスト対象のホスト名,
        "@port": テスト対象のポート番号,
        "@ssl": SSLの場合はtrue,
        "alerts":  [
            "name": 警告の名称,
            "pluginId": 警告のID
            "alert": 警告の種類,
            "riskcode": リスク度,
            "riskdesc": リスク度の概要,
            "confidence": 信用度,
            "desc": 警告の概要,
            "count": テスト対象の個数,
            "instances": [
                {
                    "uri": テスト対象のURL,
                    "method": テスト対象のメソッド,
                    "param": テスト結果のパラメータ
                }
            ],
            "solution": 警告の解決方法,
            "otherinfo": その他情報,
            "reference": 警告に関する参照URL
        ]
    }
}

riskcode については以下の通りです。

意味
0 Information
1 Low
2 Medium
3 High