Helius
Kontakt mig

Kernel og Linux

Kernen ser alt. De fleste sikkerhedsprodukter kigger bare med udefra

Sikkerhed, der kører i kernen – ikke ved siden af.

Problemet

Runtime-sikkerhed på Linux sælges typisk som en lukket agent med licens pr. server, der kører som root, og hvis kode I ikke må læse. Den ser det, leverandøren har valgt at overvåge, den bliver dyrere, når I vokser, og når den overser noget, kan I ikke finde ud af hvorfor. Imens har kernen haft de rigtige byggesten i årevis.

Tilgangen

Jeg skriver overvågningen i stedet for at leje den: eBPF-programmer koblet på processernes livscyklus og de syscalls, der faktisk betyder noget, LSM- og kprobe-hooks, der griber ind i stedet for bare at se på, og filtrering i kernen, så de 99 % af hændelserne, der er ligegyldige, aldrig bliver til netværkstrafik eller en regning for dataindsamling. Delen i userspace er skrevet i Rust, fordi hukommelsessikkerhed betyder ekstra meget i et program, der kører med fulde rettigheder på hver eneste af jeres servere.

Det får I

  • eBPF-probes koblet på de proces- og syscall-events, jeres trusselsmodel handler om
  • En agent i Rust, bygget fra kildekoden i jeres egen pipeline – intet lukket program fra en leverandør
  • Filtrering i kernen, så ligegyldige events aldrig forlader den
  • Gennemgang af angrebsfladen: hvad kører, hvad kan nås, og hvad kan fjernes
  • Alarmer i den overvågning, I allerede bruger – Prometheus, Zabbix eller Grafana – med en runbook til hver
  • Kildekoden til probes i jeres eget repository, dokumenteret så godt, at I selv kan ændre den

Eksempel

probes/src/exec.bpf.c

// SPDX-License-Identifier: GPL-2.0
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>

char LICENSE[] SEC("license") = "GPL";

struct event {
    u32 pid;
    u32 ppid;
    u32 uid;
    char filename[128];
};

struct {
    __uint(type, BPF_MAP_TYPE_RINGBUF);
    __uint(max_entries, 256 * 1024);
} events SEC(".maps");

/* Report execs that run as root. Everything else is dropped here, in the
   kernel — no ring buffer slot, no userspace wakeup, no egress, no bill. */
static __always_inline bool should_report(struct task_struct *task)
{
    return BPF_CORE_READ(task, cred, euid.val) == 0;
}

SEC("tp_btf/sched_process_exec")
int BPF_PROG(on_exec, struct task_struct *task,
             pid_t old_pid, struct linux_binprm *bprm)
{
    struct event *e;

    if (!should_report(task))
        return 0;

    e = bpf_ringbuf_reserve(&events, sizeof(*e), 0);
    if (!e)
        return 0;

    e->pid  = BPF_CORE_READ(task, tgid);
    e->ppid = BPF_CORE_READ(task, real_parent, tgid);
    e->uid  = BPF_CORE_READ(task, cred, uid.val);
    bpf_probe_read_kernel_str(e->filename, sizeof(e->filename),
                              BPF_CORE_READ(bprm, filename));

    bpf_ringbuf_submit(e, 0);
    return 0;
}

Fortæl mig, hvad der er galt

Et par linjer om problemet er nok. Inden for én arbejdsdag svarer jeg med, hvad jeg tror, det er, hvor lang tid det cirka tager, og om I overhovedet har brug for mig. Nogle gange er det ærlige svar nej.

Jeg svarer inden for én arbejdsdag · Ingen kontaktformularer, ingen sporingspixels og ingen automatiske salgsmails.