CI に特化した DAST ツール "Dastardly" を使ってみた

[LIFULL Advent Calendar 2022](https://qiita.com/advent-calendar/2022/lifull)の15日目の記事です。

LIFULL で SETとして自動テスト・CIを軸に Developer eXperience の革進に取り組んでいるキシノです。

自動テストというと機能テスト（E2E・Unitテストなど）を思い浮かべる方が多いと思いますが、私のチームでは非機能面における自動テスト（セキュリティテストなど）に関する改善も行っています。

近年セキュリティテストの改善の一環として [Burp Suite Enterprise](https://portswigger.net/burp/enterprise) を導入しました。
また、最近 Burp Suite Enterprise の開発元の PortSwigger から [Dastardly](https://portswigger.net/burp/dastardly) というツールが公開されましたので、概要やCIとして使用感などをまとめてみたいと思います。

ツールの機能性とは関係ないですが名前が個性的で面白いです。 （Dastardly ... 卑劣な）

# Dastardly とは

※ 現在（2022/12/14）の情報です。

- Free
- CI/CD パイプラインへの組み込み特化した DAST ツール
  - GitHub Actions や Jenkins に組み込む前提
      - [公式GitHub Actions](https://github.com/PortSwigger/dastardly-github-action) が提供されている
  - docker run で実行可能
  - 10分以内に終わる
- 自動スキャンのみに対応
  Target URL を指定し、その URL を始点として自動でクロールと検査を行う。
  特定のシナリオを踏まないとたどり着けないページなどはうまくスキャンできない可能性がある。
- レポートが JUnit 形式で出力
- スキャンの範囲や検査項目数が絞られている
    - 参考：https://portswigger.net/burp/dastardly/scan-checks
    - 大規模なサイトに対しては Burp Suite Enterprise や Professional などを使う必要がある

# CIに組み込んでみる

公式で提供されている[サンプル通り](https://github.com/PortSwigger/dastardly-github-action#basic-usage)に実装するだけで動きました :sunglasses:
[PR](https://github.com/nk-ty/dastardly-juice-shop/pull/2) / [Actionsの結果](https://github.com/nk-ty/dastardly-juice-shop/actions/runs/3693365004/jobs/6253268280)
8m 46sec で実行完了しました。
Actions のコンソールには以下のように脆弱性情報が表示されました。

```bash
2022-12-14 09:22:25 ERROR dastardly.ScanFinishedHandler - Failing build as scanner identified issue(s) with severity higher than "INFO":
2022-12-14 09:22:25 ERROR dastardly.ScanFinishedHandler - Path: /catalog/search/2 Issue Type: Cross-site scripting (reflected) Severity: HIGH
2022-12-14 09:22:25 ERROR dastardly.ScanFinishedHandler - Path: /catalog/search/3 Issue Type: Cross-site scripting (reflected) Severity: HIGH
2022-12-14 09:22:25 ERROR dastardly.ScanFinishedHandler - Path: /catalog/search/4 Issue Type: Cross-site scripting (reflected) Severity: HIGH
```

Step の終了ステータスは Fail 扱いとなります :x:

また、JUnit 形式のXMLを利用すると以下のようにサマリーと イシュー詳細が表示することが可能です。

[Actionsの結果](https://github.com/nk-ty/dastardly-juice-shop/actions/runs/3693601162
)
![image-20221214190919764.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10800/7c359221-6d78-22be-f9ee-3193a74ce75f.png)

さらに [JUnit Test Report ステップ](https://github.com/nk-ty/dastardly-juice-shop/actions/runs/3693601162/jobs/6253923477)を見ていくとリクエスト・レスポンス、脆弱性の参考情報なども確認できます :clap:
![Screen Shot 2022-12-22 at 17.23.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10800/8f080c15-766c-bd75-6bd1-2383f37da854.png)
![Screen Shot 2022-12-22 at 17.24.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10800/c976cbe6-7344-e02a-a678-cfada40f9e34.png)
![Screen Shot 2022-12-22 at 17.25.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10800/beadfb88-f28e-51cf-6451-37423641ab9e.png)



# Pros / Cons

## いい点

* 公式の Actions を使って CI に組み込むのはとても簡単
※ Target URL は Actions の実行環境から接続可能である必要があります
* 実行時間は CI として許容できる
実際にスキャン自体は 9 分弱で完了しました
* レポーティングも簡潔でわかりやすい
* 検知した内容の詳細も JUnit Report を吐き出せば確認できる

## 個人的にいまひとつな点

* 偽陽性としてマークができない
リスクなしと判断した場合にその検知結果を偽陽性扱いにすることがあります。
偽陽性としてマークできないと再び検知されることになり、再度リスク評価をしてしまう可能性が出てきます。

* PR ごとに解消するプロセスにするには障壁がある
Branch protect で Required することで テスト→確認→解消 のプロセスを仕組み化することが可能になります。
しかし、偽陽性の脆弱性が再検知された場合の無駄などがあると Required させることが難しいと感じました。


# Dastardly を使えそうなケース

開発フローには組み込まず、定点観測として用いるのならいいのではと思いました。

イメージとしては下記になります。
- ベースブランチなどにマージされたタイミングで実行
- 結果をデータストアへ保存する
- リポジトリごと（プロダクトごと）の保有している脆弱性数を可視化
- 脆弱性の増加状況によってメインの開発とは別に脆弱性対策を行うかを判断する
- 脆弱性対策を実行（別ツールで診断、リスク評価、脆弱性解消）

シフトレフトではありませんが、セッティングの容易さや得られる情報からこのような使い方なら一定の効果が得られそうです。

個人的には PR ごとに実行・解消の夢を追いたいので、機能改善に期待します！