OWASP ZAPで脆弱性診断を始めよう——Dockerとclaude codeで環境ごとのスクリプトを自動生成する
はじめに
「脆弱性診断って、やった方がいいのは分かってるけど、何から始めればいいか分からない」
開発者の多くが感じているであろうこのハードルに対して、今回は OWASP ZAP というオープンソースの脆弱性診断ツールを紹介します。
OWASP ZAPは、Webアプリケーションに対して自動的にセキュリティスキャンを実行し、SQLインジェクションやXSSなどの脆弱性を検出するツールです。GUIでも使えますが、CIに組み込んだりサーバ上で定期実行するには Docker + スクリプト の構成が実用的です。
ただし、ここで1つ壁があります。ZAPのスキャン設定は検証環境ごとに異なり、対象URLや認証方式、除外パスなどをケースバイケースで調整する必要があるのです。これが「難しそう」と感じる原因の1つでしょう。
この記事では、Claude Codeを使ってその環境固有のZAPスキャンスクリプトを生成する方法を紹介します。さらに、GitHubで公開されているセキュリティ監査用プロンプト集を参考に、ZAPと静的解析を組み合わせた運用フローについても触れます。
OWASP ZAPとは
OWASP ZAP(Zed Attack Proxy)は、OWASP(Open Worldwide Application Security Project)が開発・公開しているWebアプリケーション向けの脆弱性診断ツールです。
主な特徴
| 項目 | 内容 |
|---|---|
| 料金 | 完全無料・オープンソース |
| 対象 | Webアプリケーション(HTTP/HTTPS) |
| 検出できる脆弱性 | SQLインジェクション、XSS、CSRF、ディレクトリトラバーサル、セキュリティヘッダー不備など |
| 実行方式 | GUI、CLI、Docker、API |
| CI連携 | GitHub Actions、Jenkins、GitLab CI等から実行可能 |
商用の診断ツール(Burp Suite Professional等)と比較すると検出精度では劣る部分もありますが、無料で使えることと自動化のしやすさから、開発チームが自前で回す一次診断としては十分に実用的です。
ZAPの3つのスキャンモード
| モード | 速度 | 検出範囲 | 用途 |
|---|---|---|---|
| Baseline Scan | 速い(数分) | パッシブスキャンのみ | CI/CDに組み込む日常的なチェック |
| Full Scan | 遅い(数十分〜数時間) | パッシブ+アクティブスキャン | リリース前の本格的な診断 |
| API Scan | 中程度 | API定義ベースのスキャン | REST API/GraphQLの診断 |
「Baseline Scan」は対象サイトを巡回してHTTPレスポンスを受動的に分析するだけなので高速です。一方「Full Scan」はリクエストパラメータを改変して能動的に脆弱性を探すため、時間はかかりますがより多くの問題を検出できます。
Dockerでの実行環境構築
ZAPをサーバ上で実行するには、Dockerを使うのが最も手軽です。GUIを立ち上げる必要がなく、スクリプト一つで診断を開始できます。
前提条件
- Dockerがインストールされていること
- 診断対象のWebアプリケーションにネットワーク的に到達できること
ZAP Dockerイメージの取得
docker pull ghcr.io/zaproxy/zaproxy:stable
最もシンプルな実行例(Baseline Scan)
docker run --rm \
ghcr.io/zaproxy/zaproxy:stable \
zap-baseline.py \
-t https://example.com \
-r report.html
これだけで、対象サイトに対するBaseline Scanが実行され、HTML形式のレポートが生成されます。
レポートをホスト側に出力する
デフォルトではレポートがコンテナ内に出力されるため、ホスト側にマウントして取り出します。
mkdir -p ./zap-reports
docker run --rm \
-v $(pwd)/zap-reports:/zap/wrk:rw \
ghcr.io/zaproxy/zaproxy:stable \
zap-baseline.py \
-t https://example.com \
-r report.html
./zap-reports/report.html にレポートが出力されます。
環境ごとにスクリプトが異なる問題
ここがZAP運用の最大の壁です。
実際のプロジェクトでは、スキャン設定は環境ごとに大きく異なります。
| 環境 | 違いの例 |
|---|---|
| 開発環境(localhost) | HTTPのみ、認証なし、全パスが対象 |
| ステージング環境 | HTTPS、Basic認証またはVPN経由、特定パスを除外 |
| 本番環境 | HTTPS、Cookie認証、管理画面は除外、スキャン速度を制限 |
| API(REST) | OpenAPI定義ファイルベースでスキャン |
| SPA(React等) | Ajax Spiderの有効化が必要 |
たとえば、Basic認証がかかったステージング環境をスキャンするなら、認証ヘッダーを追加する設定が必要です。SPAの場合は通常のクローラーではページ遷移を追えないため、Ajax Spiderを有効にする必要があります。
このように、「ZAPを動かすこと自体は簡単だが、自分の環境に合った設定を作るのが面倒」というのが、脆弱性診断のハードルを上げている原因です。
Claude Codeで環境に合ったスクリプトを生成する
ここでClaude Codeの出番です。
環境の情報を伝えるだけで、その環境に最適化されたZAPスキャンスクリプトを生成できます。
基本のプロンプト
以下の環境に対するOWASP ZAPスキャンスクリプト(Docker実行)を作成してください。
- 対象URL: https://staging.example.com
- 認証: Basic認証(ユーザー名: test, パスワードは環境変数 ZAP_AUTH_PASS から取得)
- スキャン種別: Full Scan
- 除外パス: /admin/*, /api/health
- レポート形式: HTML + JSON
- レポート出力先: ./zap-reports/
注意事項:
- Dockerで実行する構成にすること
- パスワードはスクリプト内にハードコードしない
- CI(GitHub Actions)から実行できるようシェルスクリプトとして作成すること
生成されるスクリプトの例
Claude Codeは、以下のような構成のスクリプトを生成します。
#!/bin/bash
set -euo pipefail
# 設定
TARGET_URL="https://staging.example.com"
REPORT_DIR="./zap-reports"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# 認証情報(環境変数から取得)
if [ -z "${ZAP_AUTH_PASS:-}" ]; then
echo "エラー: 環境変数 ZAP_AUTH_PASS が設定されていません"
exit 1
fi
# レポート出力ディレクトリの作成
mkdir -p "${REPORT_DIR}"
# ZAP設定ファイルの生成
cat > /tmp/zap-config.conf << 'CONF'
# 除外パスの設定
-config globalexcludeurl.url_list.url\(0\).regex='.*/admin/.*'
-config globalexcludeurl.url_list.url\(0\).enabled=true
-config globalexcludeurl.url_list.url\(1\).regex='.*/api/health'
-config globalexcludeurl.url_list.url\(1\).enabled=true
CONF
# ZAP Full Scan の実行
docker run --rm \
-v "${REPORT_DIR}:/zap/wrk:rw" \
-e ZAP_AUTH_HEADER="Authorization: Basic $(echo -n "test:${ZAP_AUTH_PASS}" | base64)" \
ghcr.io/zaproxy/zaproxy:stable \
zap-full-scan.py \
-t "${TARGET_URL}" \
-r "report_${TIMESTAMP}.html" \
-J "report_${TIMESTAMP}.json" \
-z "-config replacer.full_list\(0\).enabled=true \
-config replacer.full_list\(0\).matchtype=REQ_HEADER \
-config replacer.full_list\(0\).matchstr=Authorization \
-config replacer.full_list\(0\).replacement='Basic $(echo -n "test:${ZAP_AUTH_PASS}" | base64)'" \
|| true
# 結果の確認
echo "スキャン完了: ${REPORT_DIR}/report_${TIMESTAMP}.html"
SPA向けのプロンプト例
Reactなどのシングルページアプリケーションの場合は、Ajax Spiderの有効化が必要です。
以下のSPAに対するOWASP ZAPスキャンスクリプトを作成してください。
- 対象URL: http://localhost:3000
- フレームワーク: React(SPA)
- 認証: なし
- スキャン種別: Full Scan(Ajax Spider有効)
- レポート形式: HTML
- Docker実行
SPAなので通常のSpiderではページ遷移を追えません。
Ajax Spiderを有効にして、JavaScriptレンダリング後のDOMをクロールしてください。
API向けのプロンプト例
OpenAPI(Swagger)定義がある場合は、それをベースにしたスキャンが可能です。
以下のREST APIに対するOWASP ZAPスキャンスクリプトを作成してください。
- OpenAPI定義: ./openapi.yaml
- ベースURL: https://api.staging.example.com
- 認証: Bearer Token(環境変数 ZAP_API_TOKEN から取得)
- スキャン種別: API Scan
- レポート形式: JSON
- Docker実行
このように、環境の特徴をプロンプトとして記述するだけで、その環境に合ったスクリプトが生成されます。 ZAPのオプション体系を暗記する必要はありません。
セキュリティ監査用ルールと組み合わせる
ZAPは「外から見た脆弱性」を検出するツールですが、コードの内部構造に起因するセキュリティ問題(認証ロジックの不備、権限チェックの漏れ等)は検出できません。
ここで有効なのが、Claude Codeにセキュリティ監査ルールを読み込ませて、コードの静的解析を併用するアプローチです。
セキュリティ監査ルールの作り方
GitHubでは、Claude Code向けのセキュリティ監査プロンプト集を公開している方もいます。これらを参考に、自分のプロジェクトに合ったルールファイルを作成できます。
具体的には、.claude/rules/ ディレクトリにセキュリティ監査用のMarkdownファイルを配置します。
# セキュリティ監査ルール
## チェック項目
- SQLインジェクション: プレースホルダーを使わない生クエリがないか
- XSS: ユーザー入力をエスケープせずに出力していないか
- 認証バイパス: 認証チェックが漏れているエンドポイントがないか
- CSRF: フレームワークのCSRF保護が無効化されていないか
- 機密情報: APIキーやパスワードがハードコードされていないか
- 依存関係: 既知の脆弱性を持つパッケージを使っていないか
このルールファイルがあると、Claude Codeは通常のコーディング作業中にもセキュリティ観点を意識した提案を行います。
ZAP + 静的解析の組み合わせフロー
1. 開発中(日常的に)
└── Claude Codeがセキュリティ監査ルールに基づいてコードをチェック
2. PR作成時
└── CI上でZAP Baseline Scanを実行(HTTPヘッダー、基本的な脆弱性)
3. リリース前
└── ZAP Full Scanを実行(能動的な脆弱性検出)
└── Claude Codeでセキュリティ重点レビューを実施
外側と内側の両方からチェックすることで、単体では見つけられない問題をカバーできます。 ZAPが外部診断、静的解析が内部診断という位置づけです。
GitHub Actionsへの組み込み
定期的な診断を自動化するなら、CIに組み込むのが効果的です。ZAPの公式がGitHub Actions用のアクションを提供しています。
name: OWASP ZAP Scan
on:
schedule:
# 毎週月曜の朝9時(JST)に実行
- cron: '0 0 * * 1'
workflow_dispatch:
jobs:
zap-scan:
runs-on: ubuntu-latest
steps:
- name: ZAP Baseline Scan
uses: zaproxy/action-baseline@v0.14.0
with:
target: 'https://your-staging-site.com'
rules_file_name: 'zap-rules.tsv'
fail_action: true
- name: レポートをアーティファクトとして保存
uses: actions/upload-artifact@v4
if: always()
with:
name: zap-report
path: report_html.html
zap-rules.tsv で特定のルールを無視したり、失敗条件をカスタマイズできます。
まとめ
- OWASP ZAPはWebアプリケーションの脆弱性を自動検出するオープンソースツール。無料で使え、Docker上でスクリプト実行できる
- 環境ごとに異なるスキャン設定が必要だが、Claude Codeに環境情報を伝えるだけで適切なスクリプトを生成できる
- 脆弱性診断はハードルが高いと感じる方も多いが、Baseline Scanなら数分で完了する。まずはこれから始めてみてほしい
- ZAPとセキュリティ監査ルールを組み合わせることで、外部診断と内部診断の両面からより網羅的なセキュリティチェックが実現できる
- GitHubにはClaude Code向けのセキュリティプロンプト集を公開している方もいる。自分のプロジェクトに合った監査ルールを作り、ZAPと合わせて運用するとよい
セキュリティは「完璧にやらないと意味がない」ものではありません。今日Baseline Scanを1回実行するだけでも、昨日よりセキュリティレベルは上がります。 まずは自分のサイトに対して docker run してみてください。