CI/CDにOWASP Dependency Checkを組み込んでOSSの脆弱性をチェックしてみた

株式会社 日立ソリューションズ 倉又裕輔


はじめに

アプリケーション開発ではOSSライブラリを活用することが一般的ですが、時には取り込んだOSSの中に脆弱性が見つかることもあります。

開発の初期段階で脆弱性が見つかれば対応は比較的スムーズですが、いざリリースとなった段階で脆弱性が見つかった場合には、その対応のために大きな手戻りが発生することも少なくありません。

特にサービス開発ではリリーススピードが求められるため、その影響は深刻です。

日立ソリューションズでは、サービス開発基盤としてCI/CD (継続的インテグレーション/継続的デリバリー) 環境の整備を進めています。

上記のような脆弱性対策による手戻りを最小限に抑えるべく、脆弱性をいち早く検知し、対策を早期に実施することで、開発スピードを高める仕組みを検討しています。

そんな中で、OSSとして公開されている脆弱性チェックツール「OWASP Dependency Check」を試してみました。今回は、その一部をご紹介します。


OWASP Dependency Checkとは

簡単にいうと、アプリをスキャンして依存するライブラリを調べ、それらのライブラリに対して公開されている脆弱性情報の有無をチェックしてくれるツールです。

詳しい説明や使い方については、以下の記事など多数がWebで閲覧できますので、本記事では省略します。

CodeZine:組み込んだOSSコンポーネントの更新漏れを可視化する「OWASP Dependency Check」

Qiita:OWASP Dependency-Checkを使って依存ライブラリの脆弱性をスキャン


今回試した使い方

OWASP Dependency Checkはさまざまな言語に対応していますが、今回はJavaのみ試しました。

私たちの環境ではGitLabを利用しており、GitLab CI/CDを使って自動ビルド/テストを実施しています。

開発中にいち早く脆弱性に気づけるように、ビルドジョブの直後にOWASP Dependency Checkを組み込み、ビルドツールがOSSライブラリを自動取得した直後に脆弱性チェックを実行できるようにしました。

また、OWASP Dependency Checkは脆弱性チェック結果のレポートをHTML形式でファイル出力しますので、GitLabのPagesからレポート閲覧する構成にしました。

処理フローのイメージは下記です。VulcheckジョブでOWASP Dependency Checkを実行します。

image.png

また、Vulcheckジョブの具体的な処理内容 (.gitlab-ci.ymlの内容) は下記です。

Vulnerabilitycheck:

image: (OWASP Dependency CheckをインストールしたDockerイメージを指定)
stage: vulcheck
cache: # 脆弱性データベースをキャッシュ(※1)
key: "$CI_PROJECT_ID"
paths:
- ./data
script:
- mkdir -p ./data # 脆弱性データベースを格納するディレクトリ
- HOMEDIR=$(pwd)
- ln -s ${HOMEDIR}/data /usr/share/dependency-check/data # dependency checkの規定のDB保管場所にリンク
- /usr/share/dependency-check/bin/dependency-check.sh --scan ./ --project $CI_PROJECT_NAME -l log.txt # スキャン実行。--scanオプションには、ビルド済みのアプリが格納されたディレクトリを指定
- cp ./dependency-check-report.html ./index.html # pages用に脆弱性レポートの名前を変更
artifacts: # 次のステージに引き継ぐファイルの指定
paths:
- ./index.html # 脆弱性レポート
- ./log.txt # 実行ログ
expire_in: 1 day # 作成物の保存期間(有効期限)を指定

(※1) OWASP Dependency Checkは処理開始前にNVD (National Vulnerability Database:米国立標準技術研究所の脆弱性DB) の脆弱性データをダウンロードしますが、毎回全データをダウンロードするのは時間がかかります。そこで、一度ダウンロードしたデータをキャッシュしておき、次回以降は差分のみダウンロードするようにしました。


使ってみてわかったこと

OSSの脆弱性チェックは、手作業で実施する場合、大きく以下の3ステップに分けて実施するかと思います。


  1. アプリが依存するOSSライブラリの一覧化

  2. 一覧化したOSSに対して脆弱性の有無を調査

  3. 発見した脆弱性がアプリに及ぼす影響の調査

OWASP Dependency Checkは上記の作業を自動化しますが、今回試した結果、自動化の範囲について以下のことがわかりました。


1. 依存するOSSライブラリを一覧化してくれる

試した範囲では、依存するOSSを漏れなく自動でリストアップできました。

アプリの規模が大きくなると、人手で調べるのはほぼ無理なので、これは便利だと思います。


2. 脆弱性の有無のチェック機能は限定的

試した範囲では、脆弱性チェック機能はそれほど精度が良くない結果でした。

原因としては以下2点が考えられます。


◆ CPE (Common Platform Enumeration:共通プラットフォーム一覧) の推定の精度が低い

冒頭で紹介した記事でも述べられていますので省略します。


◆ NVDの登録情報 (CVE(Common Vulnerabilities and Exposures:共通脆弱性識別子)とCPEの関連付け)が不十分

OWASP Dependency Checkの脆弱性チェック機能の仕様上、NVDにCVEとCPEの関連が正しく登録されていることが前提となっています。

しかし、近年ではOSSの脆弱性の報告件数が年々増加しているため、おそらくNVDの登録情報の更新が遅れているものと思われます。

上記のように、残念ながら現状では、OWASP Dependency Checkは最新の脆弱性を検知する用途には向いていないと思います。

古くて脆弱性のあるOSSを検知する用途で利用するのがよさそうです。

また、脆弱性の検知漏れがあるため、出力されたレポートの内容を鵜呑みにせず、開発者自身で脆弱性の有無を精査する必要があります。


3. 脆弱性の影響調査に役立つ情報が得られる

発見した脆弱性に対しては、重大度や影響を受けるバージョンなど、対応するNVDの情報がレポートに記載されます。

CVEの詳細情報のページへのリンクも記載されており、より詳しい調査が必要な場合に便利です。

レポートのサンプルが以下で閲覧できますので、参考にしてください。

https://jeremylong.github.io/DependencyCheck/general/SampleReport.html

なお、OWASP Dependency CheckはJavaの脆弱性情報としてNVDのみを利用しているため、対象OSSの公式サイトや、メーリングリストなどに掲載されている脆弱性情報はレポートには含まれません。

これらについては、必要に応じて利用者自身で調査する必要があります。


最後に

CI/CDによるサービス開発では、OSSの脆弱性チェックを自動ビルドプロセスに組み込むことが生産性向上に有効です。

今回試したOWASP Dependency Checkはその一つの方法ですが、まだまだ実用上の課題があるようです。

今後も継続してより良いツール、手法を試していきたいと思います。

※ OWASP、OWASP Dependency Checkは、OWASP財団の登録商標または商標です。

※ Javaは、Oracle Corporation 及びその子会社、関連会社の米国及びその他の国における商標または登録商標です。

※ GitLabは、GitLab B.V.の米国およびその他の国における登録商標または商標です。

※ その他、記載の会社名、製品名は、それぞれの会社の商標もしくは登録商標です。