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 がコンテナ内のどのダイナミックリンクライブラリをロードするかを特定します。
- 対応するダイナミックリンクライブラリのソースコードをダウンロードし、
__attribute
__属性の関数 run_at_link を追加します(この関数はダイナミックリンクライブラリがロードされる際に最初に実行されます)。 - 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 ブラックリストメカニズムをデフォルトですべての Capabilities を禁止するモードに変更し、最小限の必要な権限をコンテナランタイムに与えるホワイトリスト方式に変更しました。Docker はデフォルトでコンテナに 14 の権限を与えます。
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 の場合、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 が実行され、さらに 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