Trivy を利用した Docker Container・Image の脆弱性検知入門

tl;dr

  • trivyを利用することで簡単にDocker コンテナの脆弱性の検知をすることが出来る。
    • OSライブラリからアプリケーション依存のライブラリまで検知が可能
  • SimpleかつREADMEが豊富で導入の敷居が低い。
  • CIに組み込むことで DevOps から DevSecOps への移行を加速することが可能。

コンテナの脆弱性

2020/08/06 現在、Dockerを利用するしてプロダクトの環境を作る事がデファクトスタンダードになっている。 どの会社に行ってもセキュリティは最重要視されていると言っても過言ではないが、Docker イメージを生成 or 取得し、そのまま利用を続け、時間が経ち、利用しているライブラリに不具合が生じているのにも関わらず、知らないうちに脆弱性があるContainerを利用しているケースは少なくない。

脆弱性を放置して起きたインシデントは具体的に下記のような事例がある。

コンテナに仮想通貨の採掘を行うマルウェアイメージをダウンロードさせるキャンペーンが頻繁に行われており、ピーク時は 2,000以上の Dockerホストがマルウェア感染したとの報告もあります。

www.netone.co.jp

脆弱性の検知

コンテナの脆弱性検知を行うツールは複数ある。

Docker Bench Security

github.com

clair

github.com

anchore

anchore.com

今回はOSSのTrivyを利用する。

Trivyとは

AquaSectiry社が提供するOSS。特徴として、A Simple and Comprehensive Vulnerability Scanner for Containers, Suitable for CI と書かれているように非常にシンプルかつ、とても簡単にCIに組み込むことが出来る。

github.com

製作者は日本の方で、OSSで作成したものをAquaSecutiry社が買収し、そのまま就職をして仕事でOSS開発をするというエンジニアには夢のような記事を書かれていたことを覚えている。

knqyf263.hatenablog.com

READMEがとても豊富にかかれており、各プラットフォームでのインストールの方法が書かれており、気軽に手元で実践することが出来ることも非常に魅力的。

https://github.com/aquasecurity/trivy#installation

特に利用していきたいと決めた点は、OSパッケージの脆弱性だけではなく、各アプリケーションの依存ライブラリの脆弱性の検知も出来る。 アプリケーションの依存ライブラリというのは、RubyでいうGemfile.lock、NodeJSでいうpackage-lock.json, yarn.lock。 メジャーなアプリケーションの依存ライブラリはサポートされている印象で、業務でも使いやすい。

https://github.com/aquasecurity/trivy#application-dependencies

Trivyで脆弱性を検知する

実際に検知をしてみる。今回は3年前に作ったきり更新していないDocker Imageを利用する。

github.com

hub.docker.com

$ trivy image docker.io/teitei/docker-chrome-stable:latest
2020-08-07T00:30:14.481+0900  [33mWARN[0m You should avoid using the :latest tag as it is cached. You need to specify '--clear-cache' option when :latest image is changed
2020-08-07T00:30:46.674+0900  [34mINFO[0m Detecting Ubuntu vulnerabilities...

docker.io/teitei/docker-chrome-stable:latest (ubuntu 16.04)
===========================================================
Total: 930 (UNKNOWN: 0, LOW: 462, MEDIUM: 446, HIGH: 22, CRITICAL: 0)

+--------------------------+------------------+----------+-------------------------------------+---------------------------------------+----------------------------------------------------------+
|         LIBRARY          | VULNERABILITY ID | SEVERITY |          INSTALLED VERSION          |             FIXED VERSION             |                          TITLE                           |
+--------------------------+------------------+----------+-------------------------------------+---------------------------------------+----------------------------------------------------------+
| apt                      | CVE-2019-3462    | HIGH     | 1.2.20                              | 1.2.29ubuntu0.1                       | Incorrect sanitation of the                              |
|                          |                  |          |                                     |                                       | 302 redirect field in HTTP                               |
|                          |                  |          |                                     |                                       | transport method of...                                   |
+                          +------------------+----------+                                     +---------------------------------------+----------------------------------------------------------+
|                          | CVE-2020-3810    | MEDIUM   |                                     | 1.2.32ubuntu0.1                       | Missing input validation in                              |
|                          |                  |          |                                     |                                       | the ar/tar implementations of                            |
|                          |                  |          |                                     |                                       | APT before version 2.1.2...                              |
+--------------------------+------------------+----------+-------------------------------------+---------------------------------------+----------------------------------------------------------+
| bash                     | CVE-2019-18276   | LOW      | 4.3-14ubuntu1.2                     |                                       | bash: when effective UID is                              |
|                          |                  |          |                                     |                                       | not equal to its real UID                                |
|                          |                  |          |                                     |                                       | the...                                                   |
+                          +------------------+          +                                     +---------------------------------------+----------------------------------------------------------+
|                          | CVE-2019-9924    |          |                                     | 4.3-14ubuntu1.4                       | bash: BASH_CMD is writable in                            |
|                          |                  |          |                                     |                                       | restricted bash shells                                   |
+--------------------------+------------------+          +-------------------------------------+---------------------------------------+----------------------------------------------------------+
| bsdutils                 | CVE-2016-2779    |          | 2.27.1-6ubuntu3.2                   |                                       | util-linux: runuser tty hijack                           |
|                          |                  |          |                                     |                                       | via TIOCSTI ioctl                                        |
+                          +------------------+          +                                     +---------------------------------------+----------------------------------------------------------+
|                          | CVE-2016-5011    |          |                                     |                                       | util-linux: Extended partition                           |
|                          |                  |          |                                     |                                       | loop in MBR partition table                              |
|                          |                  |          |                                     |                                       | leads to DOS                                             |
+--------------------------+------------------+          +-------------------------------------+---------------------------------------+----------------------------------------------------------+
| coreutils                | CVE-2016-2781    |          | 8.25-2ubuntu2                       |                                       | coreutils: Non-privileged                                |
|                          |                  |          |                                     |                                       | session can escape to the                                |
|                          |                  |          |                                     |                                       | parent session in chroot                                 |
+--------------------------+------------------+----------+-------------------------------------+---------------------------------------+----------------------------------------------------------+
....
....
....

Total: 930 (UNKNOWN: 0, LOW: 462, MEDIUM: 446, HIGH: 22, CRITICAL: 0) と画面に収まりきれないほど検知出来ている。

アプリケーション依存のライブラリに存在する脆弱性の検出も出来る。これは私が雑に作ったものを入れているRepositoryで、Sinatraを利用しているが、rackに脆弱性がある。

github.com

$ trivy image teitei-tk/zatsu/ruby-rsa
2020-08-07T00:21:22.325+0900    WARN    You should avoid using the :latest tag as it is cached. You need to specify '--clear-cache' option when :latest image is changed
2020-08-07T00:21:28.282+0900    INFO    Detecting Alpine vulnerabilities...
2020-08-07T00:21:28.290+0900    INFO    Detecting bundler vulnerabilities...

teitei-tk/zatsu/ruby-rsa (alpine 3.12.0)
========================================
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)


app/Gemfile.lock
================
Total: 3 (UNKNOWN: 0, LOW: 0, MEDIUM: 3, HIGH: 0, CRITICAL: 0)

+---------+------------------+----------+-------------------+---------------+--------------------------------+
| LIBRARY | VULNERABILITY ID | SEVERITY | INSTALLED VERSION | FIXED VERSION |             TITLE              |
+---------+------------------+----------+-------------------+---------------+--------------------------------+
| rack    | CVE-2019-16782   | MEDIUM   | 2.0.7             | 2.0.8, 1.6.12 | rubygem-rack: hijack sessions  |
|         |                  |          |                   |               | by using timing attacks        |
|         |                  |          |                   |               | targeting the session id       |
+         +------------------+          +                   +---------------+--------------------------------+
|         | CVE-2020-8161    |          |                   | 2.1.3         | rubygem-rack: directory        |
|         |                  |          |                   |               | traversal in Rack::Directory   |
+         +------------------+          +                   +---------------+--------------------------------+
|         | CVE-2020-8184    |          |                   | 2.2.3, 2.1.4  | rubygem-rack: percent-encoded  |
|         |                  |          |                   |               | cookies can be used to         |
|         |                  |          |                   |               | overwrite existing prefixed    |
|         |                  |          |                   |               | cookie names...                |
+---------+------------------+----------+-------------------+---------------+--------------------------------+
....
....
....

Rackに脆弱性があることがわかる。

フィルタリング

サーベイ

CRITICAL, HIGH など、サーベイによってフィルタリングも出来る。

$ trivy image --severity CRITICAL,HIGH docker.io/teitei/docker-chrome-stable:latest
2020-08-07T00:32:37.159+0900    WARN    You should avoid using the :latest tag as it is cached. You need to specify '--clear-cache' option when :latest image is changed
2020-08-07T00:32:37.216+0900    INFO    Detecting Ubuntu vulnerabilities...

docker.io/teitei/docker-chrome-stable:latest (ubuntu 16.04)
===========================================================
Total: 22 (HIGH: 22, CRITICAL: 0)

+--------------------+------------------+----------+-------------------+-------------------+--------------------------------+
|      LIBRARY       | VULNERABILITY ID | SEVERITY | INSTALLED VERSION |   FIXED VERSION   |             TITLE              |
+--------------------+------------------+----------+-------------------+-------------------+--------------------------------+
| apt                | CVE-2019-3462    | HIGH     | 1.2.20            | 1.2.29ubuntu0.1   | Incorrect sanitation of the    |
|                    |                  |          |                   |                   | 302 redirect field in HTTP     |
|                    |                  |          |                   |                   | transport method of...         |
+--------------------+                  +          +                   +                   +                                +
| libapt-pkg5.0      |                  |          |                   |                   |                                |
|                    |                  |          |                   |                   |                                |
|                    |                  |          |                   |                   |                                |
+--------------------+------------------+          +-------------------+-------------------+--------------------------------+
| libc-bin           | CVE-2018-1000001 |          | 2.23-0ubuntu7     | 2.23-0ubuntu10    | glibc: realpath() buffer       |
|                    |                  |          |                   |                   | underflow when getcwd()        |
|                    |                  |          |                   |                   | returns relative path allows   |
|                    |                  |          |                   |                   | privilege escalation...        |
+--------------------+                  +          +                   +                   +                                +
| libc6              |                  |          |                   |                   |                                |
|                    |                  |          |                   |                   |                                |
|                    |                  |          |                   |                   |                                |
|                    |                  |          |                   |                   |                                |
+
....
....
....

OS or Library

表示する脆弱性の種類をOS or アプリケーション依存ライブラリを選ぶことも出来る

$ trivy image --vuln-type os  --s CRITICAL,HIGH docker.io/teitei/docker-chrome-stable:latest
2020-08-07T00:33:44.006+0900    WARN    You should avoid using the :latest tag as it is cached. You need to specify '--clear-cache' option when :latest image is changed
2020-08-07T00:33:44.061+0900    INFO    Detecting Ubuntu vulnerabilities...

docker.io/teitei/docker-chrome-stable:latest (ubuntu 16.04)
===========================================================
Total: 22 (HIGH: 22)

+--------------------+------------------+----------+-------------------+-------------------+--------------------------------+
|      LIBRARY       | VULNERABILITY ID | SEVERITY | INSTALLED VERSION |   FIXED VERSION   |             TITLE              |
+--------------------+------------------+----------+-------------------+-------------------+--------------------------------+
| apt                | CVE-2019-3462    | HIGH     | 1.2.20            | 1.2.29ubuntu0.1   | Incorrect sanitation of the    |
|                    |                  |          |                   |                   | 302 redirect field in HTTP     |
|                    |                  |          |                   |                   | transport method of...         |
+--------------------+                  +          +                   +                   +                                +
| libapt-pkg5.0      |                  |          |                   |                   |                                |
|                    |                  |          |                   |                   |                                |
|                    |                  |          |                   |                   |                                |
+--------------------+------------------+          +-------------------+-------------------+--------------------------------+
| libc-bin           | CVE-2018-1000001 |          | 2.23-0ubuntu7     | 2.23-0ubuntu10    | glibc: realpath() buffer       |
|                    |                  |          |                   |                   | underflow when getcwd()        |
|                    |                  |          |                   |                   | returns relative path allows   |
|                    |                  |          |                   |                   | privilege escalation...        |
+--------------------+                  +          +                   +                   +                                +
| libc6              |                  |          |                   |                   |                                |
|                    |                  |          |                   |                   |                                |
|                    |                  |          |                   |                   |                                |
|                    |                  |          |                   |                   |                                |
+
....
....
....

脆弱性の修正方法

Docker ImageをBuildをし直すだけ。

$ docker build -t teitei/docker-chrome-stable:new .
$ trivy image teitei/docker-chrome-stable:new
2020-08-07T00:39:12.168+0900    INFO    Detecting Ubuntu vulnerabilities...

teitei/docker-chrome-stable:new (ubuntu 16.04)
==============================================
Total: 275 (UNKNOWN: 0, LOW: 244, MEDIUM: 31, HIGH: 0, CRITICAL: 0)

+-----------------------+------------------+----------+---------------------------------------+---------------+------------------------------------------------+
|        LIBRARY        | VULNERABILITY ID | SEVERITY |           INSTALLED VERSION           | FIXED VERSION |                     TITLE                      |
+-----------------------+------------------+----------+---------------------------------------+---------------+------------------------------------------------+
| bash                  | CVE-2019-18276   | LOW      | 4.3-14ubuntu1.4                       |               | bash: when effective UID is                    |
|                       |                  |          |                                       |               | not equal to its real UID                      |
|                       |                  |          |                                       |               | the...                                         |
+-----------------------+------------------+          +---------------------------------------+---------------+------------------------------------------------
....
....
....

これはDockerfileのBaseImageに ubuntu:16.04 と古いImageを利用しているためLOWとMEDIUMが消えていないが、先程に比べてHIGHが0件になり、MEDIUMの検知数が415件減っていることがわかる。

CIへの組み込み

参考PR

github.com

今回はGitHubActionを利用してtrivyを実行している。trivyはtrivy-actionというGitHubActionに組み込むことが出来るActionを公開しているので、そちらを利用した。

github.com

更にGitHubActionはSchedule機能があるので、一定間隔にチェックすることも出来る。

docs.github.com

その他のCI

CircleCIやTravisCIを使っている場合でもREADMEにサンプルがあるので、それを参考にすることですぐに組み込むことが出来る。

まとめ

  1. コンテナを作成してそのまま放置し続けるのは脆弱性を放置することになり危険。
  2. trivyを利用することで簡単にコンテナの脆弱性を検知することが出来る。
  3. trivyはREADMEも豊富に書かれているのと、SimpleでCIに組み込みやすいので、比較的導入がしやすい。
  4. OSのライブラリだけでなく、アプリケーション依存のライブラリの脆弱性検知も出来る。

ref

github.com

www.slideshare.net

qiita.com