CAP_BPF a été séparée de CAP_SYS_ADMIN afin de permettre le chargement de programmes BPF et la création de maps BPF sans la capacité d'administration complète. Les programmes BPF s'exécutent à l'intérieur du noyau après avoir passé le vérificateur, et ils partagent l'unique noyau hôte entre tous les espaces de noms. Avec CAP_BPF, et selon les types de programmes et les helpers autorisés par le noyau, un attaquant peut lire la mémoire du noyau et, avec des programmes de tracing accompagnés de helpers tels que bpf_probe_write_user ou de primitives basées sur les maps, influencer la mémoire du noyau et celle de l'espace utilisateur, s'évadant ainsi de l'isolation du conteneur.
Confirmez la capacité et les types de programmes accessibles :
capsh --print | grep -o -E 'cap_bpf|cap_perfmon|cap_sys_admin'
grep CapEff /proc/self/status # cap_bpf is bit 39
bpftool feature probe 2>/dev/null | grep -i 'program_type .* available' | head
Voie : lire la mémoire du noyau#
Un programme BPF de tracing (par exemple BPF_PROG_TYPE_KPROBE ou BPF_PROG_TYPE_TRACEPOINT, qui nécessitent habituellement aussi CAP_PERFMON) peut appeler bpf_probe_read_kernel pour copier des adresses noyau arbitraires dans une map que l'attaquant lit ensuite depuis l'espace utilisateur. Cela fuit des identifiants, des pointeurs permettant de vaincre KASLR, et le contenu de structures du noyau.
// sketch of a kprobe program body (loaded via bpf() BPF_PROG_LOAD)
// reads N bytes at a target kernel address into a perf/array map
bpf_probe_read_kernel(&out, sizeof(out), (void *)target_kaddr);
bpf_map_update_elem(&results, &key, &out, BPF_ANY);
# user side: pin the map, poll it for leaked kernel data
bpftool map dump name results
Voie : primitives d'écriture#
Lorsque bpf_probe_write_user est disponible pour le type de programme chargé, un programme de tracing qui se déclenche dans le contexte d'une tâche cible peut écraser la mémoire utilisateur de cette tâche. Combiné à un helper qui atteint une structure d'identifiants, cela est escaladé jusqu'à l'écrasement de champs UID ou à la désactivation d'une vérification. Les helpers réellement accessibles dépendent de la version du noyau et de la combinaison de capacités ; CAP_BPF avec CAP_PERFMON déverrouille les types de programmes de tracing qui rendent ces helpers utilisables.
Notes d'exploitation#
- Le vérificateur BPF et les listes d'autorisation de helpers par type de programme sont le véritable verrou.
CAP_BPFseule vous limite à un sous-ensemble ; l'associer àCAP_PERFMON(tracing) ou àCAP_SYS_ADMINélargit grandement ce qui peut être chargé. Sondez avecbpftool feature probe. kernel.unprivileged_bpf_disabledne s'applique pas ici puisque vous détenez la capacité, maisCONFIG_BPF_UNPRIV_DEFAULT_OFFet une surfacebpf()verrouillée peuvent tout de même bloquer certains types de programmes.- Historiquement, plusieurs bugs du vérificateur BPF permettaient une lecture/écriture noyau arbitraire depuis des programmes chargeables ; lorsque le noyau hôte n'est pas corrigé, un programme de contournement du vérificateur est une évasion directe et pas seulement une fuite.