背景とWebアプリケーションの脆弱性スキャンが必要な理由
今日のデジタル世界において、Webアプリケーションはあらゆるビジネスの心臓部です。販売サイトから社内管理システム、サービスプラットフォームに至るまで、私たちはこれらに依存しています。しかし、その利便性には、懸念すべきセキュリティリスクが伴います。私自身、サーバーが継続的なSSHブルートフォース攻撃を受け、一晩中眠れなかった経験があります。真夜中に緊急対応を迫られ、セキュリティは「待つもの」ではないと痛感しました。プロジェクトの初期段階から継続的に設定し、検査する必要があるのです。
Webアプリケーションが「本番稼働」(production)した後で脆弱性を見つけて修正することは、「大海の一滴を探す」ようなものだと理解しています。しかし、これを怠れば、顧客データの漏洩、ブランドの信頼性低下、さらにはシステム全体のダウンといった深刻な結果を招く可能性があります。
それが、私が自動脆弱性スキャンツールの探索を始めた理由です。6ヶ月以上にわたり、複数の実際のプロジェクトでOWASP ZAPを使用した結果、これが非常に強力で柔軟性があり、そして最も重要なことに無料かつオープンソースのソリューションであると実感しました。
OWASP ZAP (Zed Attack Proxy)は単なる脆弱性スキャンツールではありません。ブラウザとWebアプリケーション間のすべての通信を傍受する中間プロキシとしても機能します。これにより、脆弱性を自動的に検出するだけでなく、能動的に分析し、深く検査することができます。ZAPは、Webアプリケーションセキュリティ分野でトップクラスの信頼を誇る非営利組織OWASP (Open Web Application Security Project)コミュニティによって開発・維持されています。
OWASP ZAPのインストール
OWASP ZAPは多くのプラットフォームに対応しており、様々なインストール方法があります。個人開発の場合、直接インストーラーをダウンロードして使用できます。しかし、私はDockerを推奨します。なぜなら、CI/CDへの統合や依存関係の管理が格段に便利になるからです。
Dockerによるインストール(推奨)
Dockerがインストールされていれば、ZAPの起動はたった1つのコマンドで完了します。
docker pull owasp/zap2docker-stable
docker run -p 8080:8080 -p 8090:8090 -i owasp/zap2docker-stable zap.sh -daemon -port 8080 -host 0.0.0.0 -config api.disablekey=true
-p 8080:8080 -p 8090:8090: ZAPのAPIポート(8080)とUIポート(8090)をホストにマッピングします。-daemon: ZAPをデーモンモード(グラフィカルインターフェースなし)で実行し、CI/CDに最適です。-config api.disablekey=true: APIキーの要求を無効にします。ローカルテスト環境で便利です。本番環境では、セキュリティを強化するためにAPIキーを設定すべきです。
コマンド実行後、グラフィカルインターフェース版を使用したい場合は、ブラウザでhttp://localhost:8090からZAPのインターフェースにアクセスできます。CI/CD環境では、APIまたはCLIを通じてZAPと対話します。
オペレーティングシステムへのインストール
Windows、macOS、またはLinux向けに、OWASP ZAPの公式サイトから直接インストーラーをダウンロードすることも可能です。この方法は簡単で、完全なユーザーインターフェースでZAPを使用したい場合に適しています。
Ubuntu/Debianの場合:
sudo apt update
sudo apt install snapd
sudo snap install zaproxy --classic
インストール後、アプリケーションメニューからZAPを起動できます。
効果的なスキャンのための詳細設定
ZAPを効果的に機能させるには、適切な設定が非常に重要です。これによりZAPは単なる「形式的なスキャン」ではなく、実際に問題を発見するための鍵となります。
1. ZAPをプロキシとして設定する
ZAPはMan-in-the-Middle Proxyとして機能します。ブラウザとWebアプリケーション間のすべてのHTTP/SトラフィックはZAPを経由して転送され、これによりZAPはすべてのリクエスト/レスポンスを記録・分析できるようになります。
ZAP内で、Tools > Options > Local Proxiesに移動してプロキシポート(デフォルトは8080)を確認します。その後、ブラウザ(Firefox、Chrome)を設定してこのプロキシを使用します。私はプロキシの切り替えを容易にするため、FoxyProxy拡張機能を備えたFirefoxをよく使用します。
Firefoxの場合:
Settings > Network Settings > Manual proxy configurationに移動します。HTTP Proxyをlocalhostに、Portを8080に設定します。Also use this proxy for HTTPSにチェックを入れます。
SSL証明書エラーが発生した場合は、ZAPのRoot CA証明書をブラウザにインポートする必要があります。ZAP内でTools > Options > Dynamic SSL Certificatesに移動し、Saveをクリックして証明書を保存し、その後ブラウザにインポートしてください。
2. コンテキストの初期化と認証 (Authentication)
これはログインを必要とするアプリケーションにとって非常に重要なステップです。ZAPが認証を必要とする機能を深くスキャンするためには、ログイン方法を知っている必要があります。
-
コンテキストの作成: ZAP UIの
Sitesタブで、スキャンしたいサイト(例:http://your-webapp.com)を右クリックし、Include in Context > New Contextを選択します。コンテキストに名前を付けます(例:MyWebApp)。 -
認証の設定:
Contextsセクション(左側のウィンドウ)で、作成したコンテキストを選択し、次にAuthenticationタブを選択します。- フォームベース認証: 最も一般的なタイプです。ログインページのURL、ユーザー名/パスワードのパラメータ(例:
usernameField=user&passwordField=pass)、そしてZAPがログインの成功/失敗を認識するためのテキスト文字列(例: 成功の場合はLog out、失敗の場合はInvalid credentials)を提供する必要があります。 - HTTP/NTLM認証: アプリケーションがこのタイプを使用している場合、よりシンプルです。
- フォームベース認証: 最も一般的なタイプです。ログインページのURL、ユーザー名/パスワードのパラメータ(例:
-
ユーザーの作成: そのコンテキストの
Usersタブで、Addをクリックして、設定済みのログイン情報(ユーザー名/パスワード)を持つユーザーを作成します。ZAPはこのユーザーを使用して、認証されたスキャンセッションを実行します。
これにより、ZAPはログイン後にのみアクセス可能なページを効率的にスキャンし、バックエンド機能におけるBroken Access Control、SQL Injectionなどの脆弱性を発見するのに役立ちます。
3. スパイダリング(アプリケーション構造の探索)
アクティブスキャンを実行する前に、ZAPはアプリケーションの構造を把握する必要があります。主なスパイダーは2種類あります。
-
Traditional Spider: HTML、JavaScript内のリンクを探索します。実行するには、コンテキストまたはサイトを右クリックし、
Attack > Spider...を選択します。 -
AJAX Spider: 動的コンテンツの読み込みに多くのJavaScriptを使用する最新のWebアプリケーションにとって非常に重要です。AJAX Spiderはヘッドレスブラウザを開き、ユーザーのインタラクションをシミュレートして動的に生成されたリンクやAPIエンドポイントを探索します。実行するには、コンテキストまたはサイトを右クリックし、
Attack > AJAX Spider...を選択します。
私はZAPが最大限のパスと機能を探索できるように、常に両方のタイプのスパイダーを組み合わせて使用しています。
4. Active Scanポリシーの設定
Active Scanは、ZAPが特別に設計された(通常は「悪意のある」)リクエストをアプリケーションに送信して脆弱性を発見するプロセスです。スキャンプロセスをより効率的にするために、ポリシーをカスタマイズできます。
Tools > Options > Active Scan Policyに移動します。ここで、新しいポリシーを作成したり、特定のルールを有効/無効にしたり、警告しきい値(Alert Threshold)や攻撃強度(Attack Strength)を調整したりできます。例えば、サーバーへの過負荷を避けたい場合は、Attack StrengthをLowまたはMediumに下げます。逆に、より深くスキャンしたい場合は、HighまたはInsaneを選択します。
機密性の高いシステムをスキャンする際、本番環境で不適切または有害な可能性のあるルール(例: DoS関連のルール)を除外することは特に重要です。
検査と監視: 手動からCI/CD自動化まで
インストールと設定が完了したら、ZAPがその真価を発揮する時です。
1. 手動スキャン(初期探索)
初回スキャンや新機能を探索したい場合、私は通常、手動で実行します。
- ZAP UIを開きます。
- ブラウザをZAPプロキシを使用するように設定します。
- アプリケーションのすべての機能を手動で操作します: ログイン、データの追加/編集/削除、フォーム送信、ユーザーインターフェースを介したAPIとのインタラクション。このとき、ZAPはすべてのリクエスト/レスポンスを
Historyタブに自動的に記録し、Passive Scan(新しいリクエストを送信せずに分析)を実行して基本的な問題を発見します。 - ブラウジング後、作成したコンテキストに対してAJAX SpiderとTraditional Spiderを実行します。
- 最後に、コンテキスト全体、またはより深く検査したいサイトの特定のブランチに対してActive Scanを実行します。
結果はAlertsタブにHigh、Medium、Low、Informationalの各レベルで表示されます。そこから、各警告を深く掘り下げてリクエスト/レスポンスの詳細を確認し、修正方法を見つけることができます。
2. CI/CDによる自動化
ここでZAPは私の開発プロセスにおける重要な要素となります。CI/CDにZAPを統合することで、脆弱性を早期に自動検出でき、時間とコストを大幅に節約できます。IBMの調査によると、開発の早い段階でセキュリティ上の欠陥を発見・修正することは、本番環境で修正するよりも最大100倍のコスト削減につながる可能性があります。
ZAPは強力なAutomation Frameworkを提供し、YAMLファイルでスキャン手順を定義できます。あるいは、よりシンプルにDockerを介してZAP Baseline ScanまたはFull Scanを使用することもできます。
ZAP Baseline Scan(高速、日次CI/CDに適している)
Baseline Scanは、既知のURLに対して一定期間(例: 1分間)Passive Scanのみを実行します。非常に高速で、あらゆるコミット/プルリクエストで実行して基本的な、容易に識別できる問題を発見するのに適しています。
docker run --rm -v $(pwd):/zap/wrk/:rw owasp/zap2docker-stable zap-baseline.py -t http://your-webapp.com -g gen_report.html -r zap_baseline_report.xml
--rm: 実行後にコンテナを削除します。-v $(pwd):/zap/wrk/:rw: レポートを保存するために、現在のディレクトリをコンテナ内にマウントします。-t http://your-webapp.com: WebアプリケーションのターゲットURLです。-g gen_report.html: HTML形式のレポートを作成します。-r zap_baseline_report.xml: XML形式のレポートを作成します(CI/CDツールで解析しやすい)。
ZAP Full Scan(より徹底的、ナイトリービルド/リリースに適している)
Full Scanでは、Passive Scan、Traditional Spider、AJAX Spider、およびActive Scanを実行します。このプロセスはより多くの時間を要しますが、より多くの脆弱性を発見できます。
docker run --rm -v $(pwd):/zap/wrk/:rw owasp/zap2docker-stable zap-full-scan.py -t http://your-webapp.com -g gen_report.html -r zap_full_report.xml -D 10
-D 10: AJAX Spiderが探索を完了するまで10分間待ちます。
結果の処理とビルドの失敗
私はZAPがHighまたはMediumレベルの脆弱性を発見した場合、CI/CDジョブが失敗するように常に設定しています。これにより、深刻なセキュリティ上の欠陥を含むコードが本番環境にデプロイされるのを防ぎます。実際の例として、多くの企業はStaging/Production環境へのデプロイ前に、High/Mediumの脆弱性がゼロであることを要求しています。
ZAPのXMLまたはJSONレポートファイル内で、警告の数と深刻度を解析して確認できます。例えば、Pythonの場合:
import json
def check_zap_alerts(report_path):
with open(report_path, 'r') as f:
report = json.load(f) # 仮にJSONレポートを作成したとします
high_alerts = 0
medium_alerts = 0
for site in report.get('site', []):
for alert in site.get('alerts', []):
if alert['riskdesc'] == 'High':
high_alerts += 1
elif alert['riskdesc'] == 'Medium':
medium_alerts += 1
if high_alerts > 0:
print(f"[ERROR] {high_alerts}件のHighリスク警告が見つかりました。")
return False
if medium_alerts > 0:
print(f"[WARNING] {medium_alerts}件のMediumリスク警告が見つかりました。")
# ポリシーによっては、ここでビルドを失敗させることができます
return False # Mediumレベルのエラーがあればビルド失敗
print("HighまたはMediumリスクの警告は見つかりませんでした。よくできました!")
return True
# 使用方法:
# if not check_zap_alerts('zap_report.json'):
# exit(1) # CI/CDビルドを失敗させる
これは単なる簡単な例です。実際には、ZAPからのレポートを解析・処理するために、専用のライブラリやCI/CDに組み込まれたツールを使用できます。
継続的な監視
CI/CDに加えて、私は重要な本番アプリケーションに対して、毎週または毎月定期的なスケジュールスキャンを設定しています。これらのスキャンからのレポートは、メールで送信されるか、集中型脆弱性管理システムに統合されます。これにより、アプリケーションのセキュリティ「健全性」を継続的に監視し、新たな問題をタイムリーに発見することができます。
要約すると、OWASP ZAPはWebアプリケーションセキュリティに関心のあるITエンジニアにとって重要なツールです。脆弱性の手動探索からCI/CDへの自動統合まで、ZAPは驚くほどの柔軟性とパワーを提供します。今日からZAPを使い始めて、アプリケーションをより良く保護しましょう!

