鳩小屋

落書き帳

Linux OSのセキュリティ機能とコンテナ技術

コンテナセキュリティの考え方

コンテナの比較対象としてよく挙がるのはベアメタル環境や仮想化環境です。

ベアメタル環境は、ひとつのOS上でミドルウェアやアプリケーションが動作するレガシーな構成です。一方、コンテナ技術や仮想化技術では、コンテナエンジンやハイパーバイザの上で別のOSが動作します。これにより、アプリケーションとホストOSが分離され、セキュリティ境界として機能します。

多層防御の視点から見ると、一般的に仮想化環境が最もセキュリティレイヤの強度が強く、ベアメタル環境が弱いとされています。なお、コンテナ環境はこれらの中間に位置しています。

仮想化環境やベアメタル環境との違い

仮想化環境は、CPUやメモリなどの物理リソースを主に仮想化することによって、ハードウェアレベルの分離を実現しています。そのため、ゲストOS上とホストOSは強く分離されており、一般的にハイパーバイザ上のプログラムがホストOSに直接アクセスすることは困難です。

一方、コンテナ環境は、ホストOS内のカーネルや物理リソースに直接アクセスして動作します。ただし、コンテナは、後述するnamespaceやcgroupなどの技術により、ホストOSへのアクセスが強く制限されています。コンテナの実体はベアメタル環境と同じプロセスやスレッドになりますが、他プロセスやホストOSへのアクセス権が制限されているため、脅威にさらされてもコンテナ内で被害を抑えることができます。そのため、ベアメタル環境よりは強固な分離が実現できます。

 

多層防御とコンテナ

コンテナ化されたプロセスは、通常のプロセスと同じように、システムコールを使用し、パーミッションや特権を必要とします。コンテナでは、実行時やコンテナイメージの構築時に、パーミッションをどのように割り当てるかがセキュリティに大きな影響を与えます。コンテナは要素技術がそのままセキュリティに繋がるので、コンテナ技術を理解する上で知っておくべきLinux OSの機能と合わせて紹介します。

コンテナの要素技術

Namespace

namespaceはリソースの分離を行います。例えばデフォルトではコンテナは自身のプロセス情報かしか見えませんが、dockerの--pidオプションを指定して他のコンテナと PID namespace を共有することで別のコンテナのプロセス情報(PIDなど)が見えます。

  • mount namespace
  • UTS namespace
  • IPC namespace
  • PID namespace
  • network namespace
  • user namespace
  • cgroup

dockerはデフォルトでmount、uts、ipc、pid、networkを使用します。

コンテナはnamespaceでコンテナプロセスを隔離しますが、オプションを指定することで隔離を弱めることができます。

具体的には、docker runに--pid=hostオプションを指定することによって、ホストのプロセスIDをコンテナ内から認識されるようにできます。

上記のようなnamespaceを緩和する設定は、コンテナの隔離機能が低下するため、基本的に非推奨となります。

pivot_root

pivot_rootはプロセスのルートファイルシステムを隔離する目的で使用されるコマンドです。ホストOSのファイルシステム上にコンテナ用の新しいルートファイルシステムを作成できます。プログラムの実体はファイルとメモリであることを考えれば、ファイルシステムの隔離技術はコンテナの根幹といえます。コンテナ技術では、プロセスのファイルシステムを隔離したうえで、namespaceで論理リソースを隔離、cgroupでcpuやメモリなどを制限して、コンテナを生成しています。

 

 

cgroups

コンテナは論理的には強力な権限分離がされていますが、物理的にはホストOSのCPUやメモリを共有しています。そのため、一つのコンテナに過剰な物理リソースを割り当てると、他コンテナの障害などに繋がります。

cgroup はCPUやメモリの仕様を制限できます。dockerでは、--cpu-shares オプションで操作が可能です。実際にはcgroup のcpu.shares ファイルによって制限されています。

同様にKubernetesのポッド構成ファイルでも制御ができます。

 

 

 

Linux capability

現在のLinuxカーネルには、30種類以上のケイパビリティが搭載されています。ケイパビリティは特権を細分化する仕組みで、割り当てたスレッドが特定のアクションを実行できるかどうかが決まります。例えば、スレッドが低番号(1024以下)のポートにバインドするには、CAP_NET_BIND_SERVICEケイパビリティが必要です。CAP_SYS_BOOT は、任意の実行ファイルがシステムを再起動する許可を得られないようにするために存在します。CAP_SYS_MODULEは、カーネルモジュールをロードまたはアンロードするために必要です。先ほど、pingツールがrootとして実行され、スレッドが生のネットワークソケットを開くために必要なケイパビリティを自分自身に与えるのに十分な時間があると述べました。この特定のケイパビリティは CAP_NET_RAW と呼ばれています。

プロセスに割り当てられたケイパビリティは、getpcapsコマンドで確認することができます。

 

Dockerでは、デフォルトでコンテナに割り当てられるケーパビリティが決まっていますが、--cap-add及び--cap-dropオプションでこれらの制御ができます。

docs.docker.com

許可されたケーパビリティ一覧

Capability Key Capability Description
AUDIT_WRITE Write records to kernel auditing log.
CHOWN Make arbitrary changes to file UIDs and GIDs (see chown(2)).
DAC_OVERRIDE Bypass file read, write, and execute permission checks.
FOWNER Bypass permission checks on operations that normally require the file system UID of the process to match the UID of the file.
FSETID Don’t clear set-user-ID and set-group-ID permission bits when a file is modified.
KILL Bypass permission checks for sending signals.
MKNOD Create special files using mknod(2).
NET_BIND_SERVICE Bind a socket to internet domain privileged ports (port numbers less than 1024).
NET_RAW Use RAW and PACKET sockets.
SETFCAP Set file capabilities.
SETGID Make arbitrary manipulations of process GIDs and supplementary GID list.
SETPCAP Modify process capabilities.
SETUID Make arbitrary manipulations of process UIDs.
SYS_CHROOT Use chroot(2), change root directory.

 

Kubernetesでも、 ポッド構成ファイルやポッドセキュリティで制御することができます。

apiVersion: v1

kind: Pod

metadata:

  name: security-context-demo-4

spec:

  containers:

  - name: sec-ctx-4

    image: gcr.io/google-samples/node-hello:1.0

    securityContext:

      capabilities:

        add: ["NET_ADMIN", "SYS_TIME"]

コンテナの種類

 

Docker runコマンドに--privilegedオプションを指定すると、これらのケーパビリティがすべて割り当てられます。これがいわゆる特権コンテナと呼ばれるものです。

現在主流の特権コンテナと通常コンテナはどちらもroot権限で動作していますが、特権コンテナと通常コンテナの主な違いは付与される特権の範囲になります。

ルートレスコンテナと呼ばれる技術も開発が進んでおり、コンテナエンジンやコンテナをホストOSの一般ユーザ権限で動作させます。これには、User Namespaceが利用されています。ルートレスコンテナの利点は、コンテナが乗っ取られたとしても、ホストOSのroot権限まで窃取されにくいところです。開発が進めばルートレスコンテナが主流になるかもしれません。

特権コンテナの危険性

特権コンテナは、ホストOSとの権限境界がnamespaceのみになり、ホストOSに特権アクセスできてしまうため、非常に危険です。

 

コンテナの運用では、--privilegedオプションを付与せず、コンテナに必要なケーパビリティのみを付与することが重要となります。

ファイルパーミッション

コンテナを運用しているかどうかに関わらず、Linux システムでは、ファイルパーミッションがセキュリティの要となります。Linuxでは、すべてがファイルであるという言葉があります。アプリケーションコード、データ、設定情報、ログなど、すべてがファイルに収められています。画面やプリンターなどの物理的なデバイスもファイルとして表現されます。ファイルに対するパーミッションは、どのユーザがそのファイルへのアクセスを許可され、ファイルに対してどのようなアクションを実行できるかを決定します。

 

 

 

ls -lコマンドを実行するとファイルとその属性に関する情報を取得できます。

$ ls -l
-rw-rw-r-- 1 user user 0 4月 11 10:17 abc

最初の3文字のグループは、ファイルを所有するユーザーに対するパーミッションを記述します。 

2番目のグループは、そのファイルのグループのメンバーに対するパーミッションを示しています。

最後のグループは、他のユーザーの権限を示しています。

ユーザーがこのファイルに対して実行できるアクションは、r、w、xの各ビットが設定されているかどうかによって、読み取り、書き込み、実行の3つに分かれます。各グループの3つの文字は、オンまたはオフになっているビットを表し、これら3つのアクションのうちどれが許可されているかを示します。

r、w、xの各ビットについては、すでにご存知の方も多いと思いますが、それだけではありません。パーミッションは、setuidビット、setgidビット、stickyビットの使用によっても影響を受けます。最初の2つのビットは、セキュリティの観点から重要です。なぜなら、攻撃者が悪意のある目的で使用する可能性のある追加のパーミッションをプロセスに取得させることができるからです。

 

通常、ファイルを実行すると、起動したプロセスは自分のユーザーIDを継承します。ファイルにsetuidビットが設定されている場合、プロセスはファイルの所有者のユーザーID(権限)を持つことになります。

以下のようなファイルの場合、root以外のユーザがファイルを実行した際に実行ファイルがrootの権限で動作します。このファイルに任意のコードや操作を実行する脆弱性ががあった場合、一般ユーザがroot権限(権限昇格)でコマンドを実行したりできるようになります。

ls -l

-rwsr-xr-x 1 root vpsuser 6579  3月 15 16:38 2016 setuid_test

 

setuidは特権昇格への危険な経路を提供するため、コンテナ・イメージ・スキャナの中には、setuid ビットが設定されたファイルの存在を報告するものがあります。また、docker run コマンドで --no-new-privileges オプションを指定すると、setuid ビットが使用されないようになります。

 

Kubernetesでは、 ポッド構成ファイルやポッドセキュリティのallowPrivilegeEscalationで制御することができます。

 

apiVersion: v1

kind: Pod

metadata:

  name: security-context-demo

spec:

  securityContext:

    runAsUser: 1000

    runAsGroup: 3000

    fsGroup: 2000

  volumes:

  - name: sec-ctx-vol

    emptyDir: {}

  containers:

  - name: sec-ctx-demo

    image: busybox

    command: [ "sh", "-c", "sleep 1h" ]

    volumeMounts:

    - name: sec-ctx-vol

      mountPath: /data/demo

    securityContext:

      allowPrivilegeEscalation: false

システムコール

アプリケーションは、ユーザースペースと呼ばれる、オペレーティングシステムカーネルよりも低いレベルの権限を持つ空間で動作します。アプリケーションが、ファイルへのアクセス、ネットワークでの通信、時刻の確認などを行いたい場合には、アプリケーションに代わってカーネルに必ず要求しなければなりません。ユーザー空間のコードがカーネルにこれらの要求をするために使用するプログラムインターフェースは、システムコールまたはsyscallインターフェースとして知られています。システムコールには300以上の種類があり、その数はLinuxカーネルのバージョンによって異なります。以下が例です。

 

read ファイルからのデータ読み込み

write ファイルへのデータ書き込み

open ファイルを開いて後から読み書きできるようにする

execve 実行プログラムの実行

chown ファイルの所有者を変更

clone 新しいプロセスの作成

 

 

システムコールは通常、より高レベルのプログラミング抽象化に包まれているため、アプリケーション開発者がシステムコールを直接気にする必要はほとんどありません。。。が、コンテナが利用できるシステムコールを制限すれば、コンテナの隔離を強化することができます。

dockerでは、seccompを使ってシステムコールの制限を行えます。設計上はseccompを使わなくてもcontainer breakoutを防げるはずですが、システムコールを制限しておくことで脆弱性に関する処理を防げる可能性があります。

しかしながら、実際のアプリケーションでは必要となるシステムコールの一覧は自明ではないため、手動のプロファイル作成は困難です。現実的な方法としては、straceなどで必要なシステムコールを洗い出す方法や、dockersilmでプロファイルを行う方法があります。

dockerでは、コンテナ実行時に--security-opt オプションでseccompのポリシーファイルを指定することで禁止されたシステムコールをブロックします。

docker run --rm -it --security-opt seccomp=/path/to/seccomp/profile.json hello-world

 

また、dockerでは、デフォルトのseccompポリシーファイルが用意されています。これは経験則から最適化されたポリシーになるため、新しいseccompプロファイルを適用する場合には、このポリシーを拡張するという方法が一般的です。

  Kubernetesでは、ポッド構成ファイルにseccompのプロファイル(ワーカノードに保存されたもの)を指定することでコンテナランタイム(dockerなど)で適用されます。

securityContext:

  seccompProfile:

    type: RuntimeDefault|Localhost|Unconfined 

    localhostProfile: my-profiles/profile-allow.json 

dzone.com

 

ユニオンファイルシステム

pivot_rootの概念図を見ると、コンテナのファイルシステムがホストOS上にそのまま配置されているだけに見えますが、実はそこまで単純ではありません。コンテナのルートファイルシステムはユニオンファイルシステムという仕組みで構成されています。

コンテナのユニオンファイルシステムは、ホストOS上に散らばったディレクトリ(ハッシュblob)を束ねてひとつのルートファイルシステムにしています。

なぜこのような仕組みなっているかというと、コンテナイメージ(コンテナのファイルバンドル)は、レイヤという論理単位で分割されていて、各レイヤごとにディレクトリ管理されているためです。

静的なファイルのコンテナイメージからコンテナ(プロセス)が起動するとリードオンリーのコンテナイメージ(レイヤ)の内容がコピーされた、読書き可能なレイヤ(コンテナレイヤ)が新しく生成されます。コンテナはそこにディスクへの変更を記録して動作します。このとき、コンテナイメージが変更されることはありません。また、コンテナが破棄されると同時に、読書き可能なレイヤ(コンテナレイヤ)は破棄されるため、実行時の情報は揮発します。

 

 

 


コンテナイメージの仕様は、(OCI)Open Container Initiativeという団体が決めています。

github.com

www.itbook.info

namu-r21.hatenablog.com

 

コンテナのセキュリティ原則

最小限の特権

最小限の特権の原則は、個人または組織が必要とする最小限のアクセスに制限することを指します。

電子商取引アプリケーションで商品検索を行うマイクロサービスがあるとします。最小特権の原則から、マイクロサービスは商品データベースへの読み取り専用のアクセスを与える認証情報のみを持つべきだと考えられます。マイクロサービスは、ユーザー情報や支払い情報などにアクセスする必要はなく、商品情報を書き込む必要もありません。

コンテナは、コンテナごとに異なる権限を与えることができ、それぞれが機能を果たすために必要な最小の権限セットに最小化されます。

深層防御

深層防御の原則では、保護の層を適用する必要があります。攻撃者が 1 つの防御を突破しても、別の層が攻撃者による配備の損傷やデータの流出を防ぐことができます。 コンテナを利用することでLinuxの多層防御に新しいセキュリティ境界を付加することが可能です。

攻撃対象の最小化

一般的なルールとして、システムが複雑であればあるほど、攻撃方法が存在する可能性が高くなると言われています。複雑さを解消することで、システムが攻撃されにくくなります。これには以下が含まれます。

  • 可能な限りインターフェイスを小さくシンプルにしてアクセスポイントを減らす。
  • サービスにアクセスできるユーザとコンポーネントを制限するコード量を最小限に抑える。

モノリシックサービスをマイクロサービスに分割することで、それらの間にクリーンなインターフェイスが形成されるため、慎重に設計することで複雑さが軽減され、アタックサーフェスが制限される可能性があります。一方で、コンテナを調整するために複雑なオーケストレーション層を追加すると、別の攻撃対象が発生するという反論もあります。(オーケストレータのAPIサーバなど)

影響範囲の制限

セキュリティ・コントロールをより小さなサブコンポーネントまたは「セル」に分割するというコンセプトは、最悪の事態が発生しても影響が限定されることを意味します。コンテナは、この原則に適しています。アーキテクチャをマイクロサービスの多数のインスタンスに分割することで、コンテナ自体がセキュリティ境界として機能するからです。 コンテナ化されたアプリケーションが脅威にさらされた場合、攻撃をコンテナ内に限定し、システムの他の部分に影響を与えないようにすることができます。

権限の分離

最小特権と爆発範囲の制限の両方に関連するのが、任務の分離という考え方です。これにより、可能な限り、異なるコンポーネントや人に、システム全体の中で必要な最小のサブセットに対する権限を与えることができます。このアプローチでは、特定の操作が複数のユーザーの権限を必要とするようにすることで、一人の特権ユーザーが与えるダメージを制限します。

認証情報などのシークレットは、それを必要とするコンテナにのみ渡すことができるため、ある秘密のセットが侵害されても、必ずしもすべての秘密が失われるわけではありません。 ただし、実際には、システム構成の不備や、コンテナイメージの構成ミス、不用意な操作によって、これらの利点が簡単に打ち消される可能性もあります。

Kubernetesの脅威モデル

脅威分析の目的は下記参照。

参考


Microsoft f:id:FallenPigeon:20210418090111p:plain

NCC

外部からの攻撃者

  • 脅威の主体

クラスタ上で実行されているアプリケーションや管理ポートにネットワーク経由でアクセスできることを除けば、クラスタへのアクセス権を持たない人々。

  • 対策

管理サービス(APIサーバー、kubelet、etcdなど)が、認証制御を行わずに信頼されていないネットワークにさらされないようにする。

悪意のあるコンテナ

  • 脅威の主体

攻撃者は、(何らかのアプリケーションの脆弱性を通じて)1つのコンテナにアクセスし、そのアクセスを拡大してクラスタ全体を乗っ取ろうとします。

  • 対策

クラスタネットワーク上のすべての管理ポートで、すべてのユーザーに認証が必要であることを確認します。
サービスアカウントがコンテナにマウントされていないか、制限された権限(クラスタ管理者ではない)であることを確認します。
ネットワークポリシーを使用して、ネームスペースとポッド間のアクセスを制限します。

 

悪意のあるユーザー/危害を加えられたユーザー

  •  脅威の主体

攻撃者は、Kubernetes APIに対してコマンドを実行するための有効な認証情報と、ネットワークアクセスを持っています。

  • 対策

 RBACポリシーがすべてのユーザーに適用されており、クラスタリソースへの「最小特権」のアクセスを提供する。
 ポッドセキュリティポリシーがすべてのユーザーに適用されており、特権コンテナなどの高リスクアイテムに特に注意して、作成可能なポッドの権限を制限する。

 

CNCF

 一般的なKubernetesクラスタに対して実施した詳細な脅威モデル演習の文書と成果を発表しました。この作業の目的は、プラットフォームに共通する攻撃ベクトルを特定し、攻撃者が特定の目標を達成するためにKubernetes内の構成上の脆弱性をどのように利用するかを確認するためのチェックリストとして使用できる、脅威と緩和策に関する詳細な見解を提供することでした。

具体的には、STRIDE手法を用いてKubernetesアーキテクチャの各コンポーネントを分析し、プラットフォーム内の信頼境界における潜在的なセキュリティ問題を特定しました。

f:id:FallenPigeon:20210410182633p:plain

 

Attack Vector Description
Service Token デフォルトでは、サービストークンが各ポッドに自動的にマウントされます。コンテナが侵害された場合、攻撃者はそれらの認証情報を使用して悪用するメカニズムを提供することになります。
ここでは、厳格なRBACポリシーと、サービストークンの自動マウントを無効にすることが重要な軽減策となります。
Compromised Container クラスタ内の主要な拠点が、攻撃者にとってのリモート実行ポイントとなるからです。前述のサービストークン攻撃以外にも、注目すべき攻撃ベクターとして、実行中のすべてのコンテナに対してコントロールプレーンをデフォルトのネットワークで公開することが挙げられます。
Network Endpoints Kubernetesエンドポイントは、内部の悪意のあるアクターから保護され、容易な攻撃ベクトルを防ぐ必要があります。攻撃者がコンテナを侵害することができた場合、ポッドのネットワークポリシーが許せば、エンドポイントへのアクセスが可能になることに注意してください。
Denial of Service 1.14のリリースまでは、サービス拒否攻撃に対する緩和策はほとんどありませんでした。
RBAC Issues

攻撃ベクターの多くは、RBACポリシーの設定ミスに依存しています。
対策としては、このようなポリシーを検証するための自動化されたツールが必要です。

Attack Trees

ボトムアップアプローチ

このアプローチでは、目標を達成するために、Kubernetesプラットフォーム全体のエントリーポイントを示します。セキュリティコントロールと標準を脅威に対応させ、その適用範囲を理解するのに役立ちます。

シナリオ・アプローチ

シナリオベースのビューで、特定のシナリオで攻撃者に開かれている攻撃ベクターを特定します。このアプローチは、最初のアプローチの詳細の多くを活用しているが、より現実的な形で、より一般的な攻撃ベクターに焦点を当てるために使用できる。

Attack Tree Approach Description
Malicious Code Execution Bottom Up この攻撃ツリーの目的は、クラスター上で悪意のあるコードを実行することです。最初の足場は、主に、コンテナへのアクセスを提供する侵害されたアプリケーションを介して行われます。
攻撃者がコンテナにアクセスできるようになると、次のステップとして、環境に悪意のあるコードを追加でロードするようになります。また、イメージプルシークレットを取得できた場合、攻撃者がリポジトリをポイズンしてそこから悪意のあるコードを配布する可能性もあります。
Establish Persistence Bottom Up このツリーの目的は、攻撃者がクラスター内で持続性を獲得するためのさまざまな方法を発見し、その持続性を評価することです。
一方、2つ目のブランチは、攻撃者がコンテナにアクセスし、設定ミスを利用して、コンテナ/ポッド/ノードの再起動にも耐えうる持続性を確立するという脅威に焦点を当てています。
Access Sensitive Data Bottom Up 主なアプローチは、RBAC権限の設定ミスを利用して、クラスターから秘密データを直接読み取ることができることです。その他にも、ログに保存された機密データの閲覧や、ネットワークトラフィックの盗聴などがあります。
Denial Of Service Bottom Up このツリーでは、攻撃者がクラスターにサービス拒否攻撃を仕掛けるためのアプローチを検討します。
1つ目のアプローチは、コンテナを侵害するシナリオで、攻撃者がクラスタのリソースを使い切って内部からDOS攻撃を試みる場合です。
2つ目のアプローチは、クラスターのコントロールプレーンにネットワークアクセスできる攻撃者に焦点を当て、適切なエンドポイントでネットワークをフラッディングしてリソースを使い切ろうとする可能性があります。
Compromised application leads to foothold in container Scenario このシナリオでは、攻撃者がコンテナ内で実行されているアプリケーションを悪用した場合に、攻撃者に開かれる潜在的ベクターについて詳しく説明します。これにより、プログラムやシェルのアクセスメカニズムを介して、コンテナ内でリモートコードが実行されます。
Attacker on the Network Scenario このシナリオでは、Kubernetesクラスターをホストするネットワークにアクセスできる内部攻撃者に焦点を当てます。これは、より特権的なユーザーである可能性が高いですが、クラスタに直接アクセスできません。なお、これらの脅威の大部分は、ファイアウォールと適切なKubernetesの設定によって軽減することができます。

f:id:FallenPigeon:20210410183537p:plain

f:id:FallenPigeon:20210410183546p:plain

 

Kubernetes Security Audit Working Group

 

Scope

この脅威モデルの具体的な内容については、6つの制御ファミリーにわたるKubernetesコンポーネントをレビューしています。

  1. Networking
  2. Cryptography
  3. Authentication
  4. Authorization
  5. Secrets Management
  6. Multi-tenancy

さらに、Kubernetes自体がAPIゲートウェイからコンテナオーケストレーション、ネットワークなどにまたがる大規模なシステムであることを考慮して、8つのコンポーネントを選択し、今回の演習の範囲に含まれるようにしました。

  1. kube-apiserver
  2. kube-scheduler
  3. kube-controller-manager
  4. kube-proxy
  5. kubelet
  6. etcd
  7. cloud-controller-manager
  8. Container Runtime

f:id:FallenPigeon:20210410183838p:plain

 

 

コンテナの脅威モデル

脅威分析の目的は下記参照。

kurobato.hateblo.jp

セキュリティの観点から見ると、コンテナ化された環境では、多くが従来のデプロイメントと同じになります。世の中には、データを盗んだり、システムの動作を変更したり、他人のコンピュートリソースを使って自分の暗号通貨を採掘しようとする攻撃者がいます。これは、コンテナに移行しても変わりません。しかし、コンテナはアプリケーションの実行方法を大きく変え、その結果、さまざまなリスクが発生します。

リスクは、潜在的な問題が発生した場合の影響を指します。脅威は、そのリスクの発生源です。緩和策は、脅威に対する対策です。

脅威のアクター

脅威モデルについて考え始める一つの方法は、関係するアクターを考えることです。関係者には次のようなものがあります。

  • 外部から配置にアクセスしようとする外部攻撃者

  • デプロイメントの一部になんとかアクセスしようとする内部攻撃者

  • デプロイメントにアクセスするためのある程度の権限を持つ開発者や管理者などの悪意のある内部アクター

  • 偶然に問題を引き起こす可能性のある内部アクター

  • システムを侵害しようとする意識を持った存在ではないが、システムにプログラムでアクセスできる可能性のあるアプリケーションプロセス

コンテナの脅威

f:id:FallenPigeon:20210419100731p:plain

f:id:FallenPigeon:20210410181319p:plain

  • 脆弱なアプリケーションコード

ライフサイクルは、開発者が作成するアプリケーションコードから始まります。このコードと、コードが依存しているサードパーティの依存関係には、脆弱性として知られる欠陥が含まれている可能性があり、公開されているものだけでも数千件あります。
脆弱性は、アプリケーションに存在した場合に攻撃者が悪用できるものです。既知の脆弱性を持つコンテナの実行を避けるための最良の方法は、イメージをスキャンすることです。既存のコードには常に新しい脆弱性が発見されているため、これは1回限りの活動ではありません。また、スキャンプロセスでは、セキュリティパッチの更新が必要な古いパッケージを使用したコンテナが実行されているかどうかを特定する必要があります。スキャナの中には、イメージに組み込まれたマルウェアを識別できるものもあります。

  • 不適切に設定されたコンテナイメージ

コードが書かれると、それがコンテナイメージに組み込まれます。コンテナイメージの構築方法を設定する際には、後で実行中のコンテナを攻撃するために使用できる弱点を導入する機会がたくさんあります。例えば、コンテナをルートユーザとして実行するように設定すると、ホスト上で実際に必要な以上の権限が与えられます。

  • ビルドマシンへの攻撃

攻撃者がコンテナイメージのビルド方法を変更したり、影響を与えたりすると、後に本番環境で実行される悪意のあるコードが挿入される可能性があります。また、ビルド環境で足場を確保することで、本番環境への侵入の足がかりとなる可能性もあります。

コンテナのイメージが構築されると、それはレジストリに保存され、実行される時点でレジストリから取り出される、つまり「プル」されます。取り出したイメージが以前にプッシュしたものと全く同じであることをどうやって確認することが必要になります。

  • 不適切に設定されたコンテナ

コンテナに不必要な権限を与える設定でコンテナを実行することが可能です。インターネットからYAML設定ファイルをダウンロードした場合、安全でない設定が含まれていないことを確認して実行する必要があります。

  • 脆弱なホスト

コンテナはホストマシン上で動作しますが、これらのホストが脆弱なコード(例えば、既知の脆弱性を持つ古いバージョンのオーケストレーションコンポーネントなど)を実行していないことを確認する必要があります。攻撃対象を減らすために、各ホストにインストールされているソフトウェアの量を最小限にするか、ベストプラクティスに従って正しく設定する必要があります。

  • 露出したシークレット情報

アプリケーションコードは、システム内の他のコンポーネントと通信するために、認証情報、トークン、またはパスワードを必要とすることがよくあります。コンテナ化されたデプロイメントでは、これらの秘密の値をコンテナ化されたコードに渡すことができなければなりません。環境変数やマウントを利用するアプローチがあります。

  • 安全でないネットワーキング

コンテナは通常、他のコンテナや外部と通信する必要があります。コンテナ間通信や他ホスト上のコンテナと通信する際にバインドポートの制限や通信の暗号化が必要になります。

containerd や CRI-O など、広く使用されているコンテナランタイムは、現在ではかなり強化されていますが、コンテナ内で実行されている悪意のあるコードをホスト上に逃がしてしまうようなバグがまだ見つかる可能性もあります。アプリケーションによっては、エスケープの結果が十分に損害を与える可能性があるため、より強力な隔離機能の仕組みを検討する価値があります。