Tutorial  on  KubernetesSecurity

Adaptive Kubernetes Sovereign Security Operations Center

Multimessenger Security: An adaptive kubernetes souvereign SOC composed from Musketeers CNCF eBPF Projects

The linux kernel through eBPF offers to unify the disparate fields security and observability through shared data structures. We show how a K8s Security Operations Center, organically composed of established eBPF projects (CNCF Kubescape, Pixie and Tetragon) can see signals that the individuals cannot.

We explain how we achieve both a comprehensive baseline and use independent signals to dial up/down coverage as suspicious indicators surface. The mutual independence of signals from across processes, file system, and network activity achieves a high signal-to-noise, enabling manageable data volumes and facilitating selective forensic storage.

Pixie

An adaptive Kubernetes Sovereign Security Operations Center based on eBPF

Acknowledgement: This work is funded in part by Netidee grant 7918/2025

Lets deploy our composite eBPF SOC - uncompromised

1) the newest release of Kubescape

We first install the nodeagent component of CNCF Kubescape, with a specific config that defineds Kubescape's learning period and some exclusion rules.

cd /home/laborant
git clone https://github.com/k8sstormcenter/bob.git
cd bob
make kubescape

Install Kubescape Nodeagent

2) a custom version of Pixie

As the second component, we install a fork of CNCF Pixie and the Pixie Cli px. This fork has the special feature, that it can read and write from/to an external database.

cd /home/laborant
git clone https://github.com/k8sstormcenter/honeycluster.git
cd honeycluster

Install (a fork of) Pixie incl its SBoB

The below commands install a normal pixie and connect it to the UI, then glob-deploy the fork and the BoBs.

cd /home/laborant/honeycluster
./honeystack/pixie/pixie_vizier/sbob/bobapply.sh
export PX_CLOUD_ADDR=getcosmic.ai
px auth login
px deploy
./honeystack/pixie/pixie_vizier/sbob/bobapply.sh
kubectl apply -f honeystack/pixie/pixie_vizier/entlein_pixieNov3.yaml
./honeystack/pixie/pixie_vizier/sbob/bobapply.sh

3) a columnar database (Clickhouse) and log forwarding (Vector)

We now deploy the hyperDX chart for Clickhouse, this chart has lots of components which we dont use, but for the KubeConNA SecurityCon Talk, it is a perfect showcase.

cd ~/honeycluster
make  clickhouse vector

Install Clickhouse DB and enable log forwarding

Lets adaptively react

Now, our detection stack is all setup. Kubescape is evaluation the differences between an SBoB and the runtime behavior.

Now we infect our stack

We pretend our database stack has been supply chain compromised

cd /home/laborant/honeycluster
make update-clickhouse

so this "update" actually pulls in our rootkit

We mock compromise clickhouse app server

Story 1: Kubescape detects an anomaly

Extract the metadata from the "possibly infected" process

We look at all current anomalies (whatever diffs from the SBoB)

px run -f /home/laborant/honeycluster/analysis/px_clickhouse/kubescape/observe.pxl
laborant@dev-machine:honeycluster$ px run -f /home/laborant/honeycluster/analysis/px_clickhouse/kubescape/observe.pxl
Pixie CLI
*******************************
* ENV VARS
*        PX_CLOUD_ADDR=getcosmic.ai
*******************************
Table ID: kubescape_pods
  MESSAGE                                                                                         PODNAME                                             NAMESPACE  TIMESTAMP               
  Unexpected system call: chmod                                                                   hyperdx-hdx-oss-v2-otel-collector-64c698f998-87qf6  click      1.761668491518777e+18   
  Unexpected system call: mkdir                                                                   hyperdx-hdx-oss-v2-otel-collector-64c698f998-87qf6  click      1.7616684918184387e+18  
  Unexpected system call: select                                                                  hyperdx-hdx-oss-v2-mongodb-56dc967bcf-8kskr         click      1.7616685275085857e+18  
  Unexpected io_uring operation detected: Epoll control (opcode=29) flags=0x0 in next-server (v.  hyperdx-hdx-oss-v2-app-6bc79cdd9b-rqfwq             click      1.7616685188072218e+18  
  Unexpected io_uring operation detected: Epoll control (opcode=29) flags=0x0 in next-server (v.  hyperdx-hdx-oss-v2-app-6bc79cdd9b-rqfwq             click      1.7616685188072428e+18  
  Unexpected io_uring operation detected: Epoll control (opcode=29) flags=0x0 in next-server (v.  hyperdx-hdx-oss-v2-app-6bc79cdd9b-rqfwq             click      1.7616685188071826e+18  
  Unexpected system call: io_uring_register                                                       hyperdx-hdx-oss-v2-app-client-775864d696-fhb4m      click      1.7616690892466696e+18

Now we focus on the io_uring_register syscall , to understand if it s a legit software update or not.

 2025-10-19 16:13:3  {"alertName":"Unexpected system call","arguments":{"syscall":"io_uring_register"},"infectedPID":61910,"md5Hash":"8cb5d303c3f5643c6fdaa3c450b6c449","profileMetadata":{"error":{},"failOnProfile":true,"type":0},"severity":1,"sha1Hash":"a6a18998930a8aff2bd0f8e99fcf14d0d7bfd372","size":"4.6 MB","timestamp":"2025-10-19T16:13:30.389130871Z","trace":{},"uniqueID":"edb92c8b30983d8ee0343a8d5a1da64d"}  empty          R0003   {"clusterName":"bobexample","containerID":"b83d9b8a6798acad4571cb35b0c3413a93447875d5be328de9f76bd28a182a40","containerName":"client","hostNetwork":false,"namespace":"cure","podName":"curing-client-7c6d4bbfb8-fssx5","podNamespace":"cure","workloadKind":"Deployment","workloadName":"curing-client","workloadNamespace":"cure"}  {"containerID":"b83d9b8a6798acad4571cb35b0c3413a93447875d5be328de9f76bd28a182a40","processTree":{"cmdline":"./client","comm":"client","path":"/app/client","pcomm":"containerd-shim","pid":61910,"ppid":61713,"startTime":"0001-01-01T00:00:00Z"}}  {"k8s":{"containerName":"client","namespace":"cure","node":"node-01","owner":{},"podLabels":{"app":"curing-client","kubescape.io/user-defined-profile":"curing-client","pod-template-hash":"7c6d4bbfb8"},"podName":"curing-client-7c6d4bbfb8-fssx5"},"runtime":{"containerId":"b83d9b8a6798acad4571cb35b0c3413a93447875d5be328de9f76bd28a182a40","runtimeName":"containerd"},"timestamp":1760890410389130871,"type":"normal"}  error  Unexpected system call: io_uring_register  Unexpected system call  2025-10-19T16:13:30Z

Lets pull up the full SBoB and compare,

Before the "update" our clickhouse app-server was a npm-application which required the two following syscalls at runtime:

#SBoB for clickhouse app
apiVersion: spdx.softwarecomposition.kubescape.io/v1beta1
kind: ApplicationProfile
metadata:
  name: app
  namespace: click
  ...
    processAllowed:
    - next-server
    - node⋯
    - node
    - npm exec concur-⋯
    - npm-⋯
    - npm
    ...
    syscalls:
    - io_uring_enter
    - io_uring_setup

If you re doing this at home, feel free to check the whole SBoB:

cat /home/laborant/honeycluster/honeystack/clickhouse/clickhouseapp.yaml

Now, we export the relevant filters from the anomaly.

export PODNAME=$(px run -f /home/laborant/honeycluster/analysis/px_clickhouse/kubescape/display_kubescape.pxl | grep register| grep '"podName"' | awk -F'"podName":"' '{print $2}' | awk -F'"' '{print $1}' | head -n1)
export namespace=$(px run -f /home/laborant/honeycluster/analysis/px_clickhouse/kubescape/display_kubescape.pxl |grep register| grep '"namespace":"' | awk -F'"namespace":"' '{print $2}' | awk -F'"' '{print $1}' | head -n1)
export COMM=$(px run -f /home/laborant/honeycluster/analysis/px_clickhouse/kubescape/display_kubescape.pxl |grep register| grep '"namespace":"' | awk -F'"comm":"' '{print $2}' | awk -F'"' '{print $1}' | head -n1)
echo "There is a suspicious pod : $PODNAME in namespace:  $namespace running comm: $COMM"
Pixie CLI
*******************************
* ENV VARS
*        PX_CLOUD_ADDR=getcosmic.ai
*******************************
There is a suspicious pod : hyperdx-hdx-oss-v2-app-client-775864d696-fhb4m in namespace:  click running comm: client .

Story 2: Pixie starts writing to (Forensic)DB

Pixie can now write to Clickhouse adaptively

All data in pixie that mentions the pod hyperdx-hdx-oss-v2-app-client-775864d696-fhb4m in namespace click involved in the io_uring_register syscall gets written to DB.

Story 3: Pixie is asked for the last 10 min of network traffic from the pod

We can detect the dns traffic from the clickhouse namespace to the curing-server-service

We can detect it in dns

There is some network traffic: it looks very "spikey"

First, we query the historical records in the official pixie tables. Filtered on the metadata from the above anomaly

cat <<EOF > pod_tcp_conns.pxl
import px

def tcp_conns():
    df = px.DataFrame(table='conn_stats')
    df.namespace = df.ctx['namespace']
    df.pod = df.ctx['pod']
    df = df[px.contains(df.pod, "${PODNAME}")]
    df = df[not df.remote_addr == '127.0.0.1']
    return df

px.display(tcp_conns())
EOF
px run -f pod_tcp_conns.pxl

Now, we're seeing both DNS and TCP traffic, but the TCP is not recognized as a known protocol (Protocol = 0 , means unknown). That is unusual

laborant@dev-machine:honeycluster$ px run -f pod_tcp_conns.pxl

Pixie CLI
Table ID: output
  TIME                  REMOTE ADDR  REMOTE PORT  TRACE ROLE  ADDR FAMILY  PROTOCOL  SSL    CONN OPEN  CONN CLOSE  CONN ACTIVE  BYTES SENT  BYTES RECV  NAMESPACE  POD                                  
  2025-10-28 16:42:12   10.43.124.187  8888         1           1            0         false  198        198         0            181 KiB     16.8 KiB    click      click/hyperdx-hdx-oss-v2-app-client-775864d696-fhb4m  
  2025-10-28 16:42:12   10.43.0.10     53           1           1            6         false  1582       1582        0            134 KiB     272 KiB     click      click/hyperdx-hdx-oss-v2-app-client-775864d696-fhb4m  
  2025-10-28 16:42:22   10.43.124.187  8888         1           1            0         false  201        201         0            184 KiB     17.1 KiB    click      click/hyperdx-hdx-oss-v2-app-client-775864d696-fhb4m  
  2025-10-28 16:42:22   10.43.0.10     53           1           1            6         false  1606       1606        0            136 KiB     276 KiB     click      click/hyperdx-hdx-oss-v2-app-client-775864d696-fhb4m  
  2025-10-28 16:42:32   10.43.124.187  8888         1           1            0         false  204        204         0            186 KiB     17.3 KiB    click      click/hyperdx-hdx-oss-v2-app-client-775864d696-fhb4m  
  2025-10-28 16:42:32   10.43.0.10     53           1           1            6         false  1629       1629        0            138 KiB     280 KiB     click      click/hyperdx-hdx-oss-v2-app-client-775864d696-fhb4m  
  2025-10-28 16:42:42   10.43.124.187  8888         1           1            0         false  207        207         0            189 KiB     17.6 KiB    click      click/hyperdx-hdx-oss-v2-app-client-775864d696-fhb4m  
  2025-10-28 16:42:42   10.43.0.10     53           1           1            6         false  1653       1653        0            140 KiB     284 KiB     click      click/hyperdx-hdx-oss-v2-app-client-775864d696-fhb4m

Network -> where is it talking to?

cat <<EOF > network.pxl
import px


def network():
    df = px.DataFrame('conn_stats')

    # Filter on namespace.
    df = df[df.ctx['namespace'] == '${namespace}']

    # Filter for client side requests.
    df = df[df.trace_role == 1]
    df.pod = df.ctx['pod']

    # Filter out any non k8s sources.
    df = df[df.pod != '']

    # Find the time window
    time_window = df.agg(
        time_min=('time_', px.min),
        time_max=('time_', px.max),
    )
    time_window.time_delta = px.DurationNanos(time_window.time_max - time_window.time_min)
    time_window = time_window.drop(['time_min', 'time_max'])
    df = df.groupby(['pod', 'upid', 'remote_addr']).agg(
        bytes_sent_min=('bytes_sent', px.min),
        bytes_sent_max=('bytes_sent', px.max),
        bytes_recv_min=('bytes_recv', px.min),
        bytes_recv_max=('bytes_recv', px.max),
    )
    df.bytes_sent = df.bytes_sent_max - df.bytes_sent_min
    df.bytes_recv = df.bytes_recv_max - df.bytes_recv_min
    df.bytes_total = df.bytes_sent + df.bytes_recv
    df = df.drop(['bytes_sent_max', 'bytes_sent_min', 'bytes_recv_max', 'bytes_recv_min'])

    df.from_entity = df.pod

    localhost_ip_regexp = r'127\.0\.0\.[0-9]+'
    df.is_remote_addr_localhost = px.regex_match(localhost_ip_regexp, df.remote_addr)
    df.to_entity = px.select(df.is_remote_addr_localhost,
                             df.pod,
                             px.nslookup(df.remote_addr))

    # Filter out entities as specified by the user.
    df = df[px.contains(df.from_entity, "${PODNAME}")]

    # Since there may be multiple processes per pod,
    # perform an additional aggregation to consolidate those into one entry.
    df = df.groupby(['from_entity', 'to_entity']).agg(
        bytes_sent=('bytes_sent', px.sum),
        bytes_recv=('bytes_recv', px.sum),
        bytes_total=('bytes_total', px.sum),
    )

    # Add time_delta to every row. Use a join to do this.
    # Future syntax will support: df.time_delta = time_window.at[0, 'time_delta']
    df.join_key = 1
    time_window.join_key = 1
    df = df.merge(time_window, how='inner', left_on='join_key', right_on='join_key')
    df = df.drop(['join_key_x', 'join_key_y'])

    # Compute as rates.
    df.bytes_sent = df.bytes_sent / df.time_delta
    df.bytes_recv = df.bytes_recv / df.time_delta
    df.bytes_total = df.bytes_total / df.time_delta
    df = df.drop(['time_delta'])


    return df
px.display(network())
EOF
px run -f network.pxl
px run -f network.pxl
Pixie CLI
*******************************
* ENV VARS
*        PX_CLOUD_ADDR=getcosmic.ai
*******************************
Table ID: output
  FROM ENTITY                                TO ENTITY                                     BYTES SENT  BYTES RECV  BYTES TOTAL  
  click/hyperdx-hdx-oss-v2-app-client-fhb4m  kube-dns.kube-system.svc.cluster.local        122 B/sec   248 B/sec   371 B/sec    
  click/hyperdx-hdx-oss-v2-app-client-fhb4m  curing-server-service.cure.svc.cluster.local  165 B/sec   15.0 B/sec  180 B/sec

Stacktrace

We zoom in to the compromised pod in the compromised namespace

Can see curing in : ** stack_trace_beta in the end shows us what is happening -> we can download the github packages by amit -> and any decent analyst at this point has found the attacker (or rather the software they smuggled in)

cat <<EOF > stacktrace.pxl
import px


def stacktraces():
    df = px.DataFrame(table='stack_traces.beta')

    df.namespace = df.ctx['namespace']
    df.pod = df.ctx['pod']
    df.container = df.ctx['container']
    df.cmdline = df.ctx['cmdline']

    df.node = px.Node(px._exec_hostname())


    df = df[px.contains(df.pod, '${PODNAME}')]
    df = df[df.namespace == '${namespace}']


    return df

px.display(stacktraces())
EOF
px run -f stacktrace.pxl

Here now we have the full stacktrace of the suspicous process:

Stacktrace

  TIME                                     STACK TRACE ID  STACK TRACE                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      COUNT  NAMESPACE  POD                                   CONTAINER  CMDLINE   NODE     
  2025-10-22 15:58:21.425844934 +0000 UTC   6777            runtime.goexit.abi0;main.main.gowrap2;github.com/amitschendel/curing/pkg/client.(*CommandPuller).Run;github.com/amitschendel/curing/pkg/client.(*CommandPuller).connectReadAndProcess;github.com/amitschendel/curing/pkg/client.(*CommandPuller).connect;net.DialTimeout;net.(*Dialer).DialContext;net.(*sysDialer).dialParallel;net.(*sysDialer).dialSerial;net.(*sysDialer).dialSingle;net.(*sysDialer).dialTCP;net.(*sysDialer).doDialTCPProto;net.internetSocket;net.socket;net.(*netFD).dial;net.(*netFD).connect;syscall.Connect;syscall.connect;syscall.Syscall;internal/runtime/syscall.Syscall6;[k] entry_SYSCALL_64_after_hwframe;[k] kretprobe_trampoline;[k] kretprobe_trampoline;[k] trampoline_handler;[k] __kretprobe_trampoline_handler;[k] _raw_spin_unlock_irqrestore                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1      click      click/curing-client-7c6d4bbfb8-rbkgv  client     ./client  node-01  
  2025-10-22 15:59:51.590700167 +0000 UTC    7215            runtime.goexit.abi0;net.(*Resolver).goLookupIPCNAMEOrder.func3.gowrap1;net.(*Resolver).goLookupIPCNAMEOrder.func3.1;net.(*Resolver).tryOneName;net.(*Resolver).exchange;net.dnsPacketRoundTrip;net.(*conn).Write;net.(*netFD).Write;internal/poll.(*FD).Write;syscall.write;syscall.Syscall;internal/runtime/syscall.Syscall6;[k] entry_SYSCALL_64_after_hwframe;[k] kretprobe_trampoline;[k] __x64_sys_write;[k] ksys_write;[k] vfs_write;[k] new_sync_write;[k] sock_write_iter;[k] __sock_sendmsg;[k] inet_sendmsg;[k] udp_sendmsg;[k] udp_send_skb;[k] ip_send_skb;[k] ip_output;[k] ip_finish_output;[k] __ip_finish_output;[k] ip_finish_output2;[k] neigh_resolve_output;[k] dev_queue_xmit;[k] __dev_queue_xmit;[k] dev_hard_start_xmit;[k] xmit_one.constprop.0;[k] dev_queue_xmit_nit;[k] packet_rcv;[k] bpf_prog_332f10ee454943d0_ig_trace_dns;[k] bpf_skb_event_output;[k] bpf_event_output;[k] perf_event_output;[k] perf_output_end;[k] irq_work_queue;[k] __irq_work_queue_local;[k] arch_irq_work_raise;[k] native_apic_msr_write                                                                                                                                                                                                                                                                                                                                                                                                                                                                1      click      click/curing-client-7c6d4bbfb8-rbkgv  client     ./client  node-01  
  2025-10-22 16:01:21.71209691 +0000 UTC    7585            runtime.goexit.abi0;net.(*Resolver).goLookupIPCNAMEOrder.func3.gowrap1;net.(*Resolver).goLookupIPCNAMEOrder.func3.1;net.(*Resolver).tryOneName;net.(*Resolver).exchange;net.(*Resolver).dial;net.(*Dialer).DialContext;net.(*sysDialer).dialParallel;net.(*sysDialer).dialSerial;net.(*sysDialer).dialSingle;net.(*sysDialer).dialUDP;net.internetSocket;net.socket;net.(*netFD).dial;net.(*netFD).connect;syscall.Connect;syscall.connect;syscall.Syscall;internal/runtime/syscall.Syscall6;[k] entry_SYSCALL_64_after_hwframe;[k] kretprobe_trampoline;[k] kretprobe_trampoline;[k] trampoline_handler;[k] __kretprobe_trampoline_handler;[k] _raw_spin_unlock_irqrestore                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      1      click      click/curing-client-7c6d4bbfb8-rbkgv  client     ./client  node-01  
  2025-10-22 16:01:21.71209691 +0000 UTC    7612            runtime.goexit.abi0;net.(*Resolver).goLookupIPCNAMEOrder.func3.gowrap1;net.(*Resolver).goLookupIPCNAMEOrder.func3.1;runtime.chansend1;runtime.chansend;runtime.send;runtime.systemstack.abi0;runtime.send.goready.func1;runtime.ready;runtime.runqput                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            1      click      click/curing-client-7c6d4bbfb8-rbkgv  client     ./client  node-01  
  2025-10-22 16:02:51.793386797 +0000 UTC   7904            ;[k] ret_from_fork;[k] io_wqe_worker                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             1      click      click/curing-client-7c6d4bbfb8-rbkgv  client     ./client  node-01  
  2025-10-22 16:02:51.793386797 +0000 UTC   7906            runtime.goexit.abi0;net.(*Resolver).goLookupIPCNAMEOrder.func3.gowrap1;net.(*Resolver).goLookupIPCNAMEOrder.func3.1;net.(*Resolver).tryOneName;net.(*Resolver).exchange;net.dnsPacketRoundTrip;runtime.makeslice;runtime.mallocgc;runtime.memclrNoHeapPointers                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   1      click      click/curing-client-7c6d4bbfb8-rbkgv  client     ./client  node-01  
  2025-10-22 16:02:51.793386797 +0000 UTC   7950            runtime.goexit.abi0;net.(*Resolver).goLookupIPCNAMEOrder.func3.gowrap1;net.(*Resolver).goLookupIPCNAMEOrder.func3.1;net.(*Resolver).tryOneName;net.(*Resolver).exchange;net.dnsPacketRoundTrip;net.(*conn).Read;net.(*netFD).Read;internal/poll.(*FD).Read;syscall.read;syscall.Syscall;internal/runtime/syscall.Syscall6;[k] entry_SYSCALL_64_after_hwframe;[k] kretprobe_trampoline;[k] kretprobe_trampoline;[k] trampoline_handler;[k] __kretprobe_trampoline_handler;[k] _raw_spin_unlock_irqrestore                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         1      click      click/curing-client-7c6d4bbfb8-rbkgv  client     ./client  node-01  
  2025-10-22 16:04:21.864827833 +0000 UTC   8255            runtime.goexit.abi0;net.(*Resolver).goLookupIPCNAMEOrder.func3.gowrap1;net.(*Resolver).goLookupIPCNAMEOrder.func3.1;net.(*Resolver).tryOneName;net.(*Resolver).exchange;net.dnsPacketRoundTrip;net.(*conn).Write;net.(*netFD).Write;internal/poll.(*FD).Write;syscall.write;syscall.Syscall;internal/runtime/syscall.Syscall6;[k] entry_SYSCALL_64_after_hwframe;[k] kretprobe_trampoline;[k] __x64_sys_write;[k] ksys_write;[k] vfs_write;[k] new_sync_write;[k] sock_write_iter;[k] __sock_sendmsg;[k] inet_sendmsg;[k] udp_sendmsg;[k] udp_send_skb;[k] ip_send_skb;[k] ip_output;[k] ip_finish_output;[k] __ip_finish_output;[k] ip_finish_output2;[k] __local_bh_enable_ip;[k] do_softirq;[k] do_softirq_own_stack;[k] asm_call_sysvec_on_stack;[k] __softirqentry_text_start;[k] net_rx_action;[k] process_backlog;[k] __netif_receive_skb;[k] __netif_receive_skb_one_core;[k] __netif_receive_skb_core.constprop.0;[k] br_handle_frame;[k] br_nf_pre_routing;[k] br_nf_pre_routing_finish;[k] br_nf_hook_thresh;[k] br_handle_frame_finish;[k] br_pass_frame_up;[k] netif_receive_skb;[k] __netif_receive_skb;[k] __netif_receive_skb_one_core;[k] ip_rcv;[k] nf_hook_slow;[k] ip_sabotage_in;[k] ip_rcv_finish;[k] ip_forward;[k] ip_forward_finish;[k] ip_output;[k] ip_finish_output;[k] __ip_finish_output;[k] ip_finish_output2;[k] neigh_hh_output;[k] dev_queue_xmit;[k] __dev_queue_xmit;[k] dev_hard_start_xmit;[k] xmit_one.constprop.0;[k] vxlan_xmit;[k] vxlan_xmit_one;[k] vxlan_get_route  1      click      click/curing-client-7c6d4bbfb8-rbkgv  client     ./client  node-01  
  2025-10-22 16:07:22.072140627 +0000 UTC  00000005-0000-7c8c-0000-0000000367e6  8864            0x000000c0002c8060;runtime.send;runtime.systemstack.abi0;runtime.send.goready.func1;runtime.ready;runtime.wakep;runtime.startm;runtime.notewakeup;runtime.mstart.abi0;runtime.mstart0;runtime.mstart1;runtime.sysmon;runtime.nanotime1.abi0;[k] asm_sysvec_apic_timer_interrupt;[k] sysvec_apic_timer_interrupt;[k] irq_exit_rcu;[k] do_softirq_own_stack;[k] asm_call_sysvec_on_stack;[k] __softirqentry_text_start;[k] rcu_core_si;[k] rcu_core;[k] note_gp_changes;[k] _raw_spin_unlock_irqrestore                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            1      click      click/curing-client-7c6d4bbfb8-rbkgv  client     ./client  node-01  
  2025-10-22 16:10:22.30384519 +0000 UTC    9729            runtime.goexit.abi0;net.(*Resolver).goLookupIPCNAMEOrder.func3.gowrap1;net.(*Resolver).goLookupIPCNAMEOrder.func3.1;net.(*Resolver).tryOneName;net.(*Resolver).exchange;net.dnsPacketRoundTrip;net.(*conn).Read;net.(*netFD).Read;internal/poll.(*FD).Read;syscall.read;syscall.Syscall;internal/runtime/syscall.Syscall6;[k] entry_SYSCALL_64_after_hwframe;[k] kretprobe_trampoline;[k] __x64_sys_read;[k] ksys_read;[k] vfs_read;[k] new_sync_read;[k] sock_read_iter;[k] sock_recvmsg;[k] inet_recvmsg;[k] udp_recvmsg;[k] __skb_recv_udp;[k] __skb_try_recv_from_queue                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      1      click      click/curing-client-7c6d4bbfb8-rbkgv  client     ./client  node-01  
  2025-10-22 16:10:22.30384519 +0000 UTC    9756            runtime.goexit.abi0;net.(*Resolver).goLookupIPCNAMEOrder.func3.gowrap1;net.(*Resolver).goLookupIPCNAMEOrder.func3.1;net.(*Resolver).tryOneName;net.(*Resolver).exchange;net.(*Resolver).dial;net.(*Dialer).DialContext;net.(*sysDialer).dialParallel;net.(*sysDialer).dialSerial;net.(*sysDialer).dialSingle;net.(*sysDialer).dialUDP;net.internetSocket;net.socket;net.sysSocket;syscall.Socket;syscall.socket;syscall.RawSyscall;internal/runtime/syscall.Syscall6;[k] entry_SYSCALL_64_after_hwframe;[k] do_syscall_64;[k] __x64_sys_socket;[k] __sys_socket;[k] kretprobe_trampoline;[k] sock_alloc;[k] new_inode_pseudo;[k] alloc_inode;[k] inode_init_always                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               1      click      click/curing-client-7c6d4bbfb8-rbkgv  client     ./client  node-01  
  2025-10-22 16:10:22.30384519 +0000 UTC    9760            runtime.goexit.abi0;net.(*Resolver).goLookupIPCNAMEOrder.func3.gowrap1;net.(*Resolver).goLookupIPCNAMEOrder.func3.1;net.(*Resolver).tryOneName;net.(*Resolver).exchange;net.(*Resolver).dial;net.(*Dialer).DialContext;net.(*sysDialer).dialParallel;net.(*sysDialer).dialSerial;net.(*sysDialer).dialSingle;net.(*sysDialer).dialUDP;net.internetSocket;net.socket;net.(*netFD).dial;net.(*netFD).connect;syscall.Connect;syscall.connect;syscall.Syscall;internal/runtime/syscall.Syscall6;[k] entry_SYSCALL_64_after_hwframe;[k] kretprobe_trampoline;[k] kretprobe_trampoline;[k] trampoline_handler;[k] __kretprobe_trampoline_handler;[k] _raw_spin_unlock_irqrestore                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      1      click      click/curing-client-7c6d4bbfb8-rbkgv  client     ./client  node-01  
  2025-10-22 16:11:52.406689359 +0000 UTC   10036           runtime.goexit.abi0;net.(*Resolver).goLookupIPCNAMEOrder.func3.gowrap1;net.(*Resolver).goLookupIPCNAMEOrder.func3.1;net.(*Resolver).tryOneName;net.(*Resolver).exchange;net.dnsPacketRoundTrip;net.(*conn).Read;net.(*netFD).Read;internal/poll.(*FD).Read;syscall.read;syscall.Syscall;internal/runtime/syscall.Syscall6;[k] entry_SYSCALL_64_after_hwframe;[k] kretprobe_trampoline;[k] kretprobe_trampoline;[k] trampoline_handler;[k] __kretprobe_trampoline_handler;[k] _raw_spin_unlock_irqrestore                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         1      click      click/curing-client-7c6d4bbfb8-rbkgv  client     ./client  node-01  
  2025-10-22 16:11:52.406689359 +0000 UTC   10049           runtime.goexit.abi0;main.main.gowrap2;github.com/amitschendel/curing/pkg/client.(*CommandPuller).Run;github.com/amitschendel/curing/pkg/client.(*CommandPuller).connectReadAndProcess;github.com/amitschendel/curing/pkg/client.(*CommandPuller).processCommands;github.com/amitschendel/curing/pkg/client.(*CommandPuller).sendGobRequest;encoding/gob.(*Encoder).Encode;encoding/gob.(*Encoder).EncodeValue;encoding/gob.(*Encoder).sendTypeDescriptor;encoding/gob.(*Encoder).sendType;encoding/gob.(*Encoder).sendActualType;encoding/gob.(*Encoder).sendType;encoding/gob.(*Encoder).sendActualType;encoding/gob.(*Encoder).writeMessage;github.com/amitschendel/curing/pkg/client.(*NetworkRWer).Write;net.(*conn).Write;net.(*netFD).Write;internal/poll.(*FD).Write;syscall.write;syscall.Syscall;internal/runtime/syscall.Syscall6;[k] entry_SYSCALL_64_after_hwframe;[k] do_syscall_64;[k] syscall_enter_from_user_mode;[k] syscall_trace_enter.constprop.0;[k] __traceiter_sys_enter;[k] __bpf_trace_sys_enter;[k] bpf_trace_run2;[k] bpf_prog_0f882ec0ca7e929e_ig_seccomp_e;[k] __htab_map_lookup_elem;[k] lookup_nulls_elem_raw                                                                                                                                                                                                                                                                                                                                                                     1      click      click/curing-client-7c6d4bbfb8-rbkgv  client     ./client  node-01  
  2025-10-22 16:11:52.406689359 +0000 UTC   10085           runtime.goexit.abi0;net.(*Resolver).goLookupIPCNAMEOrder.func3.gowrap1;net.(*Resolver).goLookupIPCNAMEOrder.func3.1;net.(*Resolver).tryOneName;net.(*Resolver).exchange;net.dnsPacketRoundTrip;net.(*conn).Write;net.(*netFD).Write;internal/poll.(*FD).Write;syscall.write;syscall.Syscall;internal/runtime/syscall.Syscall6;[k] entry_SYSCALL_64_after_hwframe;[k] kretprobe_trampoline;[k] __x64_sys_write;[k] ksys_write;[k] vfs_write;[k] new_sync_write;[k] sock_write_iter;[k] __sock_sendmsg;[k] inet_sendmsg;[k] udp_sendmsg;[k] udp_send_skb;[k] ip_send_skb;[k] ip_output;[k] ip_finish_output;[k] __ip_finish_output;[k] ip_finish_output2;[k] __local_bh_enable_ip;[k] do_softirq;[k] do_softirq_own_stack;[k] asm_call_sysvec_on_stack;[k] __softirqentry_text_start;[k] net_rx_action;[k] process_backlog;[k] __netif_receive_skb;[k] __netif_receive_skb_one_core;[k] __netif_receive_skb_core.constprop.0;[k] br_handle_frame;[k] br_nf_pre_routing;[k] setup_pre_routing;[k] sock_wfree;[k] sock_def_write_space;[k] __wake_up_sync_key;[k] __wake_up_common_lock;[k] _raw_spin_unlock_irqrestore                                                                                                                                                                                                                                                                                                                                                                                              1      click      click/curing-client-7c6d4bbfb8-rbkgv  client     ./client  node-01  
  2025-10-22 16:13:22.516908876 +0000 UTC   10400           runtime.goexit.abi0;github.com/iceber/iouring-go.New.gowrap1;github.com/iceber/iouring-go.(*IOURing).run;github.com/iceber/iouring-go.(*IOURing).getCQEvent;runtime.selectgo;runtime.gopark;runtime.mcall;runtime.park_m;runtime.schedule;runtime.findRunnable;runtime.stealWork;runtime.(*timers).check;runtime.nanotime1.abi0;[m] [vdso] + 0x7ffd5a3e6a09;[k] entry_SYSCALL_64_after_hwframe;[k] do_syscall_64;[k] syscall_enter_from_user_mode;[k] syscall_trace_enter.constprop.0;[k] __traceiter_sys_enter;[k] __bpf_trace_sys_enter;[k] bpf_trace_run2                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     1      click      click/curing-client-7c6d4bbfb8-rbkgv  client     ./client  node-01  
  2025-10-22 16:14:22.570940379 +0000 UTC   10674           runtime.goexit.abi0;net.(*Resolver).goLookupIPCNAMEOrder.func3.gowrap1;net.(*Resolver).goLookupIPCNAMEOrder.func3.1;net.(*Resolver).tryOneName;net.(*Resolver).exchange;net.dnsPacketRoundTrip;net.(*conn).Write;net.(*netFD).Write;internal/poll.(*FD).Write;syscall.write;syscall.Syscall;internal/runtime/syscall.Syscall6;[k] entry_SYSCALL_64_after_hwframe;[k] do_syscall_64;[k] syscall_exit_to_user_mode;[k] __traceiter_sys_exit;[k] __bpf_trace_sys_exit;[k] bpf_trace_run2;[k] bpf_prog_a4331b93d3bc1065_ig_cap_sys_exit;[k] htab_map_delete_elem                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     1      click      click/curing-client-7c6d4bbfb8-rbkgv  client     ./client  node-01

Stacktrace Explanation

Last Step: we real time compile a bpftrace and find what this rootkit has been reading

mkdir dfsnoop
cat <<EOF > dfsnoop/vis.json
{
    "variables": [
        {
            "name": "comm",
            "type": "PX_STRING",
            "description": "The process command to filter the dc data based on",
            "defaultValue": ""
        }
    ],
    "globalFuncs": [
        {
            "outputName": "dc_snoop",
            "func": {
                "name": "dc_snoop",
                "args": [
                    {
                        "name": "comm",
                        "variable": "comm"
                    }
                ]
            }
        }
    ],
    "widgets": []
}
EOF

cat <<'EOF' > dfsnoop/dfsnoop.pxl
import pxtrace
import px


program = """
#include <linux/fs.h>

// from fs/namei.c:
struct nameidata {
        struct path     path;
        struct qstr     last;
        // [...]
};

// comment out this block to avoid showing hits:
kprobe:lookup_fast,
kprobe:lookup_fast.constprop.*
{
    $nd = (struct nameidata *)arg0;
    printf(\"time_:%llu pid:%d comm:%s t:%s file:%s\",
           nsecs, pid, comm, \"R\", str($nd->last.name));
}

kprobe:d_lookup
{
    $name = (struct qstr *)arg1;
    @fname[tid] = $name->name;
}

kretprobe:d_lookup
/@fname[tid]/
{
    printf(\"time_:%llu pid:%d comm:%s t:%s file:%s\",
           nsecs, pid, comm, \"M\", str(@fname[tid]));
    delete(@fname[tid]);
}
"""


def dc_snoop(comm: str):
    table_name = 'dc_snoop'
    pxtrace.UpsertTracepoint('dc_snoop',
                             table_name,
                             program,
                             pxtrace.kprobe(),
                             "10m")
    df = px.DataFrame(table=table_name)
    df = df[px.contains(df.comm, comm)]

    return df

EOF
px run -f ./dfsnoop -- --comm ${COMM}

We real time compile a bpftrace and find what this rootkit has been reading

laborant@dev-machine:honeycluster$ px run -f dcsnoop.px 
Pixie CLI
*******************************
* ENV VARS
*        PX_CLOUD_ADDR=getcosmic.ai
*******************************
Table ID: output
  TIME                                     PID    COMM    T  FILE                                                
  2025-11-09 22:27:59.365371839 +0000 UTC  20593  client  R  etc/resolv.conf                                     
  2025-11-09 22:27:59.36538673 +0000 UTC   20593  client  R  resolv.conf                                         
  2025-11-09 22:27:59.365412363 +0000 UTC  20593  client  R  etc/nsswitch.conf                                   
  2025-11-09 22:27:59.365418946 +0000 UTC  20593  client  R  nsswitch.conf                                       
  2025-11-09 22:27:59.365601866 +0000 UTC  20593  client  R  etc/hosts                                           
  2025-11-09 22:27:59.36560909 +0000 UTC   20593  client  R  hosts                                               
  2025-11-09 22:27:59.376590723 +0000 UTC  20593  client  R  var/run/secrets/kubernetes.io/serviceaccount/token  
  2025-11-09 22:27:59.376602736 +0000 UTC  20593  client  R  run/secrets/kubernetes.io/serviceaccount/token      
  2025-11-09 22:27:59.376608569 +0000 UTC  20593  client  R  secrets/kubernetes.io/serviceaccount/token          
  2025-11-09 22:27:59.376613832 +0000 UTC  20593  client  R  kubernetes.io/serviceaccount/token                  
  2025-11-09 22:27:59.376620668 +0000 UTC  20593  client  R  serviceaccount/token                                
  2025-11-09 22:27:59.376627658 +0000 UTC  20593  client  R  token                                               
  2025-11-09 22:27:59.376635041 +0000 UTC  20593  client  R  ..data/token                                        
  2025-11-09 22:27:59.376641473 +0000 UTC  20593  client  R  ..2025_11_09_22_25_54.25061200                      
  2025-11-09 22:27:59.376647379 +0000 UTC  20593  client  R  token                                               
  2025-11-09 22:27:59.431891593 +0000 UTC  20593  client  R  etc/shadow                                          
  2025-11-09 22:27:59.431899959 +0000 UTC  20593  client  R  shadow

Level up your Server Side game — Join 20,000 engineers who receive insightful learning materials straight to their inbox