この記事はディップ株式会社 Advent Calendar 2022の投稿です!
はじめに
Basic認証のかかったテストサイトにOWASP ZAPで脆弱性診断を試す機会があったので、Docker版とGitHub Actionsで自動化を試してみました。
注意
OWASP ZAPが実施する脆弱性診断のための通信は攻撃とみなされることがありますので、許可なくWebサイトやアプリケーションを「テスト」することは違法です。テストする許可を明確に与えられたターゲットでのみ使用する必要があることに注意してください。
環境
MacBook Pro M2
Basic認証突破
今回はターゲットサイトのURLパターンやBasic認証情報などを登録できるコンテキストファイルを使用します。
デスクトップ版ZAPでコンテキストファイルを作成しDocker版で流用します。
確認手順
・Spiderでターゲットサイトのスキャンを実行
・ステータスコード401のレスポンスヘッダーの「realm」値をメモ
WWW-Authenticate: Basic realm="ここの値"
・コンテキストを作成しターゲットサイトの追加とBasic認証情報を登録
GUI上のコンテキスト名をダブルクリック(またはメニュー:File>Session Properties)しSession Propertiesを開き以下の内容を設定
■ Authentication
Authentication method: HTTP/NTLM Authentication
Hostname: ターゲットサイトのドメイン名
Port: 443 (httpの場合は80)
Realm: メモしたrealm値
■ Users
Addで新規登録
User Name: sample-user (任意)
Username: Basic認証の値
Password: Basic認証の値
・上記で作成したコンテキスト名とUserを指定して再度Spiderでスキャンを実行
これでBasic認証を突破することができました。
上記作成したコンテキストをGUI操作でローカルにエクスポートしておきます。
(ここでは sample-context.context としてエクスポート)
参考
Docker版でBaseline Scanの実施
Baseline ScanはSpiderをデフォルトで1分間行うパッシブスキャンです。
エクスポートしたコンテキストファイル(上記sample-context.context)を置いてあるディレクトリで以下のように実行します。
docker run --rm -p 8081:8080 \
-v $(pwd):/zap/wrk:rw \
-t owasp/zap2docker-stable zap-baseline.py \
-t ターゲットサイトURL \
-n sample-context.context \
-U sample-user \
-a \
-m 10 \
-T 20 \
-J report_baseline.json \
-d \
-z "-addonupdate" \
-z "-addonuninstall hud" \
-z "-newsession /zap/wrk/sessions/"
- ZAPコンテナ内でヘルスチェックをデフォルト8080で行っているので適宜設定
- -U: コンテキストに登録した任意のUser Name(ここでは上記で作成したUser)
- -a: アルファ版のパッシブルールを含む
- -m: Spider実行時間(分)。デフォルト1分
- -T: 最大パッシブスキャン実行時間(分)
- -J: 結果レポートをjsonで出力
- -d: debugメッセージを表示
- -z: zap コマンドライン options
-addonuninstall hud: 不要なので外しておく
-newsession: セッション情報を作成する。実施結果を再確認するのに有効
参考
GitHub ActionsでBaseline Scanの実施
公式サイトでもGitHub Actionsでの自動化について紹介されています。
また、こちらのサイトをとても参考にさせていただきました。
無料枠が気になったりジョブを独自に制御したい場合は、クラウド環境などにセルフホステッドランナーを用意することができます。
.
├── .github
│ └── workflows
│ └── baseline_scan.yml
├── output
│ ├── reports
│ └── sessions
└── zap
├── context
│ └── sample-context.context
└── rules
└── rules.tsv
name: OWASP ZAP Actions
on:
schedule:
runs every day At 01:00.
- cron: '0 1 * * *'
jobs:
zap_baseline_scan:
timeout-minutes: 60
runs-on: ubuntu-latest
name: Scan the webapplication
steps:
- name: Get Current datetime
env:
TZ: 'Asia/Tokyo'
run: |
echo "CURRENT_DATETIME=$(date +'%Y%m%d%H%M%S')" >> $GITHUB_ENV
- name: OUTPUT Payload
run: cat $GITHUB_EVENT_PATH
- name: Checkout
uses: actions/checkout@v2
with:
ref: master
- name: ZAP Basicline Scan
timeout-minutes: 40
uses: zaproxy/action-baseline@v0.7.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
docker_name: 'owasp/zap2docker-stable'
target: ${{ secrets.TARGET_URL }}
rules_file_name: 'zap/rules/rules.tsv'
# cmd_options refs https://www.zaproxy.org/docs/docker/baseline-scan/
cmd_options: '
-n zap/context/sample-context.context
-U sample-user
-m 10
-T 20
-J output/reports/baseline_${{ env.CURRENT_DATETIME}}.json
-d
-a
-z "-addonupdate"
-z "-addonuninstall hud"
-z "-newsession output/sessions/"
'
スキャンターゲットURLはリポジトリのSecretsに事前に登録しておきます。
Baseline Scanの結果はGitHubリポジトリのissueに登録されます。
出力したjsonの結果レポートやsessions情報は、S3などにアップロードすれば良さそうです。
また以下のようなルールファイルを用意すればcssファイルをスキャン対象外にできます。
* OUTOFSCOPE .*\.css
Slack通知
Baseline Scan 完了時にSlackへ通知へしたいところ。
以下のようにSlack通知用アクションを利用すれば容易に実現できそうです。
notify_succed:
if: ${{ success()}}
timeout-minutes: 10
runs-on: ubuntu-latest
name: Notify on success
needs: zap_baseline_scan
steps:
- name: Notify to Slack channel
uses: rtCamp/action-slack-notify@v2
env:
SLACK_COLOR: ${{ job.status }} # or a specific color like 'good' or '#ff00ff'
SLACK_ICON: https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png
SLACK_MESSAGE: 'Run number : #${{ github.run_number }}'
SLACK_TITLE: Workflow Success
SLACK_USERNAME: GitHub Actions
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
notify_failure:
if: ${{ failure()}}
timeout-minutes: 10
runs-on: ubuntu-latest
name: Notify on failure
needs: zap_baseline_scan
steps:
- name: Notify to Slack channel
uses: rtCamp/action-slack-notify@v2
env:
SLACK_COLOR: ${{ job.status }} # or a specific color like 'good' or '#ff00ff'
SLACK_ICON: https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png
SLACK_MESSAGE: 'Run number : #${{ github.run_number }}'
SLACK_TITLE: Workflow Failure
SLACK_USERNAME: GitHub Actions
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
参考
おわりに
OWASP ZAPは自動化するための方法がいくつか提供されているのでCICDで定期的に脆弱性診断を実施することができそうですね。
今回は攻撃を行わないフロントエンド寄りのスキャンであるBaseline Scanを行いましたが、SQL InjectionなどAPI側の脆弱性診断にはFull ScanやAPI Scanになります。
しかしこれらのScanは実際に攻撃を含むスキャンを実施するので注意が必要です。
参考