Linuxベースのコンテナのセキュリティ脆弱性への対処について知っておきたいこと
Karni Wolf
2019年9月18日
0 分で読めます現在、本番環境で稼働している最も重要なコンテナイメージについて考えてみてください。そのベースイメージはどのように選びましたか?そのベースイメージに脆弱性がいくつあるか把握していますか?知りたいと思いませんか?
Snykでは、最も安全なベースイメージを選ぶプロセスを、よりスマートでスムーズに、そして何よりデータに基づいたものにすることを目指しています。
まず、このブログ記事ではLinuxベースのイメージを扱うため、Linuxディストリビューションのセキュリティについて背景から説明します。
Linuxディストリビューションの概要
Linuxディストリビューション(ディストリビューション)とは、ソフトウェアの集合体から構成されるオペレーティングシステム(OS)です。Linuxカーネル(オペレーティングシステムの中核)、パッケージ管理システム、GNUツールおよびライブラリ、その他のソフトウェアやドキュメントをまとめ、保守担当者がさまざまなプラットフォームやデバイスのニーズに応えられるよう、その機能を最大限に高める目的で変更を加えたものです。
ディストリビューションは、通常次の2つの方法で提供されます。
コンパイル済みバイナリ(パッケージ化されたイメージ)として、Docker Hubなどのイメージリポジトリからダウンロードできます。通常、イメージはソースコードとして保守されているライブラリからパッケージ化されます。
ソースコードとして提供され、元のソフトウェアを変更できます。ディストリビューションに含まれるソフトウェアの大半は通常オープンソースであるため、柔軟性が大きく高まります。
現在、数百種類のLinuxディストリビューションがあり、その大半は活発に保守されています。機能の選択肢が豊富で柔軟性も高いため、コンテナを含め、さまざまなプラットフォームやデバイスで利用されています。
他のソフトウェアと同様に、コンテナもコードに含まれる脆弱性を悪用した攻撃の影響を受ける可能性があります。
Linuxディストリビューションや各リリースによって、セキュリティはどう異なるのでしょうか?
ディストリビューションごとに、構築方法や保守方法には違いがあります。コンポーネントのパッケージ化や管理の方法などが異なり、その結果、ディストリビューションのサイズやパッケージマネージャー、セキュリティ脆弱性の影響を受けやすさにも差が生じます。
あるコンポーネントで見つかったセキュリティ脆弱性でも、ディストリビューションによって深刻度スコアが異なる場合があります。複数のディストリビューションで共通しているコンポーネントが、あるディストリビューションでは安全と見なされる一方、別のディストリビューションでは高いCVEスコアが付くことがあります。これは、各ディストリビューションのパッケージ化方法が異なるためです。
保守に組み込まれた仕組みによって、他より安全性の高いディストリビューションもあります。商用で実績のあるディストリビューション(Debian、Ubuntu、CentOS、Oracle)には専任のセキュリティチームがあります。これらのチームは、CVEスコアの確認、セキュリティ修正の優先順位付けと実装、ディストリビューション全体のセキュリティ状態の維持を担っています。
それでも、選択肢ごとに違いはあります。主要なディストリビューションの管理方法の違いを表にまとめました。これらの違いは、それぞれの安全性にも影響します。
ディストリビューション | パッケージング | リリースサイクル |
Debian | dpkg、apt | 定期リリース:約3年間サポート。LTS:さらに2年間(セキュリティチームによるサポートなし) |
Ubuntu | dpkg、apt | マイルストーンリリース:約6か月ごと、3年間サポート LTS:さらに約2年間 |
Oracle | rpm | Red Hatをベースとした安定版リリース。最長10年間サポート |
CentOS | rpm | 安定版リリース Red Hatをベースとし、最長10年間サポート https://wiki.centos.org/FAQ/General#head-fe8a0be91ee3e7dea812e8694491e1dde5b75e6d |
Alpine | apk | edgeから約6か月ごとに安定版をリリース。2年間サポート。* |
ディストリビューション | セキュリティチーム | セキュリティアドバイザリ | パッチリリース前のアドバイザリ(CVEトラッカー) |
Debian | |||
Ubuntu | |||
Oracle | あり | あり | |
CentOS | あり | ||
Alpine | なし | なし |
ディストリビューション | セキュリティ修正 | サポートレベル |
Debian | 人気のあるDebianパッケージの大半は定期的にトリアージされています。また、特定のセキュリティ問題に対するパッチも頻繁に提供されています。 | 技術者中心のコミュニティ |
Ubuntu | 人気のあるUbuntuパッケージの大半は定期的にトリアージされています。Debianがパッチをリリースすると、Ubuntuもその後まもなく該当する修正をリリースします。 | 大規模なコミュニティ/商用サポート |
Oracle | セキュリティ修正は、以下のサイトに記載されているとおり提供されます。 https://www.oracle.com/technetwork/topics/security/alerts-086861.html | 商用サポート |
CentOS | コミュニティ | |
Alpine | 一部の限られたパッケージにはセキュリティパッチが提供され、その他のパッケージは定期的に更新されます。 | 少数のボランティアによるコミュニティ |
*Alpineはイメージの保守に独自のアプローチを採用しています。パッケージを定期的にアップグレードし、主要パッケージ(curlなど)の一部にセキュリティ修正を追加します。
Linuxディストリビューションとプログラミング言語のエコシステムはどう違うのでしょうか?
プログラミング言語のエコシステムでは、パッケージはレジストリに保存され、npmやpipなどのパッケージマネージャーがパッケージの更新を担います。同様に、ディストリビューションもパッケージリポジトリに保存され、さまざまなプロジェクトで依存関係として再利用されます。ただし、ディストリビューションはイメージとしてパッケージ化され、イメージ専用のパッケージリポジトリに別途保存されます。そこからダウンロードすれば、他のプロジェクトですぐに使用できます。イメージはダウンロードしてすぐ使えるようパッケージ化された後、独自のパッケージレジストリに保存され、元となったライブラリとは別に、パッケージマネージャーによって更新されます。
いずれの場合も、パッケージマネージャーがパッケージを定期的にダウンロードして更新し、保存先に再度アップロードします。
しかし、共通点はここまでです。
プログラミング言語のエコシステムにおけるパッケージの保守
プログラミング言語のエコシステムにおけるパッケージの扱いは、比較的シンプルです。パッケージレジストリと少なくとも1つのパッケージマネージャーがあり、両者の関係は明確かつシンプルです。マネージャーがレジストリとの間でパッケージをダウンロードおよびアップロードします。
次の図でイメージできます(左は任意のパッケージリポジトリの一般例、右はnpmの具体例です)。

ディストリビューションのリポジトリにおけるパッケージの保守
一方、イメージリポジトリにあるディストリビューションの場合は、もう少し複雑です。ディストリビューションによっては、複数のリポジトリ、パッケージマネージャー、アップロードツールを使用します。どのリポジトリ、マネージャー、アップロードツールを使うかは、ディストリビューションのリリース番号、対象範囲(main、contributions、non-free、community)などによって異なります。
次の例でイメージできます(左は任意のディストリビューションとバージョンにおける一般的なパッケージリポジトリ、右は複数のDebianリリースの例です)。

各Debianリリースでは、指定されたリリースに適したリポジトリが使用されます。
パッケージやそのバージョンは、すべてのリポジトリで常に利用できるとは限りません。ディストリビューションによっては、パッケージをバックポートできます(あるリリースタイプでのみ利用可能なパッケージバージョンを、別のリリースにインストールできます)。また、UbuntuのPersonal Package Archive(PPA)のような外部リポジトリから、ネイティブのパッケージマネージャーを使わずに、ディストリビューションのバージョンへ直接パッケージを追加できる場合もあります。パッケージとディストリビューションの関係は複雑ですが、パッケージレジストリとパッケージマネージャーの関係はシンプルです。そのため、後者は前述のバージョン管理の問題の影響を受けにくくなっています。
コンテナのセキュリティ問題への対処が複雑な理由
多くのディストリビューションのセキュリティチームは、一部のコンポーネントのみを対象にセキュリティ修正を保守しています。たとえばDebianが公式にセキュリティ修正を提供するのは、ドキュメントに記載されているとおり、mainコンポーネントのみです。これは、時間の経過とともにさまざまなイメージをトリアージするプロセスが複雑なためです。
前述のとおり、イメージは通常、別途オープンソースライブラリとして保管されているソースコードからパッケージ化されます。イメージはパッケージ化され、独立したリポジトリに保存・保守されると、元のソースコードライブラリとは別に独自のバージョンで更新され続けます。ソースコードライブラリもまた、独自のペースでバージョンが更新されていきます。そのため、ライブラリに脆弱性が存在しても、イメージには存在しない場合があります。脆弱性がライブラリの上流バージョンで初めて確認された場合、すでにパッケージ化されたイメージには影響しません。逆のケースもあり得ます。
イメージの構築に使用されたライブラリでセキュリティ脆弱性が発見された場合、セキュリティチームはそれに応じてイメージをトリアージし、脆弱性が実際に存在するか、またイメージの構成を踏まえて脆弱性と見なすべきかを検証します。
歴史があり広く定着しているディストリビューションの多くは、バージョンが大幅にアップグレードされません。そのため通常、新たな脆弱性に対する小規模な更新やセキュリティ修正が提供されます。
非常に古くサポートが終了した(EOL)ディストリビューションや、新しいディストリビューション(まだセキュリティチームの管轄下にない可能性のあるedgeバージョン)は、多くの場合、ディストリビューションの大半で保守対象外と見なされます(たとえばDebian 7はEOLです)。パッケージのバージョンXに脆弱性があり、そのバージョンがEOLリリースでしか利用できない場合や、新たにリリースされたばかりの場合、ディストリビューションのセキュリティアドバイザリに記載されていない可能性があります。そのため、EOLリリースや最新の開発版に対するディストリビューションのセキュリティサポートレベルは、実際のセキュリティ状態を必ずしも反映していません。このようなケースでは、Snykがすべての脆弱性を検出するための情報が不十分で、重大な脆弱性を見逃す可能性もあります。
Linuxディストリビューションがサポートされていないのはなぜですか?
サポート対象のディストリビューションベースのイメージはすべて、ディストリビューションとリリースに基づいて脆弱性データベースと照合してスキャンされます。スキャン後、脆弱性の詳細と情報源、修正の有無、影響を受けるディストリビューションとリリース、修正が適用されるバージョンを一覧表示します。
脆弱性情報の収集では、新しいリリースを常に把握し、それに備えたロードマップを用意できるよう努めています。また、ユーザーの活動やニーズを細かく追跡し、それに応じてデータベースを充実させています。さらに、support@snyk.ioやTwitterアカウントを通じて、いつでもユーザーとお話しできる体制を整えています。また、この記事で取り上げた各プロバイダーのLTSリリースをサポートできるよう、特に注力しています。ただし、あらゆるディストリビューションをサポートしているわけではありません。たとえば、非常に古い、または新しいディストリビューションをベースにしたイメージは、Snykでサポートされていない可能性があります。
Snykは、どのようにして安全なベースイメージの代替候補を提案するのですか?
また、幅広いリポジトリのデータを定期的に収集し、Docker Hubから各リポジトリのすべてのタグを1日に複数回取得して、最新の状態を保っています。この情報をもとに、Snykプロジェクトを関連するDockerfileにリンクしていれば、ベース(または親)イメージの修正に関するアドバイスも提供できます。
Snykのアプリケーションスキャンをご利用であれば、監視またはテストするリポジトリごとに、数件から数十件程度の脆弱性が検出されることに慣れているかもしれません。しかしLinuxエコシステムでは、検出される脆弱性の数が大きく異なり、数百件に及ぶのが一般的です。
膨大な数に圧倒されることのないよう、イメージや脆弱性について、より実践的なアドバイスとインサイトを提供できるよう努めています。そのために、コンテナプロジェクトに含まれていることの多いDockerfileを提供していただいています。
Snykでイメージをスキャンする際、Dockerfileを保存しているソースコードへのリンクを追加できます。リポジトリをスキャンすると、その結果に基づいて修正方法をご提案します。Dockerfileへのリンク方法について詳しくは、ドキュメントをご覧ください。
Dockerfileを受け取ると、ベースイメージを特定し、脆弱性のうちベースイメージに起因するものと、Dockerfileで追加された他のレイヤーに起因するものの数を把握できます。これにより、Dockerfileで追加した他のレイヤーを修正するか、ベースイメージをより安全な別のイメージに置き換えるかを判断しやすくなります。
適切なアップグレード候補をご提案するため、数十のリポジトリと数百のタグを継続的に取得してスキャンしています。次に、イメージデータベースを脆弱性データベースと照合し、最新の情報に基づいて利用可能な最も安全なイメージを見つけます。そのうえで、ベースイメージ用としてリポジトリのタグを提案します。候補は次のとおりです。
マイナーアップグレード:現在のタグからマイナーバージョンを上げたタグです。マイナーアップグレードだけで数十、場合によっては数百の脆弱性を解消できることもあります。まずは確認してみてはいかがでしょうか。
メジャーアップグレードの候補:次のメジャーリリースにアップグレードします
代替案:コンテナに適している可能性のある、別の関連性のないイメージをおすすめします
次の条件に基づいて、代替タグをアップグレード候補として判定します。
重大度の高い脆弱性の数が少ない、または重大度の高い脆弱性の数は同じでも重大度が中程度の脆弱性が少なく、重大度の低い脆弱性の数が同じかそれ以下であること。
候補イメージのタグのOSディストリビューションが、古すぎるもの、最新すぎるもの、LTS以外のもの、または不安定なものでないこと。
Alpineディストリビューションでは、パッチが適用された一部のパッケージしかセキュリティアドバイザリを利用できません。そのため、Alpineベースのイメージはセキュリティの可視性が低いと判断し、Alpineベースのタグはおすすめしていません。
代替アップグレードでは、異なるディストリビューションのタグを使うことがあり、通常は変更のリスクが大幅に高まります。それでも、イメージを安全に保つため、できるだけ多くの選択肢に関する情報を提供したいと考えています。
まとめ
コンテナはライブラリとは異なるため、セキュリティ対策やトリアージがより難しいのは間違いありません。一方で、明らかな重要メリットがあることから、コンテナはあらゆる場所で使われています。だからといって、危険なコンテナをリリースしなければならないわけではありません。計画を立て、Snykのような優れたセキュリティツールを導入すれば、コンテナのセキュリティ確保を大幅に容易にできます。
いずれにしても、コンテナの安全性をできるだけ高く保つため、定期的にトリアージすることが重要です。脆弱性を発見し、ベースイメージの置き換えが必要になった場合は、コンテナの安全性を保ちながら、正常に動作しなくなる事態を避けるため、次の点を考慮してください。
OSパッケージへの依存関係がないか確認してください。依存関係がある場合は、アップグレードによって影響が出ないことを確認してください。
イメージのサイズを考慮してください。
代替アップグレードを検討する場合は、使用中のディストリビューション固有のコマンドや機能も確認し、必要に応じて更新してください。
今すぐSnykでイメージをスキャンしてみましょう。
開発者ファーストのコンテナセキュリティ
Snykは、コンテナイメージとKubernetesワークロードの脆弱性を検出し、自動的に修正します。

