1. クラウドネイティブセキュリティとは#
クラウドコンピューティング -> クラウドネイティブ -> クラウドネイティブセキュリティ
クラウドネイティブセキュリティを理解する前に、まずクラウドコンピューティングとクラウドネイティブについて理解しましょう。
クラウドコンピューティング:
クラウドコンピューティングが登場する前は、ソフトウェアのユーザー数やデータ量が少なかったため、直接会社のサーバールームに配置することができました。しかし、現在のビッグデータ環境では、従来のソフトウェアアーキテクチャは適していません。ソフトウェアの再構築やデータの移行は困難です。そのため、クラウドコンピューティングが生まれました。
クラウドコンピューティングでは、ユーザーは必要に応じてリソースを取得できます。
クラウドネイティブ:
クラウドネイティブには明確な定義はありません。クラウドネイティブは常に進化しており、説明権は特定の個人や組織に帰属していません。
クラウドネイティブ(CloudNative)は、アプリケーションの構築と実行の方法であり、技術スタックと方法論のセットです。
クラウドネイティブアーキテクチャに準拠したアプリケーションは、オープンソーススタック(K8S+Docker)を使用してコンテナ化され、マイクロサービスアーキテクチャを採用して柔軟性と保守性を向上させ、アジャイルな方法と DevOps を利用して継続的なイテレーションと自動化された運用をサポートし、クラウドプラットフォームのインフラストラクチャを活用して弾力性のあるスケーリング、ダイナミックなスケジューリング、リソースの最適化を実現します。
クラウドネイティブの 4 つの要素:
- マイクロサービス
- コンテナ化
- DevOps
- 継続的デリバリー
クラウドネイティブを簡単に理解すると、クラウドへの移行プロセスでのソフトウェアアプリケーションサービスの技術的なアーキテクチャです。
クラウドネイティブセキュリティ:
クラウドネイティブには、従来のセキュリティの問題(DDoS 攻撃、Web 侵入など)がまだ存在します。
さらに、クラウドネイティブには以下の問題があります:
- API セキュリティ
- コンテナセキュリティ
- 中央管理の不足
- トラブルシューティングの困難さ
2. コンテナセキュリティとは#
クラウドネイティブエコシステムでは、さまざまな種類のコンテナが存在します。ここでは Docker を例に分析します。
2.1 Docker 自体のセキュリティの脆弱性#
- CVE 公式レコードによると、Docker の過去のバージョンには 20 以上の脆弱性が存在し、コードの実行、権限の昇格、情報の漏洩などが含まれます。
- Docker のソースコードのセキュリティ
- Docker Hub のセキュリティ
2.2 Docker のアーキテクチャの欠陥#
- コンテナ間のローカルネットワーク攻撃
- リソースの枯渇による DDoS 攻撃
- 脆弱なシステムコール
- 共有された root ユーザー権限
3. コンテナセキュリティ#
3.1 コンテナ化された開発テストプロセスへの攻撃に対する対策#
背景
- docker cp コマンド
docker cp コマンドは、Docker で作成されたコンテナとホストファイルシステム間でファイルやディレクトリをコピーするためのものです。
- シンボリックリンク
シンボリックリンク(ショートカット)は、Windows のショートカットに似ています。
CVE-2018-15664 - シンボリックリンクの置換による脆弱性
影響を受けるバージョン:Docker 17.06.0-ce~17.12.1-ce:rc2
,18.01.0-ce~18.06.1-ce:rc2
脆弱性の原理:CVE-2018-15664 は、実際には TOCTOU(time-of-check to time-of-use)の問題であり、競合状態の脆弱性です。
簡単に言えば、プログラムが特定のオブジェクトに対してセキュリティチェック(たとえば、ユーザーが docker cp コマンドを実行した後、Docker デーモンは指定されたコピー先パスをチェックします)とそのオブジェクトを使用するステップの間にギャップがあります。攻撃者は、セキュリティチェックをパスするオブジェクトを事前に作成し、すぐに正当なオブジェクトと置き換えることができます。その結果、ターゲットプログラムは置換後の悪意のあるオブジェクトを実際に使用します(docker cp コマンドを使用する際にシンボリックリンクを置換すると、ディレクトリトラバーサルが発生する可能性があります)。
脆弱性の再現:metargetを使用して、CVE-2018-15664 の環境を迅速に構築します。
CVE-2019-14271 - 信頼されていないダイナミックリンクライブラリのロード
影響を受けるバージョン:Docker 19.03.x before 19.03.1
脆弱性の原理:docker cp コマンドは、docker-tar コンポーネントに依存してコンテナ内部の nsswitch ダイナミックリンクライブラリをロードします。攻撃者は、コンテナ内部の nsswitch を乗っ取ることで、ホストマシン上の root 権限でのコード実行能力を実現できます。
脆弱性の利用手順は以下の通りです:
- docker-tar がコンテナ内のどのダイナミックリンクライブラリをロードするかを特定します。
- 対応するダイナミックリンクライブラリのソースコードをダウンロードし、run_at_link という関数に
__attribute
__属性を追加します(この関数はダイナミックリンクライブラリがロードされる際に最初に実行されます)。 - docker cp が脆弱性をトリガーするのを待ちます。
3.2 コンテナソフトウェアサプライチェーンへの攻撃#
コンテナ技術の普及に伴い、コンテナイメージはソフトウェアサプライチェーンの非常に重要な部分となりました。パブリックリポジトリからイメージを取得したり、プライベートリポジトリからイメージを取得したりすることができます。
パブリックリポジトリからイメージを取得する場合、次の 2 つの脆弱性の問題があります:
- イメージ内のソフトウェアのセキュリティの脆弱性
- イメージ内のマイニングプログラム、バックドアプログラム、ウイルスなどのマルウェア
イメージの脆弱性の利用
イメージの脆弱性の利用は、イメージにローカルの脆弱性が存在する場合、通常、イメージを作成して実行されるコンテナにも同じ脆弱性が存在することを意味します。
たとえば、Alpine は、musl libc と busybox に基づいて構築された軽量な Linux ディストリビューションです。そのサイズの小ささから、Alpine をベースにソフトウェアを構築することは非常に一般的です。しかし、Alpine イメージには CVE-2019-5021 という脆弱性がありました。Alpine 3.3〜3.9 のバージョンでは、root ユーザーのパスワードが空に設定されており、攻撃者はコンテナに侵入した後、コンテナ内の root 権限に昇格することができます。
イメージの汚染
イメージの汚染は広範なトピックであり、攻撃者は公開リポジトリに悪意のあるイメージをアップロードしたり、システムを侵害して被害者のローカルリポジトリにイメージをアップロードしたり、イメージ名を変更して正規のイメージを偽装したりすることで、被害者を欺いたり誘導したりして攻撃者が指定した悪意のあるイメージを作成して実行することができます。これにより、侵入や被害者のホストを悪用した悪意のある活動が可能になります。
目的に応じて、一般的なイメージの汚染には次の 3 つのタイプがあります:
- 悪意のあるマイニングイメージの投入
- 悪意のあるバックドアイメージの投入
- 悪意のあるエクスプロイトイメージの投入
3.3 コンテナランタイムへの攻撃#
不安全な構成によるコンテナの脱出
これらの年月の間、コンテナコミュニティは、深層防御、最小特権などの原則を実現するための取り組みを続けてきました。
Docker は、コンテナランタイムの Capabilities ブラックリストメカニズムをデフォルトですべて禁止するホワイトリスト方式に変更しました。Docker はデフォルトでコンテナに 14 の権限を与える近く 40 の権限のうちのいくつかを与えます。
func DefaultCapabilities() []string {
return []string{
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_FSETID",
"CAP_FOWNER",
"CAP_MKNOD",
"CAP_NET_RAW",
"CAP_SETGID",
"CAP_SETUID",
"CAP_SETFCAP",
"CAP_SETPCAP",
"CAP_NET_BIND_SERVICE",
"CAP_SYS_CHROOT",
"CAP_KILL",
"CAP_AUDIT_WRITE",
}
}
細粒度の権限制御や他のセキュリティメカニズムを使用することで、ユーザーはコンテナ環境の設定を変更したり、コンテナの実行時にパラメータを指定したりすることで、制約を縮小または拡大することができます。制御されていないコンテナに危険な構成パラメータを提供すると、攻撃者に一定の脱出の可能性を提供することになります。
危険なマウントによるコンテナの脱出
仮想化ソリューションは、ホストマシンと仮想マシン間でデータの交換を容易にするために、ホストマシンのディレクトリを仮想マシンにマウントする機能を提供しています。コンテナも同様です。ただし、ホストマシン上の機密ファイルやディレクトリをコンテナ内部にマウントすると、制御されていないコンテナが存在する場合、重大な問題が発生します。
3.4 プログラムの脆弱性によるコンテナの脱出#
CVE-2019-5736
影響を受けるバージョン:Docker version <= 18.09.2
& RunC version <= 1.0-rc6
脆弱性の原理:CVE-2019-5736 は、コンテナの脱出を可能にするコンテナランタイムである runc プログラムをカバーする脆弱性です。たとえば、docker exec
などのコマンドを実行する際に、実際にはコンテナランタイムが操作を実行しています。たとえば、runc exec
コマンドが実行されます。これにより、コンテナ内部でユーザーが指定したプログラムを実行することができます。さらに言えば、これはコンテナのさまざまな名前空間内で、さまざまな制約(Cgroups など)の下でプロセスを起動することと同じです。したがって、これはホストマシン上でプログラムを実行するのと同じです。
攻撃手順:
- コンテナ内の
/bin/sh
プログラムを#!/proc/self/exe
に上書きします。 - コンテナ内の
/proc
ディレクトリを継続的にスキャンし、各/proc/[PID]/cmdline
を読み取り、runc を文字列マッチングします。runc プロセス ID を見つけるまで続けます。 - 読み取り専用で
/proc/[runc-PID]/exe
を開き、ファイルディスクリプタを取得します。 - 取得した読み取り専用のファイルディスクリプタ (
/proc/self/fd/[fd]
) を書き込みモードで開こうと続けます。最初は常に失敗しますが、runc が使用を終了した後に書き込みモードで開くことができるようになります。その後、このファイルディスクリプタを使用してホストマシン上の/usr/bin/runc
(または/usr/bin/docker/runc
)に攻撃ペイロードを書き込みます。 - runc は最後に、
docker exec
で指定された/bin/sh
を実行します。この内容は、最初のステップで#/proc/self/exe
に置き換えられているため、実際にはホストマシン上の runc が実行され、runc も第 4 ステップで上書きされています。
3.5 カーネルの脆弱性によるコンテナの脱出#
オペレーティングシステムのレベルでは、コンテナプロセスはさまざまなセキュリティメカニズムに制約されたプロセスの一種に過ぎません。したがって、攻撃と防御の両方において、コンテナの脱出は従来の特権昇格プロセスに従います。攻撃者はこの特性を利用してコンテナの脱出のアイデアを拡張することができます。新しいカーネルの脆弱性が発生した場合、それがコンテナの脱出に使用できるかどうかを検討することができます。一方、防御側はこの特性に基づいて保護と検出を行うことができます。たとえば、ホストカーネルのパッチを適用するか、そのカーネルの脆弱性の利用にどのような特徴があるかを調べることができます。
CVE-2016-5195
影響を受けるバージョン:Linux カーネル >= 2.6.22(2007 年リリース、2016 年 10 月 18 日まで修正されなかった)
脆弱性の原理:Linux カーネルのメモリサブシステムには、書き込み時コピー(Copy-on-Write)の処理中に競合状態の脆弱性が存在し、プライベートな読み取り専用メモリマッピングを破壊することができます。
この脆弱性を利用するために、PoCを使用します。この利用の核心的なアイデアは、vDSO にシェルコードを書き込み、通常の関数呼び出しプロセスを乗っ取ることです。
4. 参考文献#
- 《クラウドネイティブセキュリティ - 攻撃と防御の実践と体系構築》
- https://github.com/Metarget/cloud-native-security-book
- https://www.cnblogs.com/buchiyexiao/p/14702051.html