サイト内の現在位置

コンテナイメージのセキュリティ

NECセキュリティブログ

2022年1月28日

NECサイバーセキュリティ戦略本部セキュリティ技術センターの山﨑です。
今回は、NIST SP800-190 Application Container Security GuidePDF[1](日本語訳版:PDF[2])で言及されているセキュリティリスクのうち、コンテナイメージに関するリスクに着目して紹介します。なお、本ブログにおけるコンテナプラットフォームはDockerを使用するものとして説明します。

はじめに

コンテナ技術は可搬性の高さや自動化、再利用のしやすさといった特長から近年のシステム構築におけるトレンドとなっています。一方で、コンテナ環境をターゲットとする攻撃事例も日々報告されています。例えば、インターネット上に公開されたDocker APIのエンドポイントを介してマルウェアを感染させる攻撃キャンペーンnew window[3]や、Docker hub上にクリプトマイナーが設置され、2000万回ものダウンロードが行われた事例new window[4]などがあります。上記の特長を持ったコンテナ技術をビジネスに活用していくためには、組織はコンテナセキュリティについて検討する必要があります。

コンテナイメージのセキュリティリスク

コンテナセキュリティを検討する際の指針として、米国国立標準技術研究所(NIST)が発行したNIST SP800-190が挙げられます。NIST SP800-190では、コンテナ技術のコアコンポーネントである「イメージ」、「レジストリ」、「オーケストレータ」、「コンテナ」、「ホストOS」に関する主要なセキュリティリスクと対応策がまとめられています。本ブログのテーマであるイメージについては、以下5つのセキュリティリスクについて言及されています。

  1. イメージの脆弱性
  2. イメージの設定の不備
  3. 埋め込まれたマルウェア
  4. 埋め込まれた平文の秘密情報
  5. 信頼できないイメージの使用

脆弱なイメージからデプロイされたコンテナは(潜在的に)脆弱な状態であるため、イメージを保護することはコンテナセキュリティを考えるうえで重要な要素の一つと言えます。

以降は、5つのセキュリティリスクの解説に加え、Dockerの機能やOSSを用いながら、対策例を紹介します。

1.イメージの脆弱性

コンテナ技術を用いたシステム開発の考え方として、イミュータブルインフラストラクチャ(不変なインフラ)という概念があります。言葉の通り、一度構築したインフラには変更を加えないという意味です。しかし、コンテナ内で使用しているコンポーネントに重大な脆弱性が発見されても対応しない(変更しない)ということではありません。変更を行う場合は、コンポーネントが実行されている既存のコンテナ(リソース)を破棄して新しいコンテナ(リソース)に入れ替えて運用を行います。
イメージの脆弱性の対策としては、イメージに対して脆弱性スキャンを行い、コンポーネントに存在する既知の脆弱性を把握することがスタートとなります。Trivynew window[5]は検査範囲の広さや使いやすさといった観点で人気のある脆弱性スキャナです。CI/CDとの相性の良さも特長です。以下の図は、Trivyで脆弱性スキャンを実行した様子です。イメージ内のコンポーネントに存在する既知の脆弱性が出力されていることが確認できます。

2.イメージの設定の不備

コンポーネントに存在する既知の脆弱性に十分な対処をしていたとしても、設定によってはセキュリティ上危険な状態となっている可能性があります。例えば、管理者が意図しない操作を引き起こす可能性のあるファイルに対してsudoで実行が許可されている、またはsuidが付与されている状態などです。
Docklenew window[6]は、CISベンチマークやオリジナルのチェック項目に基づいた各種設定を検出するOSSです。以下の図で”CIS-DI”から始まる部分が、CISベンチマークの推奨設定を満たしていないとして検出されている項目です。
DockleではCISベンチマークのうちの一部は検査項目としてサポートしておらず、Trivyを使用して検査することを推奨しています。コンテナセキュリティに限った話ではありませんが、ツールを使用してセキュリティ検査を行う際には、使用するツールの検出対象・範囲を認識しておく必要があります。よって、Trivy、Dockleなど検査範囲の異なる複数のツールをビルドパイプラインに組み込むことでより広い観点での検査が可能となります。

3.埋め込まれたマルウェア

身元不明のイメージを使用することは危険です。悪意のあるファイルが身元不明イメージ内に含まれている可能性があるからです。以下は身元不明、すなわち信頼できないイメージと想定した「{Username}/reverse:latest」をDocker hubからpullし、起動した様子です。

実はこのイメージにはマルウェアが仕込まれています。当該イメージからコンテナを起動した瞬間、攻撃者のマシンにリバースシェルが接続され、meterpreterセッションが確立されます。以降、攻撃者はこのコンテナが起動している間、コンテナ内で任意の操作が可能です。

あくまで一例でしたが、身元不明のイメージを使用することで上記のようなリスクが起こり得ます。対策としては、不審な動作を検知するためのモニタリングや、発行元が検証されたイメージのみ使用を許可する(後述)などが考えられます。

4.埋め込まれた平文の秘密情報

コンテナから他システムへ接続するためにSSH秘密鍵などの秘密情報をイメージに含めたい場合があるとします。このとき、秘密情報を誤った方法でイメージに含めてしまうと、イメージにアクセス可能な第三者によって秘密情報を窃取される可能性があります。
以下のDockerfileはalpineをベースイメージとし(①)、ホストのsecret.txtをコンテナ内のrootディレクトリ配下にコピー後(②)、rmコマンドで/root/secret.txtを削除する処理(③)を行っています。このDockerfileから生成されたイメージ(secret-image)からコンテナを起動してもsecret.txtは削除済であるため、その存在は確認できません。

次に、secret-imageのレイヤー(*1)を確認します。以下はdivenew window[7]を使ってレイヤー構成を視覚的に表示した様子です。
「Layers」ペインを見ると、Dockerfileの①②③に対応した3つのレイヤーがあることが分かります。「Current Layer Contents」ペインには、選択したレイヤー内に存在するディレクトリやファイルが一覧化されており、2番目のレイヤー(Id:35b29…771e)に/root/secret.txtが存在していることが確認できます。

secret-imageをtarアーカイブファイルとして保存・展開後、secret.txtが存在するレイヤーId(を名前に持つディレクトリ)配下にあるlayer.tarを展開するとsecret.txtの抽出に成功します。このように、Dockerfile内で秘密情報を削除していたとしても、イメージのレイヤー構成という特徴から秘密情報の抽出が可能です。

イメージ内で秘密情報を安全に扱うためには以下のような方法が考えられます。

  1. BuildKitnew window[8]を利用したビルド
  2. マルチステージビルドnew window[9]の利用

1はBuildKit(*2)を有効化し、イメージのビルド時にsecretオプションを使用する方法です。Dockerfileで秘密情報を渡す必要がある場合に、このオプションを使用することで、命令の実行時のみコンテナ内にマウントされ、最終イメージには秘密情報を残さずにビルドが可能です。
2のマルチステージビルド(*3)を利用すると、ビルドプロセス中に複数のイメージが生成されますが、最終イメージ以外の中間イメージはプロセスの最後に破棄されます。よって、秘密情報が必要な処理は中間イメージで行うようにすることで最終イメージには秘密情報が残りません。

(*1) Dockerイメージは読み込み専用のイメージレイヤーと読み書き可能なコンテナレイヤーで構成されている
(*2) Dockerの18.09で正式に導入された、イメージのビルドの拡張機能
(*3) Dockerの17.05以上で利用可能な機能

5.信頼できないイメージの使用

信頼できない第三者が作成したイメージを利用する場合、マルウェアや脆弱性のあるコンポーネントを取り込んでしまうといったリスクが考えられます。また、自組織で作成したイメージを使用しているつもりでも、組織のレジストリが不正アクセスを受け、第三者にイメージが改ざんされている可能性も考えられます。このようなリスクの対策としては、イメージの発行元の検証、およびイメージの完全性の検証を行うことが考えられます。
Docker Content Trust(DCT)new window[10]は、デジタル署名技術を利用してイメージの発行元の検証とイメージの完全性の検証を行う機能です。環境変数「DOCKER_CONTENT_TRUST=1」を設定することで有効化できます。Notarynew window[11]はDCTをサポートするOSSで、イメージに対する署名、および署名の検証を行います。Notaryを使用する際は、別途Notaryサーバーを準備する必要がありますが、レジストリがDocker hubの場合は連携されているNotaryサーバーが自動的に使われるため、上記環境変数の設定以外は準備不要です。
以下の図は、Docker hubからイメージをpullする際に署名の検証に成功したイメージ({Username}/dct:signed)と、署名の検証に失敗したイメージ({Username}/dct:signed)の様子です。署名の検証に失敗したイメージは信頼できないイメージとしてpullに失敗していることが確認できます。

まとめ

今回はNIST SP800-190で言及されているセキュリティリスクのうちコンテナイメージに着目して、それぞれのリスクの解説、および対策例を紹介しました。コンテナイメージのセキュリティについて考えるきっかけや参考になれば幸いです。

参考

執筆者プロフィール

山﨑 泉樹(やまざき せんじゅ)
セキュリティ技術センター リスクハンティングチーム

ペネトレーションテスト、脆弱性診断を通じたセキュア開発支援、NECの社内CTF運営に従事。業後はフィジカルセキュリティの強化に励む。CISSP、RISS、GPEN、GCPNを保持。

執筆者の他の記事を読む

アクセスランキング