セキュリティブログ:Dockerコンテナを特権モードで実行することが危険な理由

Kubernetesの充実と共に活用が広まるDocker。 しかしながら、まだまだこれからの領域であるからこそのトラブルも多く耳にします。
そんなDockerにおいて、「Dockerコンテナを特権モードで実行することが危険な理由」について紹介します。 

Docker の「Privileged(特権)」コンテナ(以下、特権コンテナ)は、簡潔に言えば、ホストコンピュータに対するすべてのルート権限を備えたコンテナであり、通常のコンテナではアクセスできないリソースへのアクセスが可能です。この特権コンテナの使用例の1つにDockerコンテナ内でDockerデーモンを実行することがあります。もう1つの使用例は、コンテナがハードウェアに直接アクセスする必要がある場合でです。
前者の例である、コンテナ内でコンテナを操作する「Docker-in-Docker」は、Docker自体の開発の目的で導入されました。今日では、オープンソースの自動化サーバJenkinsでの継続的インテグレーションおよび継続的デリバリー(CI / CD)タスクの自動化など、特権コンテナの実行にはさまざまなユースケースが存在します。
ただし、特権コンテナの実行は必ずしも安全ではない。本記事では、セキュリティ保護が十分でない特権コンテナが、どのように企業や組織のシステムへサイバー犯罪者による侵入を許すことになるかを解説します。

■特権コンテナの問題点

一般に、「Docker-in-Docker」は、コンテナの実行中にもう一つ別のコンテナを生成する必要がある場合に使用されます。ただし、保護をせずに特権コンテナを使用した場合、いくつかの深刻な影響が懸念されています。

特権コンテナを実行すると、組織内部のユーザはホストのリソースへの高度なアクセス権限を持つことになります。しかしこれは、攻撃者に悪用された場合も同等のアクセスが可能になることを意味します。
特権コンテナを利用する攻撃に必ずしもリモートコードの実行は伴いませんが、実行された場合、攻撃可能な対象は広範囲に及びます。特権コンテナを利用する目的はアクセス権限を強化するためであり、攻撃者がルート権限でコードを実行できる可能性が高くなります。これは、攻撃者が、全能ともいえる「CAP_SYS_ADMIN」をはじめ、利用可能なすべてのケーパビリティでの完全なルートアクセスを実行できることを意味します。また、cgroups、AppArmor、SECcompなど、セキュリティを追加する他の隔離機能が放棄される、あるいは無効化されることにも注意が必要です。

露出している特権コンテナにアクセスを試みる攻撃者にとって、その利用目的は無限に存在すると言えます。攻撃者は、ホストコンピュータで実行されているソフトウェアを識別し、ソフトウェアの持つ脆弱性を利用することができます。
また、コンテナソフトウェアの脆弱性や、脆弱なパスワードを利用するコンテナまたは認証チェックの全くないコンテナなどの不用意な設定を狙うという可能性もあります。攻撃者の手にルートアクセス権限があるため、不正なコードや、コインマイナーなどのマルウェアが実行され、しかもうまく隠蔽されてしまう可能性があります。

■コンテナを隔離する

アプリケーションの基本コンポーネントが含まれるコンテナは、本来は隔離された環境です。単一のホストコンピュータ内で複数のプロセスを独立して実行することができるように、コンテナエンジンはさまざまなカーネル機能を使用します。DockerコンテナはLinux環境上で実行されるためLinuxカーネルのリソースを区切る機能を利用して独立して実行されます。これらの1つはLinuxのNamespace(名前空間)と呼ばれます。表1は、この名前空間の種類を示しています。

表1:Linux名前空間の種類
デフォルトでは、Dockerデーモンおよびコンテナのプロセスは、ルート権限で実行されます。ただし、別のユーザを作成してアクセス権限を下げることも可能となっており、セキュリティの観点からはそのようにすることが強く推奨されます。

特権コンテナ内でルートアクセス権限を持つことは、ホストコンピュータにおいてもルートアクセス権限を持つことを意味します。しかし表2に示すように、コンテナプロセスのデフォルトのケーパビリティセットは限られていることに注意してください。ただし、特権コンテナはすべてのケーパビリティを持つことになります。

表2:ルート権限で実行されるコンテナのケーパビリティ
セキュリティ強化のため、Dockerには、Dockerfile(必要なDockerイメージを作成するためのファイル)内のUSERディレクティブを使用して、非ルートユーザ権限でコンテナプロセスを実行できるオプションがあります。ホストコンピュータのルートユーザと、コンテナのルートユーザを分離することのできるユーザ名前空間が、デフォルトでは使用されないことに注意してください。ユーザ名前空間はDockerデーモンで設定することが可能で、ルートアクセスが必要な多くの状況で使用できます。 図1に示される角括弧内の数字に注目してください。

図1:ユーザ名前空間がデフォルトでは使用されないことに注意

このように、Dockerは、-userns-remapフラグで明示的に指定しなければ、ユーザ名前空間を使用することはありません。

ユーザ名前空間内では、完全な操作権限をプロセスに付与できますが、ユーザ名前空間外ではそのようにできません。これは、プロセスが、ユーザ名前空間外では非特権ユーザIDを持つことができ、ユーザ名前空間内ではルートユーザを示す ”0 ” を持つことができることを意味します。

これは、たとえプロセスがケーパビリティ「CAP_SYS_ADMIN」を使用できる新しいユーザ名前空間内で実行されており、実行されるアクションが例えばカーネルモジュールのインストールなどの特権昇格を必要とする場合でも、親ユーザ名前空間(ルートユーザ下では実行されず、必要なケーパビリティを持たない)においても要求される特権についてチェックされます。見つからない場合、アクション全体が拒否されます。

–userns-remapによってセキュリティが強化されますが、これは本記事執筆時点でまだ実験的な機能である「Rootless Docker」とは異なります。親コンテナのプロセスであるDockerデーモンは、引き続きルート権限下で実行されます。

■特権コンテナを悪用する攻撃

特権コンテナのケーパビリティがあれば、攻撃者はそれを利用してユーザのホスト環境へのルートアクセスを取得することが可能になります。

最近、トレンドマイクロの設置したハニーポットの1つで、特権コンテナを利用してホストコンピュータの/root/authorized_keys内に独自のSSH公開キーを配置しようとする攻撃者の不正活動を確認しました。

図2:不正な意図で生成された特権コンテナのコード

解析すると、攻撃者が特権コンテナで「/mnt」バインドを使用して、ホストのルート「/」にバインドしようとしたことが確認されました。そしてその後、以下のコマンドが実行されたことを確認しました。

  • “Cmd”:[“sh”,”-c”,”mkdir -pv /mnt/root/; mkdir -pv /mnt/root/.ssh/; ls -ld /mnt/root/.ssh/; chattr -i -a /mnt/root/.ssh/ /mnt/root/.ssh/authorized_keys”]
  • イミュータブル(書き換え禁止)属性を削除し、「/mnt/root/.ssh」および「/mnt/root/.ssh/authorized_keys」にある属性を追加する
図3:特権コンテナで実行されたコマンド

図3のコードには ”Privileged:false” が示されていますが、新しいプロセスは特権コンテナのコンテキスト内で実行されるため、そのケーパビリティはその前に生成された特権コンテナのケーパビリティと一致することになります。解析によれば、 “/”,”/mnt/root ” バインドはDocker CLI内の -v /:/mnt/root  と同等であるため、ホストコンピュータのファイルシステムにアクセスが可能です。

攻撃者はauthorized_keysファイルの上書きも試みたことが、図4のAPIリクエストから確認できます。

図4:authorized_keysを上書きしようとしていることが確認できる

これらの例から、コンテナは本来隔離されたものであるにもかかわらず、攻撃者がそのような制限を外しホストコンピュータのリソースへのアクセス権限を獲得することにより、ユーザのインフラストラクチャが危険にさらされる可能性があることがわかります。

Dockerのprivilegedフラグは、隔離する機能を事実上無効にします。コンテナには、異なるPID名前空間およびMNT名前空間、またcgroupsプロファイルが適用される場合があります。しかし、Dockerコンテナで–privilegedフラグが実行されている場合、ユーザと、そして不本意ながら攻撃者も、ホストに接続されているハードドライブへのアクセスが可能になります。

-privilegedフラグによってルートアクセス権限を得ることになり、攻撃者が「拘束された環境からの脱出」するための多くの方法があります。

  • /dev/sda1または同等の をマウントし、ホストの記憶装置へのアクセスを許可する
    • ls –la /dev/
    • mkdir /hdd & mount /dev/sda1 /hdd
  • cgroups notify_on_releaseおよびrelease_agentを使用して、ホストのルート内でシェルを生成する
  • カスタムカーネルモジュールをデプロイし、ホストでの持続的な活動を可能にする(リバースシェルなど)

■特権コンテナのセキュリティに関する推奨事項

ルート権限なしでユーザがDockerデーモンを実行できるようにすることを目的とした、実験的なRootless (非ルート)Dockerモードが、DockerのエンジニアであるTõnis Tiigi氏によって提案されています。Rootless Dockerモードを使用した場合たとえ攻撃者がDockerデーモンとコンテナに侵入したとしても、ホストコンピュータへのルートアクセス権限はありません。

開発初期段階にあるため、RootlessモードはDockerの全機能を完全にはサポートしていません。2020年12月20日現在、以下についてサポート対象外となっています。

  • cgroups(cgroupに依存するdocker topを含む )
  • AppArmor
  • Checkpoint
  • Overlay network
  • Exposing SCTP ports

とはいえRootlessモードは、これらの機能を使用する確率の低いJenkinsでのビルドなどの多くのユースケースでは十分に利用可能です。

Dockerコンテナは、企業や組織が増え続ける要求に答えるために役立ちます。Dockerコンテナの利用を採用する企業が増加するに伴い、ますます多くのサイバー犯罪者が、そのようなツールのセキュリティギャップを利用しようと余念がありません。

特権モードのコンテナにはもちろん正規の使用方法がありますが、開発者は使用の際には注意を払い、規制をかける必要があります。つまるところ、特権モードのコンテナが攻撃者によって侵入ポイントとして利用された場合、不正なコードやマルウェアを侵害されたホストコンピュータへの拡散に利用される可能性に注意が必要です。

特権コンテナの使用は絶対に避けるべき、ということではありません。組織環境でそのような特権コンテナを実行するときには十分なセキュリティ保護をしてください。

特権コンテナを使用する際のセキュリティ上の推奨事項を以下に示します。

  1. 最小特権の原則を適用する。コンテナの実行を助けるデーモンサービスなどクリティカルなコンポーネントへのアクセスを制限する。ネットワーク接続も暗号化する
  2. コンテナは、内部ネットワークを含め、信頼できるソースにのみアクセスを許可するように設定する。これには、コンテナ自体の適切な認証手順の実装が含まれる
  3. 推奨されるベストプラクティスに従う。Dockerはベストプラクティスの包括的なリストを提供し、インストール後のDockerとの連携を強化するためにLinuxホストを構成するなど、専門家が利用できる組み込みのセキュリティ機能を備えている
  4. 導入を慎重に検討する。どうしてもDockerで実行する必要があるか。ルートアクセスでの実行を必要とせず効果的にジョブを実行できる他のコンテナエンジンはないか。あるいは別の方法で実行可能か。実行した場合関連するリスクは想定範囲内か
  5. 不審なコンテナおよびイメージをチェックするために、定期的にセキュリティ監査を実行する

本記事は、トレンドマイクロ様の許諾により「トレンドマイクロ・セキュリティブログ」の内容を元に作成しております。
ソース:https://blog.trendmicro.co.jp/archives/23577

関連記事

カテゴリー:

セキュリティニュース

情シス求人

  1. チームメンバーで作字やってみた#1

ページ上部へ戻る