👋 Приветствую в мире цифровой безопасности!
Расскажу про eBPF с точки зрения безопасности - не просто трейсинг, а как технология меняет и атаку и защиту.
⏺Почему eBPF интересен в контексте ИБ: программы выполняются прямо в ядре с минимальными накладными расходами, видят всё что происходит в системе до того как это попадает в логи, и при этом не требуют написания kernel module. Это одновременно делает eBPF мощным инструментом защиты и потенциально опасным вектором атаки.
⏺Установка инструментов:
apt install bpfcc-tools bpftrace linux-headers-$(uname -r)
⏺Детект reverse shell в реальном времени - ловим процессы которые перенаправляют stdin/stdout в сокет:
# detect_revshell.py через bpfcc
from bcc import BPF
prog = """
#include <uapi/linux/ptrace.h>
#include <linux/sched.h>
BPF_PERF_OUTPUT(events);
struct data_t {
u32 pid;
char comm[16];
int fd;
};
int trace_dup2(struct pt_regs *ctx, int oldfd, int newfd) {
if (newfd <= 2) {
struct data_t data = {};
data.pid = bpf_get_current_pid_tgid() >> 32;
bpf_get_current_comm(&data.comm, sizeof(data.comm));
data.fd = oldfd;
events.perf_submit(ctx, &data, sizeof(data));
}
return 0;
}
"""
b = BPF(text=prog)
b.attach_kprobe(event="__x64_sys_dup2", fn_name="trace_dup2")
dup2 вызывается когда процесс перенаправляет файловые дескрипторы - именно это делает каждый reverse shell.
⏺Мониторинг execve с аргументами - ловим запуск подозрительных команд:
bpftrace -e '
tracepoint:syscalls:sys_enter_execve {
printf("pid=%d comm=%s file=%s\n",
pid, comm, str(args->filename));
}'
⏺Детект privilege escalation - ловим момент когда процесс получает uid=0:
bpftrace -e '
kprobe:commit_creds {
$cred = (struct cred *)arg0;
if ($cred->uid.val == 0 && uid != 0) {
printf("ALERT: %s (pid=%d) escalated to root\n", comm, pid);
}
}'
Срабатывает в момент изменения credentials - до того как процесс успеет что-то сделать с новыми правами.
⏺XDP для блокировки трафика на скорости wire speed - дропаем пакеты до того как они попадут в сетевой стек:
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/tcp.h>
SEC("xdp")
int block_scanner(struct xdp_md *ctx) {
void *data = (void *)(long)ctx->data;
void *data_end = (void *)(long)ctx->data_end;
struct ethhdr *eth = data;
if ((void *)(eth + 1) > data_end) return XDP_PASS;
struct iphdr *ip = (void *)(eth + 1);
if ((void *)(ip + 1) > data_end) return XDP_PASS;
struct tcphdr *tcp = (void *)(ip + 1);
if ((void *)(tcp + 1) > data_end) return XDP_PASS;
// Блокируем SYN-сканирование — пакеты с только SYN флагом
if (tcp->syn && !tcp->ack && !tcp->fin && !tcp->rst) {
// Здесь можно добавить логику rate limiting по src IP
// через BPF_MAP_TYPE_LRU_HASH
}
return XDP_PASS;
}
⏺Обратная сторона eBPF, как инструмента атаки: исследователи демонстрировали rootkit на eBPF который перехватывает системные вызовы и скрывает файлы и процессы - всё это без kernel module и без записи на диск. Инструмент ebpfkit показал что можно реализовать полноценный backdoor полностью в eBPF который крайне сложно обнаружить стандартными средствами.
⏺Защита от вредоносного использования eBPF: ограничение через Linux capabilities (CAP_BPF требуется для загрузки программ), kernel.unprivileged_bpf_disabled=1 запрещает непривилегированным пользователям загружать eBPF программы, мониторинг загрузки BPF-программ через аудит:
sysctl -w kernel.unprivileged_bpf_disabled=1
auditctl -a always,exit -F arch=b64 -S bpf -k ebpf_load
ZeroDay | Белый Хакер | #eBPF