GitHub Actions で OWASP ZAP が動くだと!?

本記事は [NECソリューションイノベータ　Advent Calendar 2021](https://qiita.com/advent-calendar/2021/nec_solution_innovators)の 12/12 の記事です。

# はじめに

最近、2008年製の開発PC（Windows 10, 4CPU, 16GBメモリ）がついに寿命を迎え、開発環境を MacBook（M1チップ） に移行することになったのですが、セキュリティテストで利用していた OWASP ZAP のコンテナイメージが M1 上で動作しなくて途方にくれていたら、GitHub Actions で動くようになっていたという情報を見つけたので、実際に試してみました。

## 注意

- OWASP ZAP が実施する脆弱性診断のための通信は、攻撃とみなされることがありますので、自分たちで管理していない外部サイトなどに対して使用しないよう十分にご注意ください。

# フロントエンドに Full Scan を実施する

### 1. GitHub リポジトリの作成＆設定

はじめに、GitHub のリポジトリを作成します。

- リポジトリ名：owaspzap-actions-website-scan
- 公開設定：Private

リポジトリを作成したら、以下の設定を行います。

- シークレット
    - リポジトリの `Settings` → `Secrets` を開き、 `New repository secret` をクリック
        - Name：`WEBSITE_URL`
        - Value：テスト対象のWebサイトURL

### 2. Workflow の作成

リポジトリを clone して、以下のファイルを作成します。

- ディレクトリ構成
  
    ```
    + .github
      └ workflow
        └ owaspzap.yml
    ```
    
- ファイルの記述
    - owaspzap.yml
      
        ```yaml
        name: OWASP ZAP Actions
        on: [push]
        jobs:
          website-scan:
            runs-on: ubuntu-latest
            name: DAST (Dynamic Application Security Testing)
            steps:
              - name: Checkout
                uses: actions/checkout@v2
                with:
                  ref: master
              - name: Action Full Scan
                uses: zaproxy/action-full-scan@v0.3.0
                with:
                  token: ${{ secrets.GITHUB_TOKEN }}
                  docker_name: owasp/zap2docker-stable
                  target: ${{ secrets.WEBSITE_URL }}
                  cmd_options: >
                    -a
                    -j
                    -z "
                    -config alert.maxInstances=0
                    -config view.locale=ja_JP
                    "
        ```
        
        - `target` に作成したシークレット名 `WEBSITE_URL` を指定します
        - `cmd_options` でセキュリティテストの動作設定を行います
            - `-a` α版の診断ルールを追加する
            - `-j` Ajax Spider を追加する
            - `-z`
                - 最大アラート件数の制限（既定値：20件）を無制限に緩和
                - `view.local=ja_JP` 診断レポートを日本語化

### 3. セキュリティテストを実行する

2 で作成した Workflow をリポジトリに push すると自動的に実行が開始されます。

### 4. 診断レポートの入手

Workflow の実行が完了すると診断レポートがリポジトリの Issue に登録されます。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104325/71772df6-73ce-d968-062b-e32eee707882.png)

Issue を開き、一番下までスクロールすると Workflow の実行結果に移動するリンクがあるのでクリックします。

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104325/b148cedd-cb0c-e056-787e-cb434d3428d8.png)

Workflow の実行結果のページを開くと、診断レポートが Artifats として登録されています。

Name 列（`zap_scan` ）をクリックすると診断レポートが zip 形式でダウンロード可能です。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104325/bbf559ee-77df-7fea-5434-723e7f660893.png)


### 課題

- `Threshold` や `Strength` をどこで指定するのか？
    - GitHub Actions 以前に、そもそもDocker版の `full-scan, api-scan`の話。 `webswing` の GUI 以外での指定方法がわからない
- `Ajax Spider` が動かない不具合があるそうです
    - [Issue #18](https://github.com/zaproxy/action-full-scan/issues/18)（→ [Issue #33](https://github.com/zaproxy/action-baseline/issues/33)）
- カスタムルールファイル（`-c` オプション）で IGNORE してもレポートに結果が含まれてしまう（GitHub Actions ではなく Docker 版の話）
    - [Issue #5019](https://github.com/zaproxy/zaproxy/issues/5019)


# バックエンドに API Scan を実施する

### 1. GitHub リポジトリの作成＆設定

はじめに、GitHub のリポジトリを作成します。

- リポジトリ名：owaspzap-actions-api-scan
- 公開設定：Private

リポジトリを作成したら、以下の設定を行います。

- シークレット
    - リポジトリの `Settings` → `Secrets` を開き、 `New repository secret` をクリック
        - Name：`ACCESS_TOKEN`
        - Value：テスト対象のシステムにログインして発行される Access Token

### 2. Workflow の作成

リポジトリを clone して、以下のファイルを作成します。

- ディレクトリ構成
  
    ```
    + .github
    | └ workflow
    |   └ owaspzap.yml
    |
    + openapi.yml
    ```
    
- ファイルの記述
    - owaspzap.yml
      
        ```yaml
        jobs:
          api-scan:
            runs-on: ubuntu-latest
            name: DAST (Dynamic Application Security Testing)
            env:
              ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
            steps:
              - name: Checkout
                uses: actions/checkout@v2
                with:
                  ref: master
              - name: Action API Scan
                uses: zaproxy/action-api-scan@v0.1.0
                with:
                  token: ${{ secrets.GITHUB_TOKEN }}
                  docker_name: 'owasp/zap2docker-stable'
                  format: openapi
                  target: openapi.yml
                  cmd_options: >
                    -a
                    -j
                    -z "
                    -config replacer.full_list\\(0\\).description=AccessToken
                    -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\\).regex=false
                    -config replacer.full_list\\(0\\).replacement=$ACCESS_TOKEN
                    -config alert.maxInstances=0
                    -config view.locale=ja_JP
                    "
        ```
        
        - `ACCESS_TOKEN` 環境変数にシークレットから取得した値を設定します
        - `target` にリポジトリに登録した OpenAPI ファイル（`openapi.yml`）を指定します
            - OpenAPI ファイルのパスはリポジトリのルート配下からの相対パスを指定します
        - `cmd_options` でセキュリティテストの動作設定を行います
            - `-a` α版の診断ルールを追加する
            - `-j` Ajax Spider を追加する
            - `-z`
                - `Authorization` ヘッダにアクセストークンを設定
                - 最大アラート件数の制限（既定値：20件）を無制限に緩和
                - `view.local=ja_JP` 診断レポートを日本語化
    
    - openapi.yml
    
      ```yaml
      公開できないため省略します。
      ※ 一般的なAPI定義で特殊なことはしておりません。
      ```
    
      - 接続先 URL が中にハードコードされたままなので、フロントエンドと同様に環境変数にしたかったけど、時間切れになっちゃいました…

### 3. セキュリティテストを実行する

※ フロントエンドと同様のため省略します。

### 4. 診断レポートの入手

※ フロントエンドと同様のため省略します。


### 課題

- API Scan では `API-Minimal.policy` が適用されているため、検知可能な脆弱性が非 Docker 版より少ない
    - [Issue #4354](https://github.com/zaproxy/zaproxy/issues/4354)
        - 回避策：Docker の `-v` オプションでポリシーファイルを上書くとか？
            - 今回利用している action-api-scan だとダメかも？


# GitHub Actions から実行したアクセス情報を確認してみた

実はテスト対象のアプリケーションは AWS 上に構築していました。

CloudFront の `ビューワー` より以下の情報がわかりました。

- デバイスは `デスクトップ`

- ブラウザは `Firefox`

- オペレーティングシステムは `Windows`

- ロケーションは `United States`

    ![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104325/11481711-be72-ce4f-3498-a795336c30bf.png)


# 検証結果よりわかったこと

- 以前から Docker 版ではありますが Web Swing の方を利用して細かいスキャンポリシーの定義などを行っていました。
    今回は Full Scan、API Scan を利用しましたが、この 2 つは独自の診断ポリシーの定義を行っているようで、診断結果を見ると、実施したルール数が少ないようでした。ちょっと調べた感じでは Web Swing を利用した時のように、詳細項目（Attack Threshold、Attack Strength、など）を設定して、すべてのルールを適用ということができなさそうでした。

  - 2021/11 時点で合計 159 のルールIDが定義されている（以下URL）ようですが、Full Scan、API Scan の結果ではこれより少ない

        [https://www.zaproxy.org/docs/alerts/](https://www.zaproxy.org/docs/alerts/)

- GitHub の Issues を見ると、まだまだ重要な問題が残っているようなので、本格利用はその辺りが解決してからかな。と思いました。


Web Swing でコンテキストファイルを作成して、それをインプットに動かしたら良さそうな…という書き込みもあったのですが、時間切れで未確認の状況です。次の機会があれば試してみたいと思います。
結局、コンテキストファイルを作るには、OWASP ZAP が動く環境を自前で準備しないといけないんだよな〜。AWS でやるか〜 (´；ω；｀)


# 参考

GitHub Marketplace

- [OWASP ZAP Full Scan](https://github.com/marketplace/actions/owasp-zap-full-scan)

- [OWASP ZAP API Scan](https://github.com/marketplace/actions/owasp-zap-api-scan)

ZAP2Docker

- [Full Scan](https://www.zaproxy.org/docs/docker/full-scan/)
- [API Scan](https://www.zaproxy.org/docs/docker/api-scan/)

以上。