nf_tables is the modern netfilter framework for firewall rules, managed through the nft netlink API. It has been a rich source of kernel vulnerabilities, typically use-after-free or type-confusion bugs in how set elements, chains, and expressions are allocated, referenced, and freed. The reason these matter for containers is reachability: configuring nf_tables needs CAP_NET_ADMIN, and an unprivileged process that creates a new user namespace (unshare -Un) receives CAP_NET_ADMIN within the network namespace it then creates. A container that is allowed to create user namespaces can therefore reach the vulnerable code even with no privileges on the host.
Check reachability:
uname -r # version gates which nf_tables bug applies
unshare -Urn sh -c 'echo in userns+netns; nft list ruleset' 2>&1 | head
sysctl kernel.unprivileged_userns_clone 2>/dev/null # 1 or unset => userns creation allowed
Exploitation pattern#
The specific trigger differs per bug, but the shape is consistent:
# 1. Enter a new user + network namespace to obtain CAP_NET_ADMIN over nf_tables
unshare -Urn /bin/sh
# 2. From a C exploit: build an nft batch that drives the vulnerable path, e.g.
# create a set/chain, trigger the premature free, then reallocate the freed
# object with attacker-controlled data (heap spray via nft objects or msg_msg)
# 3. Use the resulting UAF to gain a controlled kernel write primitive
# 4. Escalate: overwrite modprobe_path or a cred structure, or build arbitrary R/W
A common escalation after achieving a kernel write is to overwrite modprobe_path so that triggering an auto-load executes an attacker binary as root, or to locate and zero the UID fields of the current process's credentials structure.
Exploitation notes#
- The gating control is user-namespace creation. Hosts that set
kernel.unprivileged_userns_clone=0, or runtimes that block theunshare/cloneuser-namespace flags via seccomp, cut off reachability even on a vulnerable kernel. - These bugs give a kernel primitive, not a one-shot command; a working exploit includes a heap-grooming and KASLR-defeat stage specific to the kernel build, so they are version-sensitive.
- Where the default seccomp profile is in force it already blocks
unsharewith the user-namespace flag for many configurations; confirm with a throwawayunshare -Un truebefore relying on this route.