まったり技術ブログ

主にWebエンジニア向けのセキュリティブログ。たまに開発も

【Webセキュリティ】依存ライブラリのセキュリティチェックツールを使ってみる

f:id:motikan2010:20200129012730p:plain

はじめに

 まず「依存ライブラリのセキュリティチェックツール」とは?ということですが、このようなツールの呼び方が定まっていないため本記事ではこのような呼び方にしています。
これらのツールの特徴として、動作しているアプリケーションが依存しているライブラリやパッケージに既知の脆弱性が存在していないかをバージョン情報などをもとに検査します。脆弱性があるバージョンのライブラリがあるとアラートを出す挙動をします。

 従来から利用されている Burp Suite や OWASP ZAP などのWebセキュリティ診断ツールは実際にアプリケーションを動作させて、その挙動から脆弱性を検出します。それに対して「依存ライブラリのセキュリティチェックツール」はアプリケーションを動作させずに検査します。ツールの動作が全く異なるので、検査内容も大きく違います。

 どちらかといったらWordPressの検査に利用される WPScan に検査内容は近いです。どちらも利用しているプラグイン(ライブラリ)のバージョン情報で検出するのがメインとなっているからです。
それでも検査を実施できる範囲は異なります。
 WPScan はネット越しに公開されているサイト全てに検査することが可能です。対して「依存ライブラリのセキュリティチェックツール」はアプリケーションが依存しているライブラリが記述されているファイル(Gemfile.lock や composer.lock)が検査対象になりますので、それらのファイルを閲覧できる権限者のみが検査を実施できます。それらのファイルに依存関係はほぼ全て記述されているので、依存関係を全て取得するのが難しいネット越しでの検査に比べてより厳密な検査ができます。

 そして近頃、Webアプリケーションなどのソフトウェアに依存しているライブラリに既知の脆弱性が潜んでいないかを検査するために、セキュリティチェックツールを提供・利用するサービスが増えてきている気がしています。

▼ Snyk もセキュリティチェックツールを開発/提供している企業であり資金調達が上手くいっている模様。 jp.techcrunch.com

 まずは、手軽に導入することができるOSSのセキュリティチェックツールを使用してみて、どのような検査結果を得ることができるのかなどを確認してみます。
ついでに検出された脆弱性の情報はどこから取得しているのかなども確認してきます。

言語別 ツール一覧

 昨今では様々な言語に対応したセキュリティツールが存在しています。
本記事では「PHP」「Ruby」「Python」「Java」「JavaScript」の5つの言語に対応したツールを各言語一つづつ紹介していきます。

 今回紹介するツールはどれもOSSなのでセキュリティ関連のツールに興味のある人はコードを読んでみても良いかと。

PHP

 まず初めにPHPのセキュリティチェックツールを使ってみます。

有名なものに security-checker がありますので、これを紹介します。

sensiolabs / security-checker

 検査時にcomposer.lockファイルを指定することから、composer.lockに記述されたPHPの依存ライブラリのバージョン情報から脆弱性を検出していることが分かります。

github.com

f:id:motikan2010:20200128223937p:plain

使い方

 検査用のスクリプトを取得したら、1つのコマンドでセキュリティの検査が可能です。

# security-checker のスクリプトを取得
$ wget https://get.sensiolabs.org/security-checker.phar

# 検査の開始
$ php security-checker.phar security:check composer.lock
Symfony Security Check Report
=============================

2 packages have known vulnerabilities.

symfony/http-foundation (v3.4.32)
---------------------------------

 * [CVE-2019-18888][]: Prevent argument injection in a MimeTypeGuesser

symfony/http-kernel (v3.4.32)
-----------------------------

 * [CVE-2019-18887][]: Use constant time comparison in UriSigner

[CVE-2019-18888]: https://symfony.com/cve-2019-18888
[CVE-2019-18887]: https://symfony.com/cve-2019-18887

Note that this checker can only detect vulnerabilities that are referenced in the SensioLabs security advisories database.
Execute this command regularly to check the newly discovered vulnerabilities.

 検査の結果、「CVE-2019-18888」と「CVE-2019-18887」の脆弱性が「symfony/http-foundation」と「symfony/http-kernel」から検出されました。

脆弱性データベース

github.com

 プルリクベースで新しい脆弱性の追加などの更新が行われており、今後も引き続き更新は行われていきそうです。

他の言語のセキュリティチェックツールも同様に、ほとんどの脆弱性データベースは様々に人によって頻繁に更新されています。

Web版

 Web版も用意されており、インストールなども必要なく利用することができます。

検査対象となるcomposer.lockファイルをアップロードすることで検査が可能です。

security.symfony.com

▼ 検査結果
f:id:motikan2010:20200128224042p:plain:w400

Ruby

rubysec / bundler-audit

github.com

f:id:motikan2010:20200128224105p:plain

使い方

 試しに適当にRailsプロジェクトを作成し、そのプロジェクトに対して検査を実施していきます。

# bundler-audit をインストール
$ gem install bundler-audit

# 検査対象のディレクトリに移動
$ cd ~/RubymineProjects/railsTestApp/

# 検査を実施
$ bundle-audit
bundle-audit
Name: actionview
Version: 5.1.6
Advisory: CVE-2019-5419
Criticality: Unknown
URL: https://groups.google.com/forum/#!topic/rubyonrails-security/GN7w9fFAQeI
Title: Denial of Service Vulnerability in Action View
Solution: upgrade to >= 6.0.0.beta3, >= 5.2.2.1, ~> 5.2.2, >= 5.1.6.2, ~> 5.1.6, >= 5.0.7.2, ~> 5.0.7, >= 4.2.11.1, ~> 4.2.11

Name: actionview
Version: 5.1.6
Advisory: CVE-2019-5418
Criticality: Unknown
URL: https://groups.google.com/forum/#!topic/rubyonrails-security/pFRKI96Sm8Q
Title: File Content Disclosure in Action View
Solution: upgrade to >= 4.2.11.1, ~> 4.2.11, >= 5.0.7.2, ~> 5.0.7, >= 5.1.6.2, ~> 5.1.6, >= 5.2.2.1, ~> 5.2.2, >= 6.0.0.beta3

 検出した脆弱性は17個あり列挙するとこんな感じです。

CVE-2019-5419    CVE-2019-5418  CVE-2018-16476  CVE-2019-5421  CVE-2019-16109
CVE-2019-15587  CVE-2018-16468  CVE-2019-5477  CVE-2019-11068  CVE-2018-14404
CVE-2019-13117  CVE-2015-9284  CVE-2019-16770  CVE-2018-16470  CVE-2019-16782
CVE-2019-16892  CVE-2018-1000544

 昨年発見された rack(CVE-2019-16782)の脆弱性も検出されており、検出に用いられる脆弱性データベースも更新されていることが分かります。

 次は脆弱性データベースを見てみることにします。

脆弱性データベース - rubysec / ruby-advisory-db

 検出のために用いられている脆弱性データベースは 「rubysec / ruby-advisory-db」リポジトリにあります。
github.com

Python

pyupio / safety

github.com

f:id:motikan2010:20200128224129p:plain

脆弱性データベース
使い方
# 脆弱性データベースを取得
$ pip install safety-db

# safetyのインストール
$ pip install safety

# 依存ライブラリの確認。古いDjangoがあります。
$ cat requirements.txt
Django==1.7.5

# 検査の開始
$ safety check -r requirements.txt
╒══════════════════════════════════════════════════════════════════════════════╕
│                                                                              │
│                               /$$$$$$            /$$                         │
│                              /$$__  $$          | $$                         │
│           /$$$$$$$  /$$$$$$ | $$  \__//$$$$$$  /$$$$$$   /$$   /$$           │
│          /$$_____/ |____  $$| $$$$   /$$__  $$|_  $$_/  | $$  | $$           │
│         |  $$$$$$   /$$$$$$$| $$_/  | $$$$$$$$  | $$    | $$  | $$           │
│          \____  $$ /$$__  $$| $$    | $$_____/  | $$ /$$| $$  | $$           │
│          /$$$$$$$/|  $$$$$$$| $$    |  $$$$$$$  |  $$$$/|  $$$$$$$           │
│         |_______/  \_______/|__/     \_______/   \___/   \____  $$           │
│                                                          /$$  | $$           │
│                                                         |  $$$$$$/           │
│  by pyup.io                                              \______/            │
│                                                                              │
╞══════════════════════════════════════════════════════════════════════════════╡
│ REPORT                                                                       │
│ checked 5 packages, using default DB                                         │
╞════════════════════════════╤═══════════╤══════════════════════════╤══════════╡
│ package                    │ installed │ affected                 │ ID       │
╞════════════════════════════╧═══════════╧══════════════════════════╧══════════╡
│ django                     │ 1.7.5     │ <1.7.11                  │ 25714    │
│ django                     │ 1.7.5     │ <1.7.6                   │ 25715    │
│ django                     │ 1.7.5     │ <1.8.10                  │ 33074    │
│ django                     │ 1.7.5     │ <1.8.10                  │ 33073    │
│ django                     │ 1.7.5     │ <1.8.15                  │ 25718    │
│ django                     │ 1.7.5     │ >=1.7,<1.7.10            │ 25728    │
│ django                     │ 1.7.5     │ >=1.7,<1.7.10            │ 25727    │
│ django                     │ 1.7.5     │ >=1.7,<1.7.7             │ 25731    │
│ django                     │ 1.7.5     │ >=1.7,<1.7.7             │ 25713    │
│ django                     │ 1.7.5     │ >=1.7,<1.7.9             │ 25725    │
│ django                     │ 1.7.5     │ >=1.7,<1.7.9             │ 25726    │
╘══════════════════════════════════════════════════════════════════════════════╛

 いくつかの脆弱性が検出されました。しかし脆弱性の詳細情報は出力されていない状態です。
--full-reportオプションを付与することで、脆弱性の詳細情報を出力することができます。

詳細情報レポートの取得。 --full-report オプション

 --full-reportオプションを付与することで、検出した脆弱性の詳細を表示することが可能です。

$ safety check -r requirements.txt --full-report
╒══════════════════════════════════════════════════════════════════════════════╕
│                                                                              │
│                               /$$$$$$            /$$                         │
│                              /$$__  $$          | $$                         │
│           /$$$$$$$  /$$$$$$ | $$  \__//$$$$$$  /$$$$$$   /$$   /$$           │
│          /$$_____/ |____  $$| $$$$   /$$__  $$|_  $$_/  | $$  | $$           │
│         |  $$$$$$   /$$$$$$$| $$_/  | $$$$$$$$  | $$    | $$  | $$           │
│          \____  $$ /$$__  $$| $$    | $$_____/  | $$ /$$| $$  | $$           │
│          /$$$$$$$/|  $$$$$$$| $$    |  $$$$$$$  |  $$$$/|  $$$$$$$           │
│         |_______/  \_______/|__/     \_______/   \___/   \____  $$           │
│                                                          /$$  | $$           │
│                                                         |  $$$$$$/           │
│  by pyup.io                                              \______/            │
│                                                                              │
╞══════════════════════════════════════════════════════════════════════════════╡
│ REPORT                                                                       │
│ checked 5 packages, using default DB                                         │
╞════════════════════════════╤═══════════╤══════════════════════════╤══════════╡
│ package                    │ installed │ affected                 │ ID       │
╞════════════════════════════╧═══════════╧══════════════════════════╧══════════╡
│ django                     │ 1.7.5     │ <1.7.11                  │ 25714    │
╞══════════════════════════════════════════════════════════════════════════════╡
│ The get_format function in utils/formats.py in Django before 1.7.x before    │
│ 1.7.11, 1.8.x before 1.8.7, and 1.9.x before 1.9rc2 might allow remote       │
│ attackers to obtain sensitive application secrets via a settings key in      │
│ place of a date/time format setting, as demonstrated by SECRET_KEY.          │
╞══════════════════════════════════════════════════════════════════════════════╡
│ django                     │ 1.7.5     │ <1.7.6                   │ 25715    │
╞══════════════════════════════════════════════════════════════════════════════╡
│ Cross-site scripting (XSS) vulnerability in the contents function in         │
│ admin/helpers.py in Django before 1.7.6 and 1.8 before 1.8b2 allows remote   │
│ attackers to inject arbitrary web script or HTML via a model attribute in    │

(以下省略)

Java

jeremylong / DependencyCheck

github.com

 OWASPツールのDependencyCheckですが、MavenやGradleなどの様々なJavaプロジェクトに対応しています。

今回はGradleのプロジェクトを対象にツールを使用しますので、「dependency-check-gradle」というライブラリをGradleに追記します。

Gradle用 jeremylong/dependency-check-gradle

github.com

 使用方法は簡単で「./gradlew dependencyCheckAnalyze」コマンドを実行するだけです。

検査が開始されますので、しばらくすると脆弱性が存在しているライブラリの一覧が表示されます。

f:id:motikan2010:20200128224152p:plain

 整形されずに出力されるので少々見づらいですが、このツールの良い点としてHTML形式のレポートが自動的に保存されるようになっている。
私の環境だと「./build/reports/dependency-check-report.html」に保存されていました。
出力内容をブラウザで確認してみます。

f:id:motikan2010:20200128224212p:plain:w400
f:id:motikan2010:20200128224225p:plain:w400

 ブラウザ上での確認だと非常に見やすく、脆弱性の詳細情報への遷移もラクで便利です。

JavaScript

Npm標準ツール - npm-audit

github.com

f:id:motikan2010:20200128224238p:plain

npmコマンドに標準で付属されているnpm auditサブコマンドです。

脆弱なパッケージをアップデートする " npm audit fix " コマンド

 npm audit fixコマンドを使用することで、脆弱性見つかっているパッケージのアップデートを行うことができます。
 以下がそのコマンドを使用してパッケージのアップデートが行われるまでの流れです。

$ cat package-lock.json | grep '"hot-formula-parser"' -A 1
    "hot-formula-parser": {
      "version": "3.0.0",

 npm audit fixコマンドを実行します。1つの脆弱性が見つかり、修正した旨のメッセージが表示されました。

$ npm audit fix
npm WARN vuln_hot-formula-parser_RCE No repository field.
npm WARN vuln_hot-formula-parser_RCE No license field.

+ hot-formula-parser@3.0.2
updated 1 package in 0.316s
fixed 1 of 1 vulnerability in 5 scanned packages

 依存パッケージを確認してみると、バージョンが上がっていることが確認できます。

$ cat package-lock.json | grep '"hot-formula-parser"' -A 1
    "hot-formula-parser": {
      "version": "3.0.2",

 確認のために再度npm auditコマンドを実行します。
脆弱性は見つからず、修正されたことが確認できます。

$ npm audit

                       === npm audit security report ===

found 0 vulnerabilities
 in 5 scanned packages

まとめ

 どのツールもリポジトリが依存するライブラリのバージョンを利用して検査しています。
そのため実際にアプリケーションが動作する環境に影響を及ぼすことなくセキュリティの検査を実施することが可能です。
今回紹介したツールは、主に各自の環境にインストールして利用するものでした。しかし、そのような手間をかけるかけることなく「検査対象のリポジトリを登録するだけで脆弱性が存在しているライブラリが存在する場合にアラートを出してくれるサービス」も存在しています。

 一番身近なものはGitHubだと思います。リポジトリが依存しているライブラリに脆弱性が見つかったら下画像のようにアラートが表示されます。 これは脆弱性が放置されている良くない例です・・・。ちなみにリポジトリ所有者のみにアラートが見えるようになっています。
f:id:motikan2010:20200129013022p:plain:w400

 Github以外にも Snykyamory といったサービスがあります。
どちらも無料プランがあり、導入も簡単であることから両方利用していますがどちらも使いやすくオススメです。趣味で開発している人も使ってみるとよいかと。

更新履歴

  • 2019年1月29日 新規作成