Google Cloudとコンテナの継続的なセキュリティ
本文の内容は、2023年7月4日にNIGEL DOUGLAS が投稿したブログ(https://sysdig.com/blog/cloud-defense-in-depth/)を元に日本語に翻訳・再構成した内容となっております。
継続的なデータ漏洩や深刻化するサイバー脅威に直面する中、企業はクラウドの徹底的な防御を優先せざるを得なくなっています。これらの対策は、重要な資産を保護し、クラウドベースのシステムの完全性を維持するために不可欠です。包括的なセキュリティ計画を策定することで、企業はセキュリティに対するコミットメントを効果的に伝え、弾力的で安全なクラウド環境のための強固な基盤を築くことができます。
このブログポストでは、Kubernetes内でKinsingのようなマルウェアの横方向の動きを緩和する上で極めて重要な役割を果たす、オープンソースのクラウドネイティブなツールが提供する深い強みと汎用性について掘り下げていきます。この種のマルウェアは、クラウド環境で動作するデータベースにとって重大な脅威となります。ここでは、最近の攻撃パターンとしてKinsingに焦点を当てていますが、ここで説明する原則は、クラウドネイティブなアプリケーションを標的とする他のタイプのマルウェアにも流用できます。
クラウドセキュリティをさらに強化するために、組織は多層防御の概念を取り入れる必要があります。クラウドの多層防御は、サプライチェーンセキュリティやホスト/ワークロード・ランタイムセキュリティといった一般的な制約を超えて拡張されます。これは、組織のクラウドインフラストラクチャー全体にわたって、複数のレイヤーのセキュリティコントロールをプロアクティブに実装することです。
シフト・レフトとシールド・ライトの方法論は、組織がクラウドセキュリティを強化するために採用できる強力なプラクティスとして登場しました。シフト・レフトは、開発プロセスの早い段階でセキュリティの考慮事項をインテグレーションすることに重きを置く事で、開発者が脆弱性を特定し、その根源に対処できるようにします。静的コード解析、脆弱性スキャン、セキュアコーディングガイドラインなどのセキュリティツールやプラクティスを取り入れることで、企業は潜在的なリスクがアプリケーション全体に伝播する前に、プロアクティブに排除することができます。
一方、シールド・ライトは、アプリケーションライフサイクルにおける実行時および運用段階におけるセキュリ ティ管理と保護の実装に重きを置いています。これにより、攻撃や悪意のある活動からアプリケーションを保護するための強固なセキュリティ対策が確保されます。一般的なコンテナ・オーケストレーション・プラットフォームであるKubernetesは、シールド・ライトの手法において重要な役割を果たしています。Kubernetesは、役割ベースのアクセス制御(RBAC)、Kubernetesネットワークポリシー(KNP)、Falcoを介したランタイム監視などの機能を活用することで、組織がコンテナ化されたアプリケーションを安全に保護することを可能にします。
クラウドネイティブのワークロードをセキュアにするためのエンドツーエンドの検知の必要性を正当化する攻撃シナリオについて説明して行きましょう。このインシデントは、コンテナ・イメージの脆弱性を悪用するKinsingマルウェアに関連しており、設定を誤るとPostgreSQLコンテナが公開され、Kubernetesクラスターに侵入されます。Kinsingは、クリプトマイニングのためにコンテナ化された環境を標的にした歴史を持つLinuxマルウェアで、侵害されたサーバー・リソースを利用して脅威行為者に不正な利益をもたらします。
Kinsingマルウェアに馴染みがない場合は、この種の攻撃を理解するためのブログを参照ください。Kinsingの背後にいるオペレーターは、Log4Shellのような有名な脆弱性を悪用することで有名です。
彼らの目的は、オンプレミスかクラウドかを問わず、2つの標準的なオプションを悪用してLinuxサーバーに初期アクセスすることです。3 番目のポイントでは、クラウド環境への横方向の移動のための潜在的な手法を概説します。
1. 誤設定された PostgreSQL データベースにおけるリスクの軽減
2. 脆弱なコンテナイメージのリスク軽減
3. クラウドへの横の動きの抑制
イメージの脆弱性を悪用する場合、脅威者はペイロードをプッシュできるリモートコード実行の欠陥を探します。前の図で示したように、潜在的に脆弱なイメージの脆弱性スキャンやネットワーク セキュリティの強化など、適用できる軽減戦略がいくつかあります。それぞれについて、オープンソース、クラウドネイティブテクノロジーのコンテキストで説明していきましょう。
コンテナイメージに既知のレジストリを使用することは、環境内で使用されるイメージの完全性とセキュリティを確保するのに役立つため、データベースの侵害を回避するためにとても重要です。信頼できる評判の高いレジストリからコンテナ・イメージを取得すれば、そのイメージの信頼性と品質に高い信頼を持つことができます。
既知のレジストリは、イメージスキャン、脆弱性検出、アクセスコントロールなどのセキュリティ対策を確立していることが多く、危険なイメージや悪意のあるイメージを展開するリスクを軽減するのに役立ちます。Trivyのようなオープンソースツールを活用することで、既知のレジストリの使用を強制し、イメージスキャンを実行して脆弱性やセキュリティ上の問題を特定することができます。
以下の例では、Dockerイメージをスキャンし、既知のレジストリを強制することができます:
trivy image --only-fixed-versions --clear-cache --exit-code 1 docker.io/postgresql:latest
Code language: PHP (php)
あるいは、Docker Content Trust(DCT)のようなツールは、コンテナイメージの完全性と真正性を保証するためのイメージ署名と検証メカニズムを提供しています。既知のレジストリからの署名付きイメージの使用を強制するポリシーを設定できます。これは、信頼できるリポジトリと関連するキーのリストを含むnotary configuration file(notary-config.json)を作成することで実現できます。
{
"trust_dir": "~/.docker/trust",
"remote_server": {
"url": "https://notary.example.com",
"root_ca": "/path/to/root-ca.crt"
},
"repositories": {
"docker.io/library": {
"default": {
"signing_keys": [
{
"key_id": "<your-key-id>",
"key_path": "~/.docker/trust/private/<keyname>.key"
}
]
...
Code language: JSON / JSON with Comments (json)
設定ミスのあるデータベース・サーバーを特定できなかったと仮定した場合や、最小特権を原則としたネットワーク制御を実施していない本番環境にデータベースをプッシュする前に、パッチの適用が間に合わなかった時などを想定した場合、実行中のデータベースワークロードからペイロードのデプロイメントを検出できることが重要です。
- rule: DB program spawned process
desc: >
a database-server related program spawned a new process other than itself.
This shouldn\'t occur and is a follow on from some SQL injection attacks.
condition: >
proc.pname in (db_server_binaries)
and spawned_process
and not proc.name in (db_server_binaries)
and not postgres_running_wal_e
and not user_known_db_spawned_processes
output: >
Database-related program spawned process other than itself (user=%user.name user_loginuid=%user.loginuid
program=%proc.cmdline pid=%proc.pid parent=%proc.pname container_id=%container.id image=%container.image.repository)
priority: NOTICE
tags: [host, container, process, database, mitre_execution, T1190]
Code language: PHP (php)
Falcoによる検出ルールにより、侵害されたPostgreSQLデータベースがそれ自身以外のプロセスを生成するインスタンスを特定できることが明らかになりました。これは、Kinsingマルウェアに関連する侵害、あるいはデータベースに対する潜在的なSQLインジェクション攻撃の明らかな兆候です。
CI/CDパイプラインでイメージの脆弱性をスキャンすることと、既知のレジストリからの出所を確認することは、見落としてはならない2つの重要なプラクティスです。しかしながら、脆弱性を特定するために今現在使われているコンテナをランタイム時にスキャンすることは軽視されがちです。
PostgreSQLデータベースの脆弱性ステータスを評価するには、オープンソースツールのAnchore Engineを強く推奨します。Anchore Engine は、実行中のコンテナに特化して設計された広範なイメージスキャン機能と脆弱性分析を提供し、PostgreSQL データベースのセキュリティ体制に関する貴重な洞察を提供します。
Docker を使ってスキャンしたいコンテナイメージをプルします:docker pull postgresql:latest
次に、Anchore Engine を使用して、プルされたイメージをスキャンすることができます。'add'アクションは、Anchore Engineにコンテナイメージを追加して分析するために使用します。一方、'wait' アクションは、文字通り、特定のイメージの解析が完了するのを待ちます。最後に、'content' コマンドは、イメージの内容に関する詳細情報を取得します。
docker run -e ANCHORE_CLI_URL=http://<anchore-engine-host>:8228/v1 --rm anchore/anchore-cli image add postgresql:latest
docker run -e ANCHORE_CLI_URL=http://<anchore-engine-host>:8228/v1 --rm anchore/anchore-cli image wait postgresql:latest
docker run -e ANCHORE_CLI_URL=http://<anchore-engine-host>:8228/v1 --rm anchore/anchore-cli image content postgresql:latest
Code language: HTML, XML (xml)
もちろん、 をあなたの Anchore Engine インスタンスのホスト名または IP アドレスに置き換える必要があります。これを実行すると、Anchore Engine はイメージを解析し、イメージのパッケージや依存関係から見つかった脆弱性に関する情報を含む、詳細な脆弱性レポートを提供します。これにより、実行中のコンテナ型データベースが Kinsing マルウェアによって侵害される可能性があるかどうかが確認されます。
Kubernetesでデータベースの堅牢なパッチ管理戦略を持つことは、コンテナのロールアウト・プロセスにもかかわらず、依然として極めて重要です。コンテナは分離とカプセル化を提供しますが、データベース・ソフトウェアを含むコンテナ・イメージ内には依然として脆弱性が存在する可能性があります。そのため、セキュリティの脆弱性に対処し、潜在的な悪用から保護された状態を維持するために、データベースを定期的に更新し、パッチを適用することが不可欠です。
しかし、Kubernetesではコンテナのデプロイメントが動的かつ自動化されているため、手動パッチ適用だけに頼っていては不十分な場合があります。そこで、Gatekeeperのようなツールの出番となります。Gatekeeperを活用することで、CVE(Common Vulnerabilities and Exposures)スコアが不合格となったコンテナを拒否するポリシーを適用し、許容できるセキュリティレベルのコンテナのみがデプロイされるようにすることができます。
このプロアクティブなアプローチは、パッチ管理戦略を補完し、コンテナ化されたデータベースの潜在的なセキュリティリスクに対する防御の追加レイヤーを提供します。OPA Gatekeeper を使用して実行時に既知の CVE を拒否するには、特定の脆弱性をチェックし、その脆弱性を持つリソー スのデプロイメントを制限するポリシーを定義します。これらのポリシーは、OPA で使用されるポリシー言語である Rego 言語を使用して記述できます。
package kubernetes.cve_rejection
deny[msg] {
input.kind == "Deployment"
input.apiVersion == "apps/v1"
input.metadata.labels.app == "postgresql"
input.spec.template.spec.containers[_].image == "vulnerable-image:latest"
msg = "Deployment of my-app with vulnerable image is not allowed."
}
Code language: JavaScript (javascript)
この例では、ポリシーは、イメージ vulnerable-image:latest
を使用している app: postgresql
というラベルのデプロイメントリソースが作成されているかどうかをチェックします。そのようなデプロイメントが検出された場合、ポリシーがトリガーとなり、対応するエラーメッセージとともに拒否します。
Gatekeeper は、ポリシーを定義する ConstraintTemplate マニフェストを作成し、特定のリソースに適用される制約を作成するために使用できます。このようにOPA Gatekeeperを利用することで、特定の脆弱性基準に適合するカスタムポリシーを定義し適用することで、既知のCVEの実行時拒否を強制することができます。
コンテナイメージの悪用を防ぐには、主要なセキュリティ対策を実施することが不可欠である。これには、信頼認証の解除、ネットワークアクセスの保護、デフォルトユーザーの削除、厳格な RBAC 管理の実施などが含まれます。これらの対策を講じることで、コンテナ化されたデータベースのセキュリティを強化し、不正アクセスや潜在的な侵害のリスクを低減することができます。
これはPostgreSQLに対して、"サーバに接続できる人は誰でもデータベースへのアクセスが許可されている "と仮定するように指示するものです。可能であれば、この設定を無効にすることを強く推奨します。
PostgreSQLの認証設定とセキュリティポリシーの適用を支援するオープンソースツールにpgAuditがあります。このツールはPostgreSQLの詳細なロギングと監視機能を提供し、認証の試行やデータベースの活動をログに記録し分析する機能を含みます。
pgAudit を構成することで、認証パターンを把握し、不正なアクセスの試みを特定することができます。そして、Falco は Postgres データベースから不審なプロセスの活動を検出するように動作します。両者が連携することで、認証の動作とプロセスの動作に対処することができます。
もう1つの間違いは、攻撃者がサーバーへのアクセスを与えるために使用している可能性のあるあらゆるIPアドレスを含む、広すぎるIPアドレス範囲を割り当てることです。これは、Kubernetesネットワークポリシー、そして一般的なネットワークの可視性が、脆弱なイメージと誤った設定のPostgreSQLデータベースの両方に対して強く求められることを意味します。
攻撃は幅広いIPアドレスのスキャンから始まり、WordPressのような特定の一般的なウェブアプリケーションのデフォルトポートと一致するオープンポートを探します。このような場合の一般的なベストプラクティスは、IP許可リストを使用し、最小権限の原則に従うことで、公開されているコンテナへのアクセスを最小限に抑えることです。
デフォルトでは、Kubernetesクラスター内のすべてのポッドは、何の制限もなく相互に通信できます。Kubernetesネットワークポリシーは、マイクロサービスアプリケーションを互いに隔離して、影響範囲を制限し、全体的なセキュリティ体制を改善するのに役立ちます。
Kubernetes Network Policiesは、ワークロードを保護するための "最小特権 "ポリシーを生成することができます。PostgreSQLワークロードに許可したいポートとIPトラフィックを理解する必要があります。そうすることで、ワークロードが危険にさらされているかどうかに関係なく、期待しているものだけを許可できます。
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
Metadata:
name: postgresql-policy
Spec:
Selector:
matchLabels:
app: postgresql
Ingress:
- action: Allow
protocol: tcp
Source:
selector: app=app1
Destination:
Ports:
- 5432
Egress:
- action: Allow
protocol: tcp
Destination:
selector: app=frontend
Source:
Ports:
- 5432
上記のポリシーは、app: postgresqlとラベル付けされたPodを対象としています。このポリシーは、app: frontendとラベル付けされたPodからのポート5432(PostgreSQLのデフォルトポート)の ingress(受信)トラフィックのみを許可します。また、app: frontend とラベル付けされたポッドへのポート 5432 での egress(発信)トラフィックも許可します。
また、このネットワークポリシーは、PostgreSQLとフロントエンドのポッドをすでにデプロイし、それに応じてラベル付けしていることを前提としています。デプロイの構成に基づいてポリシーを調整する必要があります。
ネイティブのKubernetes Network Policiesは、すでにサポートされている(Container Networking Interface)CNI以外のネットワーク要件を追加する必要はありません。私たちが提供した例は、Calicoネットワークポリシーのものです。このセキュリティ目標を達成するために、Calico、Cilium、またはデフォルトの Network Policy 実装のいずれかを使用することができます。
2番目の "Default-Deny" ポリシーは、パケットパイプラインでまだ許可されていないすべてのトラフィックを確実にドロップするために必要です。これは、CoreDNS(UDPポート53)トラフィックをブロックから除外するクラスターのグローバルなデフォルト拒否ルールです。これが広すぎる場合は、ネットワークネームスペースレベルごとに"Default-Deny"を作成できます。
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
Metadata:
name: deny-app-policy
Spec:
namespaceSelector: has(projectcalico.org/name) && projectcalico.org/name not in {"kube-system"}
Types:
- Ingress
- Egress
Egress:
- action: Allow
protocol: UDP
Destination:
selector: 'k8s-app == "kube-dns"'
Ports:
- 53
Code language: JavaScript (javascript)
ネットワーク・ポリシーは確かに攻撃の範囲を狭めますが、最初の侵害には対処していません。そこで必要なのが、Falcoによるディープな侵入検知機能による徹底的な防御戦略です。パケットがドロップされた場合、その理由を知る必要があります。疑わしいネットワーク接続なのか?IPTablesはそれ自体ではこのようなコンテキストを与えてくれません:
- rule: Outbound or Inbound Traffic not to Authorized Server Process and Port
desc: Detects traffic that is not to an authorized server process and port.
condition: >
inbound_outbound and
container and
container.image.repository in (allowed_image) and
not proc.name in (authorized_server_binary) and
not fd.sport in (authorized_server_port)
enabled: false
output: >
Network connection outside authorized port and binary
(command=%proc.cmdline pid=%proc.pid connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id
image=%container.image.repository)
priority: WARNING
tags: [container, network, mitre_discovery, TA0011]
Code language: JavaScript (javascript)
デフォルトユーザは PostgreSQL データベースのセキュリティを強化する上で重要な役割を果たします。不正アクセスや潜在的なセキュリティ侵害のリスクを最小限にするためには、デフォルトユーザを削除することが重要です。デフォルトユーザは多くの場合、幅広い権限と既知の認証情報を持っており、攻撃者にとって魅力的なターゲットとなります。
しかし、Kubernetesできめ細かなRBAC制御を実施し、影響範囲を制限することも、同等かそれ以上に重要です。RBACを実装することで、個々のユーザーやサービスアカウントに特定のロールと権限を割り当てることができ、タスクの実行に必要な権限のみを確実に持たせることができます。
このようなきめ細かなRBAC制御を実施するのに役立つもう1つのオープンソースツールが、Kubernetes RBAC Managerです。これは、カスタムリソースを使用して宣言的にRBACポリシーを定義し、管理することを可能にします。
apiVersion: rbacmanager.reactiveops.io/v1beta1
kind: RBACDefinition
Metadata:
name: database-access
Spec:
Roles:
- name: database-reader
Rules:
- apiGroups: ["postgres.databases.io"]
resources: ["database"]
verbs: ["get", "list"]
- name: database-writer
Rules:
- apiGroups: ["postgres.databases.io"]
resources: ["database"]
verbs: ["get", "list", "create", "update", "delete"]
roleBindings:
- name: read-access-binding
Subjects:
- kind: User
name: nigel
roleName: database-reader
- name: write-access-binding
Subjects:
- kind: User
name: daniel
roleName: database-writer
Code language: JavaScript (javascript)
RBACは2つのロールを作成するために定義されます:
そして、RoleBindingsがロールを特定のユーザー(この場合はNigelとDaniel)に関連付けます。Kubernetes RBAC Managerを使用すると、許可されたユーザーのみがKubernetes内で必要なパーミッションを持つことを保証し、影響範囲を制限し、よりセキュアな環境を維持することができます。
ホストからのシステムコールイベントをリアルタイムで直接キャプチャーすることで、Falcoエージェントは迅速なアラートを可能にします。PostgreSQLデータベースがKinsingマルウェアの被害に遭った場合、このマルウェアが主にLinuxベースのシステムとDockerコンテナを標的にしていることに気をつけてください。通常、Kinsingマルウェアの目的はKubernetes内での被害であり、クラウドへの拡大ではありません。
しかし、Kubernetes環境が侵害された場合、敵がクラウドネイティブのワークロードからクラウドに進出するのをどのように防ぐことができるでしょうか?これは、KubernetesクラスターがAWS上のElastic Kubernetes Service(EKS)のようなクラウド上のマネージドサービスである場合に特に関連します。イメージパイプラインとコンテナランタイムだけでなく、クラウドネイティブなワークロードをホスティングするクラウドサービスもセキュアにする必要性があるため、これらの考慮事項はエンドツーエンドのセキュリティ計画に不可欠です。
危殆化したPostgreSQLデータベースからクラウドへの移動には、さらなる技術を活用し、クラウドインフラストラクチャーの脆弱性を悪用する必要があることは注目に値します。敵対者がKubernetesクラスターとPostgreSQLワークロードをホストするクラウドアカウントにアクセスするために通常取り得る一般的なシナリオを以下に示します:
これらすべては、PostgreSQL DB をホストしているホスト サーバー上で実行されることに注意してください。 したがって、Falco は、攻撃者がこれらのシステム上で秘密鍵や機密資格情報を検索しようとしているインスタンスを検出できます。
Kubernetesクラスターから秘密鍵やパスワードを盗もうとする試みにおいて、敵対者はクラスター内の様々なファイル、ログ、または設定データを検索するためにgrepコマンドを利用するかもしれません。正規表現を活用することで、秘密キーやパスワードに関連付けられたパターンを識別し、クラスターのリソースへの不正アクセスを許可し、環境全体のセキュリティを侵害する可能性のある機密情報を抽出できます。
- rule: Search Private Keys or Passwords
desc: Detects grep private keys or passwords activity.
condition: >
(spawned_process and
((grep_commands and private_key_or_password) or
(proc.name = "find" and (proc.args contains "id_rsa" or proc.args contains "id_dsa")))
)
output: >
Grep private keys or passwords activities found
(user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid container_id=%container.id container_name=%container.name
image=%container.image.repository:%container.image.tag)
Priority: WARNING
tags: [host, container, process, filesystem, mitre_credential_access, T1552.001]
Code language: PHP (php)
この種の動作に対するリアルタイムの検出機能がないと仮定すると、敵は、脆弱なアクセス制御、露出した管理インターフェース、パッチが適用されていないソフトウェアなど、検出されないままクラウドインフラストラクチャーの脆弱性を悪用する可能性があります。Kinsingはこれらの脆弱性を悪用して、クラウドインフラへの不正アクセスを試みるかもしれません。このため、リアルタイムの検知の必要性がさらに高まります。
検知機能をクラウドに拡張することは、Kubernetes環境の全体的なセキュリティを強化するために不可欠です。Kubernetesにおける流出の試みを、S3バケットの暗号化の不正削除など、クラウドにおける疑わしいアクティビティと関連付けることで、組織は潜在的なセキュリティインシデントを包括的に把握し、高度な攻撃パターンを検出することができます。
- rule: Delete Bucket Encryption
desc: Detects the deletion of configurations used to encrypt bucket storage.
Condition:
ct.name="DeleteBucketEncryption" and not ct.error exists
Output:
A encryption configuration for a bucket has been deleted
(requesting user=%ct.user,
requesting IP=%ct.srcip,
AWS region=%ct.region,
bucket=%s3.bucket)
priority: CRITICAL
source: aws_cloudtrail
Code language: JavaScript (javascript)
検知機能をクラウドに拡張することで、組織は、Kubernetesとクラウド環境の両方をカバーする全体的なクラウド多層防御セキュリティアプローチを確立し、新たな脅威に対するより強力な防御を確保し、データの流出や不正アクセスの可能性を低減することができます。
Kinsingマルウェア攻撃に関連するリスクを軽減するために、組織は、シフト・レフトのセキュリティプラクティスと堅牢な防御策を組み合わせた包括的なオープンソースアプローチを採用することができます。これには、パイプライン・フェーズで脆弱性のイメージスキャンを実装し、実行中のコンテナに潜在的なエクスプロイトがないか継続的に監視することが含まれます。
PostgreSQLのようなクラウドネイティブでコンテナ化されたワークロードに起因する攻撃が、Kubernetes内で伝播し、クラウドに拡大する可能性があることを認識することは極めて重要です。攻撃者のテクニックは時間の経過とともに進化するかもしれませんが、これらのベストプラクティスを順守することは、堅牢なセキュリティ計画を維持するための強固な基盤となります。
これらのガイドラインに従うことで、組織はセキュリティ対策の有効性に大きな自信を持つことができます。さらなる洞察については、Sysdigのウェビナーで、シフト・レフトとシールド・ライトの手法を組み合わせることの価値について、有益な情報を紹介しています:(https://go.sysdig.com/WebShiftCloudSecurityEMEA.html)