bpf_probe_read arbitrary kernel memory read¶
Bir tracing BPF program'ı, attacker'ın seçtiği bir kernel address'iyle
bpf_probe_readhelper'ını çağırarak fault-safe şekilde arbitrary kernel memory okur ve bunu bir BPF map üzerinden dışarı sızdırır.
Mechanism¶
Note
Tracing BPF program'ları için (kprobes, tracepoints, perf events), bpf_probe_read
bir kernel-space address'inden size byte'ı güvenli şekilde BPF kontrollü bir
destination'a okur. "Güvenli" demek, erişim sırasında oluşan bir fault'un kernel'i
oops'lamak yerine yakalanıp error olarak döndürülmesi demek — ama target address
program tarafından kontrol edildiği için, bir tracing program'ı arbitrary kernel
memory okuyup bunu (örneğin bir BPF map üzerinden) dışarı sızdırabilir, böylece KASLR'ı
aşar ya da secret'ları döker. Kernel BPF design FAQ bunu doğrudan söylüyor: "Tracing bpf
programs can read arbitrary memory with bpf_probe_read()."
Walkthrough¶
Helper prototype'ı (bpf-helpers(7)'ten):
long bpf_probe_read(void *dst, u32 size, const void *unsafe_ptr);
/* "For tracing programs, safely attempt to read size bytes from kernel
space address unsafe_ptr and store the data in dst."
Returns 0 on success, or a negative error on failure. */
Bir tracing program'ın içinde, seçilen bir kernel address'i okuyup userspace için saklayalım:
SEC("kprobe/some_func")
int probe(struct pt_regs *ctx) {
char leak[64];
bpf_probe_read(leak, sizeof(leak), (void *)TARGET_KERNEL_ADDR);
bpf_map_update_elem(&out_map, &key, leak, BPF_ANY); /* exfiltrate */
return 0;
}
Userspace daha sonra leak edilen byte'ları almak için out_map'i okur. Man page,
kernel ve user read'lerini ayıran açık bpf_probe_read_kernel() / bpf_probe_read_user()
varyantlarını kullanmayı tavsiye ediyor.
Warning
Bu helper'ı sadece tracing BPF program'ları alır. BPF design FAQ, networking program'larının "cannot read arbitrary memory, since they don't have access to these helpers" olduğunu belirtiyor — arbitrary-read gücü tracing program tiplerine özgü.
Detection¶
Tracing BPF program'larının yüklenmesi audit edilebilir (BPF program load event'leri, attach edilmiş kprobe'lar); kernel memory okuyup dışarı aktaran beklenmedik kprobe/tracepoint program'ları bir sinyaldir.
Mitigation¶
Kernel BPF design FAQ'a göre, "Tracing BPF programs are root only" — helper privileged
context'lerle sınırlandırılmıştır. BPF/tracing capability'lerini kısıtlayın (CAP_BPF,
CAP_PERFMON, CAP_SYS_ADMIN), kernel.unprivileged_bpf_disabled=1 ayarlayın ve
kernel.perf_event_paranoid'i öyle sınırlayın ki unprivileged kullanıcılar tracing
program'larını attach edemesin.