本文の内容は、2024年10月9日に Álvaro Iradier が投稿したブログ(https://sysdig.com/blog/container-security-best-practices/)を元に日本語に翻訳・再構成した内容となっております。
コンテナセキュリティのベスト プラクティスに従うことは、検証済みのソフトウェアを正常に提供し、重大なセキュリティ侵害とその結果を防ぐために不可欠です。これらのベスト プラクティスは、堅牢なクラウド ネイティブアプリケーション保護プラットフォーム (CNAPP)を実装する上で重要な要素です。
2023年のCNCF調査によると、90%以上の企業がコンテナを使用しており、84%の企業がKubernetesを使用または評価中でした。コンテナ技術は主流となり、あらゆるところに存在しています。
しかし、コンテナは安全かつ隔離された状態を保つためのものではないのでしょうか? まあ、ある意味そうです。
たとえば、コンテナ内の悪用可能な脆弱性が、公開されたメタデータや誤った資格情報の構成と組み合わさると、クラウド インフラストラクチャー全体が危険にさらされる可能性があります。クラウド ラテラル ムーブメントに関する投稿で説明したように、ハッカーは、この一連のエクスプロイトと誤った構成を使用して、クラウド アカウントで暗号通貨マイニング アプリケーションを実行する可能性があります。
コンテナは、自己完結型アプリケーションの分散メカニズムとして設計されており、分離された環境でプロセスを実行できます。分離を目的として、カーネルネームスペースを使用した軽量メカニズムを採用し、完全なオペレーティング システム、CPU、ハードウェア仮想化など、VM 内のいくつかの追加レイヤーの必要性を排除します。
これらの追加の抽象化レイヤーが欠如し、カーネル、オペレーティング システム、およびコンテナランタイムと緊密に結合されているため、エクスプロイトを使用してコンテナの内部から外部へ、またはその逆にジャンプすることが容易になります。
コンテナセキュリティのベスト プラクティスには、デリバーされるアプリケーションやコンテナイメージ自体のセキュリティ保護だけでなく、コンテナのビルド、配布、特別な実行に使用される完全なコンポーネントスタックも含まれます。
これには以下が含まれます:
ホストまたはVM
- コンテナランタイム
- クラスター技術
- クラウドプロバイダーの構成
- さらにもっと、
セキュリティは、開発、配布、実行、検知、脅威への対応といったさまざまなフェーズで適用できます。

興味深い詳細を詳しく見ていきましょう。一般的な考え方を、DevOps ワークフローに適用できる 17 の具体的なコンテナ セキュリティのベストプラクティスに分解します。
複雑なスタック
コンテナの成功は、多くの場合、次の 2 つの非常に便利な機能によって促進されます。
- これらは、従来の VM イメージよりもはるかに軽量でありながら、すべてのライブラリと依存関係を含む自己完結型の実行可能イメージとしてソフトウェアを配布および実行する非常に便利な方法です。
- カーネルネームスペースを使用して、マウント、PID、ネットワーク、IPC などを含む独自の “jail” 内でプロセスを実行し、カーネル cgroup を介して CPU 使用量とメモリを制限するリソースも提供することで、優れたレベルのセキュリティと分離を提供します。メモリ保護、権限の強制などは、標準のカーネルセキュリティメカニズムを介して提供されます。

コンテナセキュリティモデルはほとんどの場合に十分かもしれませんが、たとえば AWS はサーバーレスソリューションにさらなるセキュリティを追加しています。これは、顧客間の侵害を防ぐために別のレベルの仮想化を追加するマイクロ仮想マシンであるFirecracker内でコンテナを実行することによって実現されます。
これはコンテナが安全ではないことを意味しますか?
それは諸刃の剣であるとも言えます。
コンテナ内で実行されるアプリケーションは、マシン内で直接実行され、ファイルシステムとプロセスを他の多くのアプリケーションと共有するアプリケーションと何ら変わりはありません。ある意味では、それらは悪用可能な脆弱性を含む可能性のあるアプリケーションにすぎません。
コンテナ内で実行してもこれを防ぐことはできませんが、アプリケーションのエクスプロイトからホストシステムにジャンプしたり、他のアプリケーションからデータにアクセスしたりすることがはるかに困難になります。
一方、コンテナは、別のカーネル機能セット、コンテナ ランタイム、そして通常は、悪用される可能性のあるクラスターまたはオーケストレーターに依存します。
したがって、スタック全体を考慮する必要があり、コンテナライフサイクルのさまざまなフェーズでコンテナ セキュリティのベスト プラクティスを適用できます。次の図にこれら 2 つの側面を反映し、各ブロックに適用できるプラクティスに焦点を当ててみましょう。
サーバーレス コンピューティング エンジンECS Fargate、Google Cloud Run などのケースでは、これらの部分の一部が私たちの管理外となるため、私たちは共有責任モデルで取り組んでいます。
- プロバイダーは基盤部分の機能維持とセキュリティ確保を担当します。
- あなたは上位レイヤーに集中できます。

予防: セキュリティをシフトレフトするための 8 つのステップ
コンテナ内のアプリケーションが実行される前に、脅威の発生を防ぐためにさまざまな手法を適用できる場所がいくつかあります。
近年、ソフトウェアサプライチェーンはサイバー脅威の最大の侵入口となっています。現代のビジネスでは、サードパーティのアプリケーション、依存関係、パッケージに日常的に依存しており、脅威アクターがサプライ チェーンを悪用した大規模なセキュリティインシデントが数多く発生しています。
コンテナセキュリティをできるだけ早く予防して適用することが重要であり、コンテナ イメージの開発と配布中にいくつかの優れたプラクティスを適用すれば、最小限の労力で多くのトラブル、時間、コストを節約できます。
1. CI/CDプロセスにコードスキャンを統合する
セキュリティスキャンは、ソフトウェア、構成、インフラストラクチャーを分析し、潜在的な問題や既知の脆弱性を検出するプロセスです。スキャンはさまざまな段階で実行できます。
- コード
- 依存関係
- Infrastructure as code
- コンテナイメージ
- ホスト
- クラウド構成
- …その他
最初の段階であるコードに焦点を当てましょう。アプリケーションを提供する前、またはアプリケーションをビルドする前に、コードをスキャンしてバグや潜在的に悪用される可能性のあるコード (新しい脆弱性) を検出できます。
アプリケーションコードの場合、SAST (静的アプリケーションセキュリティテスト) 用のSnyk CodeやCheckmarx Oneなどのツールを使用して、脆弱性やその他の問題をスキャンできます。さまざまな言語の脆弱性スキャナーを提供するsonarqubeや、Go コードを分析してルールやリンターなどに基づいて問題を検出するgosecなどのオープン ソース SAST ツールもあります。
開発者マシンで実行することもできますが、CI/CD プロセスにコードスキャンツールを統合することで、最低限のコード品質を確保できます。たとえば、一部のチェックが失敗した場合は、デフォルトでプルリクエストをブロックできます。
gosec を実行する Github Action:
name: "Security Scan"
on:
push:
jobs:
tests:
runs-on: ubuntu-latest
env:
GO111MODULE: on
steps:
- name: Checkout Source
uses: actions/checkout@v2
- name: Run Gosec Security Scanner
uses: securego/gosec@master
with:
args: ./...
対応する出力は次のようになります。

2. 依存関係スキャンによる外部脆弱性の削減
サードパーティのライブラリやフレームワークが不要なのは、ごく小規模なアプリケーションとおもちゃのアプリケーションだけです。ただし、外部依存関係のコードを再利用すると、これらの依存関係のバグや脆弱性がアプリケーションの一部として含まれることになります。依存関係のスキャンは、あらゆるアプリケーションビルドプロセスのベスト プラクティスとして組み込む必要があります。
SCA (ソフトウェア構成分析) 機能を提供する Snyk などのツールを使用すると、サードパーティの依存関係を識別できます。npm、maven、go などのパッケージ管理ツールは、脆弱性データベースをアプリケーションの依存関係と照合し、有用なアラートを提供できます。
例えば、Mavenでdependency-checkプラグインを有効にするには、単に pom.xml
にプラグインを追加するだけです:
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>6.2.2</version>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
...
</project>
そして、Maven が実行されるたびに、脆弱性レポートが生成されます。

依存関係を修正された新しいバージョンに更新することで、依存関係を通じて脆弱性が混入されることを回避します。

場合によっては、修正パッチが利用できないためにこれが不可能な場合があります。また、バージョンを上げると、重大な変更のために多くのリファクタリングが必要になる場合もあります。依存関係スキャンによって明らかになった脆弱性を分析して、影響と悪用可能性を評価し、コード内のチェックや脆弱性が悪用されるのを防ぐ保護メカニズムなどの追加対策を導入します。
後で依存関係をスキャンすることも可能ですが、アプリケーションがビルドされると、一部のメタデータ情報が利用できなくなるため依存関係のスキャンの精度が低下し、Go や Rust などの静的にリンクされたアプリケーションでは不可能になる可能性があることに注意してください。
3. イメージスキャンを使用してコンテナイメージを分析する
アプリケーションがビルドされパッケージ化されたら、最小限のライブラリ、依存フレームワーク (Python、Node など)、および構成ファイルを含むコンテナ内にコピーするのが一般的です。コンテナのビルドとランタイムのセキュリティ保護に重点を置いたベスト プラクティスについては、こちらのDockerfileのベストプラクティス Top 20をご覧ください。
イメージスキャナーを使用して、コンテナイメージを分析します。イメージスキャンツールは、コンテナイメージベース ディストリビューションによって提供されるオペレーティングシステムパッケージ (rpm、dpkg、apk など) の脆弱性を検出します。また、前の段階で依存関係スキャンを適用しなかった場合でも、Java、Node、Python などのパッケージ依存関係の脆弱性も明らかにします。

イメージ スキャンは簡単に自動化して実行できます。CI/CD パイプラインの一部として組み込んだり、新しいイメージがレジストリにプッシュされたときにトリガーしたり、クラスター アドミッションコントローラーで検証して非準拠のイメージの実行が許可されていることを確認したりすることができます。もう一つの方法としては、Sysdigを使用して、コンテナが実行されているホストで、コンテナが起動した直後にイメージをスキャンすることが挙げられます。
一例として、Github ActionとSysdig Secure Inline Scan Action の統合が挙げられます。
name: "Security Scan"
on:
push:
jobs:
build-and-scan:
runs-on: ubuntu-latest
steps:
- name: Build the Docker image
run: docker build . --file Dockerfile --tag my-image:latest
- name: Scan image
id: scan
uses: sysdiglabs/scan-action@v3
with:
image-tag: my-image:latest
sysdig-secure-token: ${{ secrets.SYSDIG_SECURE_TOKEN }}
input-type: docker-daemon
run-as-user: root
前の例では、Docker イメージを煮る度し、Docker デーモンからローカルでスキャンします。
スキャン結果はアクション出力の一部として直接提供され、チェックステータスに応じてプルリクエストのマージがブロックされる可能性があります。

4. イメージコンテンツの信頼性を強化する
コンテナイメージの整合性は、 Notaryなどを使用してデジタル署名を追加することで強制でき、その後、アドミッションコントローラーまたはコンテナランタイムで検証できます。
簡単な例を見てみましょう:
$ docker trust key generate example1
Generating key for example1...
Enter passphrase for new example1 key with ID 7d7b320:
Repeat passphrase for new example1 key with ID 7d7b320:
Successfully generated and loaded private key. Corresponding public key available: /Users/airadier/example1.pub
これで、「example1」という署名キーができました。公開部分は次の場所にあります。
$HOME/example1.pub
プライベートカウンターパートは以下の場所にあります:
$HOME/.docker/trust/private/<key ID>.key
他の開発者も独自のキーを生成し、公開部分を共有できます。
ここで、許可された署名者のキーをリポジトリ (例では airadier/alpine) に追加して、署名済みリポジトリを有効にします。
$ docker trust signer add --key example1.pub example1 airadier/alpine
Adding signer "example1" to airadier/alpine...
Initializing signed repository for airadier/alpine...
...
Enter passphrase for new repository key with ID 16db658:
Repeat passphrase for new repository key with ID 16db658:
Successfully initialized "airadier/alpine"
Successfully added signer: example1 to airadier/alpine
そして、リポジトリ内のイメージに次のように署名できます。
$ docker trust sign airadier/alpine:latest
Signing and pushing trust data for local image airadier/alpine:latest, may overwrite remote trust data
The push refers to repository [docker.io/airadier/alpine]
bc276c40b172: Layer already exists
latest: digest: sha256:be9bdc0ef8e96dbc428dc189b31e2e3b05523d96d12ed627c37aa2936653258c size: 528
Signing and pushing trust metadata
Enter passphrase for example1 key with ID 7d7b320:
Successfully signed docker.io/airadier/alpine:latest
DOCKER_CONTENT_TRUST
環境変数が 1
に設定されている場合、プッシュされたイメージは自動的に署名されます:
$ export DOCKER_CONTENT_TRUST=1
$ docker push airadier/alpine:3.11
The push refers to repository [docker.io/airadier/alpine]
3e207b409db3: Layer already exists
3.11: digest: sha256:39eda93d15866957feaee28f8fc5adb545276a64147445c64992ef69804dbf01 size: 528
Signing and pushing trust metadata
Enter passphrase for example1 key with ID 7d7b320:
Successfully signed docker.io/airadier/alpine:3.11
イメージの署名者を確認するには、次のようにします。
$ docker trust inspect --pretty airadier/alpine:latest
Signatures for airadier/alpine:latest
SIGNED TAG DIGEST SIGNERS
latest be9bdc0ef8e96dbc428dc189b31e2e3b05523d9... example1
List of signers and their keys for airadier/alpine:latest
SIGNER KEYS
example1 7d7b320791b7
Administrative keys for airadier/alpine:latest
Repository Key: 16db658159255bf0196...
Root Key: 2308d2a487a1f2d499f184ba...
環境変数 DOCKER_CONTENT_TRUST
が 1
に設定されている場合、Docker CLIは信頼情報がないイメージのプルを拒否します:
$ export DOCKER_CONTENT_TRUST=1
$ docker pull airadier/alpine-ro:latest
Error: remote trust data does not exist for docker.io/airadier/alpine-ro: notary.docker.io does not have trust data for docker.io/airadier/alpine-ro
Kubernetesクラスターでアドミッションコントローラーを使用して、コンテントトラストを強制することができます
5. よくあるセキュリティ設定ミスとその修正
ホスト、コンテナランタイム、クラスター、またはクラウドリソースの構成が誤っていると、攻撃に対して無防備な状態になったり、権限を昇格して横方向の移動を簡単に実行できる状態になったりする可能性があります。
ベンチマーク、ベストプラクティス、強化ガイドは、誤った構成の特定方法、それが問題となる理由、および修正方法についての情報を提供します。さまざまな情報源の中で、インターネット セキュリティ センター (CIS) は最も重要です。これは、さまざまな環境向けの無料ベンチマークを公開している非営利団体で、個人や企業が知識を共有できます。セキュリティ ベンチマークの事実上の標準となっています。
コンテナセキュリティに関するこのような設定を確認する最良の方法は、可能な限り自動化することです。これを実現するためのツールはいくつか存在し、主に静的な構成分析に基づいており、さまざまなレベルで構成パラメータを確認し、それらを修正するためのガイダンスを提供します。Sysdig Secureには、CISベンチマークやPCI DSS、SOC 2、NIST 800-53、NIST 800-190、HIPAA、ISO 27001、GDPRなどのコンプライアンス基準に基づいて、Linuxホスト、Docker、Kubernetes、EKS、GKE、AKS、MKE、OpenShiftクラスターなど、インフラ全体をスケジュール、実行、分析できるコンプライアンス機能が含まれており、すべてを単一の中央ダッシュボードで管理できます

使用できる他のツールとしては、linux-bench、docker-bench、kube-bench、kube-hunter、kube-striker、Cloud Custodian、OVAL、OS Queryなどがあります。
ホストベンチマークコントロールの例
Linux をインストールしたばかりの物理マシン、クラウドプロバイダーでプロビジョニングされた仮想マシン、またはオンプレミスには、知らないうちに安全でない設定がいくつか含まれている可能性があります。長期間使用したり、本番環境のワークロードを実行したり、インターネットに公開したりする場合は、特別な注意が必要です。これは、Kubernetes ノードや OpenShift ノードにも当てはまります。結局のところ、これらは仮想マシンです。クラウド プロバイダーによってプロビジョニングされたクラスターを使用している場合、完全に安全であると想定しないでください。
CIS には、ディストリビューションに依存しない Linux 用のベンチマークがあり、Debian、CentOS、Red Hat、その他多くのディストリビューション専用のベンチマークもあります。
検出できる誤った構成の例:
Linuxディストリビューションの例
次の図は、CIS Benchmark for Distribution Independent Linuxrsh
によって提供されており、サーバーが有効になっていないことを確認するための構成です。
次の図は、CISベンチマークが提供するディストリビューションに依存しないLinux向けのものです。この設定は、 rsh
サーバーが有効になっていないことを確認するためのものです。


コンテナランタイムを保護するためのベンチマークコントロールの例
自分で所有するサーバーに Docker などのコンテナランタイムをインストールする場合は、ベンチマークを使用して、デフォルトの安全でない構成が修正されていることを確認することが不可欠です。次の図は、Docker クライアントコマンドの承認が有効になっていることを確認するための構成を示しています。


オーケストレーターベンチマークコントロールの例
Kubernetes では、デフォルトで多くの認証メカニズムがサードパーティの統合によって管理されるようになっています。ベンチマークにより、考えられるすべてのセキュリティ上の問題に対処できるようになります。下の画像は、–anonymous-auth引数が false に設定されていることを確認するための構成を示しています。


クラウドベンチマークコントロールの例
クラウド プロバイダー アカウントのベンチマークは、クラウド セキュリティ ポスチャ管理( CSPM ) とも呼ばれ、アカウントのすべての資産のセキュリティをチェックするため不可欠です。攻撃につながる可能性のあるすべての設定、非公開であるべきが公開されているリソース (S3 バケットなど)、暗号化されていないストレージは、この種のベンチマークで定義されます。クラウド アカウントの資産は常に変化し、すべてが可能な限り安全であることを常に監視する必要があるため、これは自動化が不可欠なベンチマークです。次の画像は、90 日以上使用されていない資格情報が無効になっていることを確認する構成チェックの例です。



6. IaCスキャンとポリシーをコードとして組み込む
クラウド リソース管理は複雑なタスクですが、Terraform や CloudFormation などのツールは、この負担を軽減するのに役立ちます。インフラストラクチャーはコードとして宣言され(「Infrastructure as Code」とも呼ばれます)、リポジトリに保存され、バージョン管理されます。自動化によって定義の変更が適用され、既存のインフラストラクチャーが宣言に合わせて最新の状態に保たれます。
インフラストラクチャーをコードとして(IaC)使用している場合は、インフラが作成または更新される前にその構成を検証するため、IaCスキャン機能を備えたツールを組み込みましょう。その他のリンティングツールと同様に、IaCスキャンツールをローカル環境やパイプラインで適用し、セキュリティ問題を引き起こす変更をブロックすることを検討してください。
ポリシーをコードとして扱う「Policy as Code」は、セキュリティやインフラストラクチャーなどを管理するためのポリシーをコードで定義・管理するアプローチです。このアプローチを利用することで、IaCやKubernetes環境全体にわたってコンプライアンスとガバナンスを自動化し、組織全体でスケーラビリティと一貫性を確保することが可能です。
Sysdigは、TerraformやHelm、YAMLファイルなどのIaCツールにわたる構成ミスをスキャンし、それらをソースにマッピングするIaCセキュリティ機能を提供します。また、OSSのポリシー管理標準であるOPAを活用して、複数のIaCソースやKubernetesクラスターにわたって一貫したポリシーの適用を強制することもできます。

7. ホストスキャンでホストを保護する
ホストのセキュリティ保護は、コンテナのセキュリティ保護と同じくらい重要です。コンテナが実行されるホストは、通常、Linux カーネル、一連のライブラリ、コンテナランタイム、およびバックグラウンドで実行されるその他の一般的なサービスとヘルパーを備えたオペレーティングシステムで構成されます。これらのコンポーネントはいずれも脆弱であったり、構成が誤っていたりする可能性があり、実行中のコンテナにアクセスするためのエントリポイントとして使用されたり、サービス拒否攻撃を引き起こしたりする可能性があります。
たとえば、コンテナ ランタイム自体の問題により、ホストでの新しいコンテナの作成を妨げるこの DoS 攻撃のように、実行中のコンテナに影響を及ぼす可能性があります。
「安全でない構成」セクションで、ホスト構成の強化についてすでに説明しました。しかし、脆弱なコンポーネントをどのように検出するのでしょうか?ホストスキャンツールは、カーネル、glibc などの標準ライブラリ、サービス、さらにはホスト内にあるコンテナ ランタイムの既知の脆弱性を検出できます (コンテナ イメージに対するイメージスキャンの機能と非常に似ています)。
Sysdig はホストを透過的にスキャンし、見つかった脆弱性を報告します。次の図は、ダッシュボードで一目でリスクを検出するのがいかに簡単かを示しています。

この情報を使用して、オペレーティングシステム、カーネル、パッケージなどを更新します。最も重大で悪用される可能性のある脆弱性を排除するか、少なくともそれらを認識し、ファイアウォール、ホストへのユーザー アクセスの制限、使用されていないサービスの停止などの他の保護メカニズムを適用します。
8. 安全でないコンテナの実行を防ぐ
最後の防衛線として、Kubernetes アドミッションコントローラー は安全でないコンテナがクラスター内で実行されるのをブロックできます。前述のイメージスキャンのベストプラクティスでこの問題を軽減できますが、デプロイするすべてのものが CI/CD パイプラインまたは既知のレジストリを通過するわけではありません。サードパーティのイメージや手動のデプロイもあります。たとえば、急いでいるときにプロトコルをスキップして手動デプロイを実行したり、クラスターにアクセスできる攻撃者がイメージ スキャナーをスキップしてイメージをデプロイしたりする可能性があります。
アドミッションコントローラーを使用すると、ポッドの仕様 (アノテーションの適用、特権ポッドの検出、ホストパスの使用など) とクラスターのステータス (クラスター内のすべてのイングレスホストが一意であることを要求するなど) に基づいて、コンテナを受け入れるかブロックするかのポリシーを定義できます。
保護 – コンテナを安全に実行する
ランタイムにビルド時や設定時のコンテナセキュリティのベストプラクティスに従っても、コンテナが100%安全になるわけではありません。コンテナの新たな脆弱性は日々発見されており、今日安全なコンテナも、明日には新たに公開されたエクスプロイトの潜在的な被害者となる可能性があります。
このセクションでは、コンテナ脆弱性管理と保護対策をワークロードに含めるためのコンテナセキュリティのベストプラクティスを紹介します。
9. リソースを保護する
コンテナとホストには脆弱性が含まれている可能性があり、新しい脆弱性が継続的に発見されています。ただし、危険なのはホストまたはコンテナの脆弱性自体ではなく、攻撃ベクトルと悪用可能性です。
たとえば、実行中のコンテナや脆弱なサービスへの接続を阻止することで、ネットワークの悪用可能な脆弱性から保護できます。また、攻撃ベクトルにホストへのローカル アクセス (ホストにログインしていること) が必要な場合は、そのホストへのアクセスを制限できます。
したがって、ホスト、クラウドアカウント、リソースにアクセスできるユーザーの数を制限し、さまざまなメカニズムを使用して不要なネットワークトラフィックをブロックします。
- クラウド プロバイダーの VPC、セキュリティ グループ、ネットワークルール、ファイアウォールルールなどにより、VM、VPC、インターネット間の通信を制限します。
- ホストレベルのファイアウォールにより、必要なサービスの最小限のセットのみが公開します。
- クラスターにおけるKubernetes ネットワークポリシーや、サービスメッシュや API ゲートウェイなどの追加ツールを使用すると、ネットワーク要求をフィルタリングするための追加のセキュリティ レイヤーを追加できます。
10. イメージの署名を検証する
”イメージコンテンツの信頼性”で説明したように、イメージ署名はイメージが改ざんされていないことを保証する保護メカニズムです。イメージ署名を検証することで、タグが発行者によって署名された特定のダイジェストに対応していることを保証し、タグの可変性による一部の攻撃を防ぐこともできます。下の図は、この攻撃の例を示しています。

11. 実行時にコンテナ権限を制限する
コンテナ内の脆弱性が悪用された場合の範囲または「影響範囲」は、コンテナの権限と、ホストや他のリソースからの分離レベルに大きく依存します。ランタイム構成により、既存および将来の脆弱性の影響を次の方法で軽減できます。
- 有効なユーザー: コンテナをrootとして実行しないでください。さらに良い方法は、ホスト内の実際のユーザーにマップされないランダム化された UID (Openshift など) を使用するか、準備ができたらDocker とKubernetesのユーザーネームスペース機能を使用することです(公開時点では利用できません)。
- コンテナ権限の制限: Docker とKubernetesは、権限を削除し、権限付きコンテナを許可しない方法を提供します。SeccompとAppArmor は、コンテナが実行できるアクションの範囲にさらに制限を追加できます。
- リソースリミットを追加する: コンテナがすべてのメモリまたは CPU を消費し、他のアプリケーションが不足するのを防ぎます。
- 共有ストレージやボリュームには注意してください。具体的には、hostPathや、ホストからのファイルシステムの共有などです。
- hostNetwork、hostPID、hostIPCなどのその他のオプション: Kubernetes はコンテナがホストとネームスペースを共有するようにし、分離を減らします。
- ポッドセキュリティ標準(PSS) とセキュリティコンテキスト制約(Openshift の SCC)を定義する: クラスターにガードレールを設定し、コンテナの構成ミスを防止します。PSS と SCC は、セキュリティコンテキストが定義されたポリシーに準拠していない場合にポッドを拒否するアドミッションコントローラーです。
12. コンテナの脆弱性を賢く管理する
脆弱性を賢く管理し、評価してください。すべての脆弱性に修正プログラムが用意されているわけではなく、簡単に適用できる場合もあります。
ただし、それらのすべてが簡単に悪用できるわけではなく、悪用するにはホストへのローカルアクセスまたは物理的なアクセスが必要になる場合もあります。
次のような優れた戦略が必要です。
- 修正が必要なものを優先する:実行時に使用されているホストとコンテナの脆弱性に重点を置く必要があります。実稼働環境にない脆弱性に対処すると、実際に組織を危険にさらす脆弱性に費やすことができる貴重な時間が無駄になります。また、アクティブなエクスプロイトがない脆弱性は、悪意のある攻撃者によって悪用されている脆弱性よりもリスクが低くなります。重大または重大度の高い脆弱性のうち、修正プログラムが用意され、アクティブなエクスプロイトがあり、実稼働環境で使用されているのはわずか 1%です。これらの最もリスクの高い脆弱性を優先すると、重要なリスクに対処しながら大幅に時間を節約できます。
- コンテナとホストを保護するための対策として修正を適用する計画を立てます。チケットを作成して追跡し、脆弱性管理を標準の開発ワークフローの一部にします。
- 影響を受けないと結論付けた場合は、脆弱性の例外を作成します。これにより、ノイズが減ります。例外を永続的に追加する代わりにスヌーズすることを検討して、後で再評価できるようにします。
戦略は、コンテナ脆弱性スキャナーがいくつかの基準に従って検出された脆弱性に対してアラートをトリガーし、次のようなさまざまなレベルで防止と保護を適用するために使用できるポリシーに変換する必要があります。
- チケット発行: 検出された脆弱性を開発者に通知し、修正を適用できるようにします。
- イメージレジストリ: 脆弱なイメージがプルされるのを一切防止します。
- ホスト/カーネル/コンテナ: 実行中のコンテナをブロックし、追加の保護手段を追加するか、重大な問題が発生した場合にホストまたはコンテナを強制終了、隔離、またはシャットダウンして対応します。
実行中のコンテナに適用される新しい脆弱性が発見されたときにアラートを受け取るようにするには、継続的な脆弱性スキャンと再評価を実行することも重要です。Sysdig Secure は、脆弱性フィードが更新されるたびにスキャンポリシーを再評価するため、この点で役立ちます。
検知 – 異常な振る舞いに対するアラート
これまで、私たちは予防と保護、コンテナを可能な限り最良の状態で稼働させること、潜在的および既知の攻撃を予測することに重点を置いてきました。コンテナを構築、配布、実行する際に適切な権限と保護を適用し、基盤となるスタックを確保することで、攻撃者が実行できるアクションの範囲を制限できます。しかし、それはコンテナの実行を忘れて、適用されたセキュリティ対策を信頼してよいという意味ではありません。セキュリティ対策が実行されると、攻撃を受ける可能性があります。セキュリティインシデントが再発しないように修正措置を講じるためには、アプリケーションの異常な振る舞いや予期しない動作を検知する必要があります。
さまざまな攻撃ベクトルが存在します。たとえば、MITRE ATT&CK は「現実世界の観察に基づく」戦術と手法の広範なリストを提供しており、これを使用して予防策を適用したり、アクティビティを分析して攻撃や侵入が行われている可能性がある異常な振る舞いを検知したりできます。MITRE ATT&CK Matrix for Containers は、コンテナ技術を特に対象とした手法をカバーしています。

13. リアルタイムイベントとログ監査を設定する
コンテナセキュリティに対する脅威は、ログとイベントのさまざまなソースを監査し、異常なアクティビティを分析することで検出できます。イベントのソースには次のものがあります。
- ホストとKubernetesのログ
- クラウド ログ (AWS の CloudTrail、GCP の Activity Audit など)
- コンテナ内のシステムコール
Falco は、実行されたシステムコールを監視し、疑わしいアクティビティに対してアラートを生成することができます。コミュニティが提供したルールのライブラリが含まれており、簡単な構文を使用して独自のルールを作成することもできます。Kubernetes 監査ログもサポートされています。
Falcoの実際の動作例については、MITRE ATT&CK の検出に関する記事をご覧ください。
Sysdig Secure は Falco の機能を拡張し、さまざまなクラウド プロバイダーからのイベントを取り込むこともできます。
たとえば、次のルールは、アカウントで新しい ECS タスクが実行されるたびにアラートをトリガーします。
rule: ECS Task Run or Started
condition: aws.eventSource="ecs.amazonaws.com" and (aws.eventName="RunTask" or aws.eventName="StartTask") and not aws.errorCode exists
output: A new task has been started in ECS (requesting user=%aws.user, requesting IP=%aws.sourceIP, AWS region=%aws.region, cluster=%jevt.value[/requestParameters/cluster], task definition=%aws.ecs.taskDefinition)
source: aws_cloudtrail
description: Detect a new task is started in ECS.
Sysdig には、対応するコンプライアンス標準とコントロールがタグ付けされたルールのセットも含まれており、インフラストラクチャー内のすべてのセキュリティ イベントを調査するためのダッシュボードも提供されます。

インシデント対応とフォレンジック
システムでセキュリティ インシデントが発生していることを検出したら、脅威を阻止し、さらなる被害を最小限に抑えるための措置を講じてください。コンテナを強制終了したり、ホストをシャットダウンするだけでなく、隔離、一時停止、スナップショットの取得を検討してください。適切なフォレンジック分析により、多くの手がかりが得られ、何が、いつ、どのように発生したかが明らかになります。次の点を特定することが重要です。
- セキュリティインシデントが実際の攻撃であったか、それとも単なるコンポーネントの不具合であったか。
- 正確には何が起こったのか、どこで発生したのか、また、影響を受ける可能性のある他のコンポーネントはあるのでしょうか?
- セキュリティインシデントの再発を防ぐにはどうすればよいでしょうか?
14. 隔離して調査する
セキュリティ インシデントが検出された場合は、まずそれをすぐに停止して、さらなる被害を最小限に抑える必要があります。
- 停止してスナップショットを作成する: 可能な場合は、ホストまたはコンテナを分離します。コンテナランタイムのオプションは、コンテナを「一時停止」するか (つまり、「docker pause」コマンド)、スナップショットを作成してから停止することです。ホストの場合は、ファイルシステムレベルでスナップショットを作成してからシャットダウンします。EC2 または VM インスタンスの場合は、インスタンスのスナップショットを作成することもできます。次に、分離に進みます。ネットワークなしでスナップショットを安全なサンドボックス環境にコピーし、ホストまたはコンテナを再開できます。
- 探索とフォレンジック: 分離したら、稼働中のコンテナまたはホストを探索し、実行中のプロセスを調査できます。ホストまたはコンテナが稼働していない場合は、ファイルシステムのスナップショットに集中できます。ログと変更されたファイルを探索します。Sysdig Secure キャプチャなどのツールは、イベント周辺のすべてのシステム コールを記録し、コンテナまたはホストが停止した後でも探索できるようにすることで、フォレンジック機能を大幅に強化します。
- 最後の手段として、侵害されたコンテナやホストを強制終了する: 疑わしいアクティビティを単に破壊するだけで、短期的にはそれ以上の被害を防ぐことができます。しかし、何が起こったかの詳細がわからないと、再発を防ぐことが不可能になり、次の攻撃が起こるのを何度も待って再び強制終了するという、終わりのないモグラ叩きの状況に陥る可能性があります。
15. 誤った設定を修正する
調査により、攻撃を可能にした原因が明らかになるはずです。攻撃元を発見したら、再発防止のためのセキュリティ対策を講じてください。ホスト、コンテナ、またはアプリケーションが侵害される原因は、過剰な権限、公開されたポートやサービス、または悪用された脆弱性などの不適切な構成である可能性があります。
前者の場合、誤った構成を修正して、再発を防ぎます。後者の場合、ファイアウォールなどの構成を変更したり、より制限の厳しいユーザーを使用したり、追加の権限や ACL でファイルやディレクトリを保護したりすることで、脆弱性が悪用されるのを防ぐ (または少なくともその範囲を制限する) ことができる可能性があります。
問題が環境内の他の資産にも当てはまる場合は、それらすべてに修正を適用します。リモートネットワーク接続を介してエクスプロイトが実行される可能性がある場合、インターネットからアクセスできるアプリケーションなど、公開される可能性のある資産に修正を適用することが特に重要です。
16. 脆弱性を修正する
可能であれば、脆弱性自体を修正します。
- オペレーティングシステムパッケージ (dpkg、rpm など) の場合: まず、ディストリビューションベンダーが修正を含むパッケージの更新バージョンを提供しているかどうかを確認します。パッケージまたはコンテナベースイメージを更新するだけです。
- 古いディストリビューションバージョン: ベンダーは更新バージョンとセキュリティ修正プログラムの提供を停止します。手遅れになる前に、ホストとイメージをサポートされているバージョンに保ってください。
- NodeJS、Go、Java などの言語パッケージの場合: 依存関係の更新バージョンを確認します。大規模なバージョン更新で発生する可能性のある重大な変更の計画とテストに追加の時間を費やすことができない場合は、セキュリティ問題を修正するだけのマイナー更新またはパッチ バージョンを検索します。ただし、事前に計画を立ててください。古いバージョンは永久に維持されるわけではありません。
- ディストリビューションがパッチを適用したバージョンを提供していない場合、またはメンテナンスされていないパッケージに修正がない場合: 修正が存在し、手動で適用またはバックポートできる可能性があります。これには追加の作業が必要になりますが、システムにとって重要なパッケージや、まだ公式の修正バージョンがない場合には必要になることがあります。NVD などのデータベース、ベンダー フィードとソース、バグ レポートの公開情報などの脆弱性リンクを確認してください。修正が利用可能な場合は、それを見つけることができるはずです。
影響を受けるパッケージに適用できる修正プログラムがない場合でも、構成や保護手段 (ファイアウォール、分離など) によって脆弱性の悪用を阻止できる可能性があります。また、複雑で脆弱性に関する深い知識が必要になる場合もありますが、独自のコードに追加のチェックを追加できます。たとえば、Web API サーバーで使用される JSON 処理ライブラリのオーバーフローによって発生する脆弱性は、HTTP 要求レベルでいくつかのチェックを追加し、オーバーフローにつながる可能性のある文字列を含む要求をブロックすることで防止できます。
17. ループを閉じる
残念ながら、ホストとコンテナのセキュリティは、コンテナのセキュリティに関する一連のベストプラクティスを一度適用して、その後は忘れてしまえるような一方通行ではありません。ソフトウェアとインフラストラクチャーは日々進化しており、複雑さが増し、新しいエラーが発生します。これにより、脆弱性や構成の問題が発生します。新しい攻撃やエクスプロイトが継続的に発見されます。
まず、予防とセキュリティのベストプラクティスを取り入れます。次に、リソース (主にホストとワークロード、クラウド サービス) に保護対策を適用します。異常な振る舞いの監視と検知を継続して、発見されたインシデントに対してアクションを実行し、対応、調査、報告を行います。フォレンジックの証拠によってループが閉じられます。つまり、発見された脆弱性を修正して保護を強化し、もう一度やり直し、イメージを再ビルドし、パッケージを更新し、リソースを再構成し、将来のセキュリティ インシデントに対するインシデント レポートを作成します。
中間段階では、リスクを評価し、脆弱性を管理する必要があります。複雑で大規模な環境では、管理する入力の数が膨大になる可能性があるため、分類して優先順位を付け、最もリスクの高いものに最初に焦点を合わせます。

まとめ
コンテナ セキュリティのベスト プラクティスを DevOps ワークフローに簡単に適用する方法を確認しました。特に、次の点に注意してください。
- セキュリティをシフトレフトさせます。最初のステップは予防です。
- すべての資産を保護します。
- 組織内で発生するすべての事象を把握し、問題をできるだけ早く監視および検知します。
- 攻撃は避けられないため、インシデント対応を計画してください。
コンテナセキュリティのベストプラクティスには、配信されるアプリケーションやコンテナイメージ自体だけが含まれるわけではないことに注意してください。コンテナのビルド、配布、および具体的な実行に使用される完全なコンポーネントスタックも含める必要があります。
コンテナの 70% は5 分以下しか存続しないため、異常な振る舞いや侵害の調査は非常に困難になります。
クラウドネイティブセキュリティの重要なポイントの 1 つは、コンテナセキュリティリスクにできるだけ早く対処することです。開発ライフサイクルの後半でこれを実行すると、クラウド導入のペースが遅くなり、セキュリティとコンプライアンスのリスクが高まります。