One Character in nftables Hands Any Linux User Root

Ethical Hacking Complete Course Zero to Expert
Hack like black hat hackers. Penetration testing, Kali Linux, WiFi and web hacking, and the hacker mindset behind it.
→ Take the full courseOne extra character in the Linux kernel hands a normal user root. A single ! that does not belong inside nftables, the firewall built into Debian and Ubuntu by default, flips a check the wrong way so a local user with no special rights can become root and break out of a container. It was patched months ago, and the working exploits are now public.
The flaw carries the name CVE-2026-23111. The kernel maintainers fixed it on the fifth of February, and for four months it stayed a quiet line in a changelog. What changed is that the people who cracked it started showing exactly how. Exodus Intelligence published a full technical walkthrough on the eighth of June, and they were not the first to get there. A team at FuzzingLabs had already rebuilt the exploit on their own back in April, while preparing for Pwn2Own Berlin, a hacking competition.
So far there is no sign of any of this hitting real systems. The public exploits are proof of concept code from security researchers, the kind written to prove a bug is real, not something caught in live attacks, and that gap is the difference between an emergency and a patch you apply on the normal schedule.
To follow how a firewall bug turns into full control of a machine, it helps to know what nftables actually is. Linux carries a firewall inside the kernel itself, the core of the operating system. It decides which network packets pass and which get dropped, and it took over from the older iptables system that a lot of people still know by name.
Admins drive it with a command line tool called nft, building tables, chains, and rules that say what happens to traffic.
Most of that work runs deep in the kernel, which is the reason a bug there carries so much weight. Code that runs in the kernel can touch anything on the machine. A bug down there is a bug in the most powerful part of the computer.
nftables does not change rules one at a time. It groups them into a batch, so a set of changes either all land together or all roll back together. To make that work, the kernel keeps two versions of the rules side by side, a current one and a next one, and flips between them once a batch succeeds.
When a batch fails halfway through, the kernel hits undo. It walks back everything the failed batch started and puts the rules back the way they were. That cleanup step is called the abort path.
That abort path is where the trouble lives. When the kernel removes a certain kind of firewall map, it first switches off the elements inside it and lowers a counter on any chain those elements point to. That counter tracks how many things still need the chain, and the kernel only hands the memory back once it hits zero. The name for that counter is a reference count.
When the batch fails and the abort runs, the kernel is supposed to walk back through those elements, switch them on again, and raise the reference count back up.
A map can have one fallback entry, the one that says what to do when nothing else matches. That is the catchall element. The function that switches it back on after an abort got its check turned around.
Here is the correct version next to the broken one:
| |
The working function passes over the elements that are already active and handles the ones that are switched off, which is what a rollback needs. The catchall version carries one extra exclamation mark in front of the same check, so it does the reverse. It skips the switched-off elements that still need restoring and only touches the ones that are already fine. That single character flips the meaning of that line.
The effect is quiet and slow. Each time a batch gets aborted, the reference count on the chain drops and never climbs back. Repeat it enough times and the tally reaches zero while something is still pointing at that chain.
The kernel now believes nothing depends on the chain, so it deletes the chain and hands the memory back, even though something else is still pointing at it. Now the kernel is using memory it already gave away. That bug has a name: use-after-free, and it is one of the classic ways a small memory mistake turns into full control.
The freed spot gets refilled with data the attacker chooses, and the kernel ends up reading attacker data while it believes it is reading its own.
There is a second twist in the same code. The broken cleanup did not hold just one mistake. The break instructions sitting right next to the inverted check introduced another bug, tracked as CVE-2026-23278, with its own separate patch. One short stretch of catchall handling, two security holes.
Getting from that point to root takes a careful sequence, and both teams walked almost the same one. It starts in the same place. To attack the kernel you first have to know where it sits in memory, and Linux moves that spot on every boot to make this harder. So both teams found a way to read the real location back.
They let a small kernel object called seq_operations drop into the freed slot, then read the addresses stored inside it. FuzzingLabs credits that step to an earlier nftables write-up. From there both teams ran the same play: leak a few more addresses to map out the heap, take over a function pointer the kernel trusts, and run their own chain of instructions through it. The only real difference is the last move, how each team turned that control into root.
Exodus, where researcher Oliver Sieber found the bug, ran it on Debian Bookworm and Trixie and on Ubuntu 22.04 and 24.04. Their last step stays inside the kernel. They call commit_creds to hand the running program root, then call switch_task_namespaces, the kernel function that drops a process out of its container, and return to normal. An ordinary user inside a container walks out as root on the host.
FuzzingLabs, the work of researchers Alexis and Lyes, reproduced it on Red Hat. Their last step leaves the kernel a different way. They overwrite modprobe_path, a kernel setting that points at a program the kernel itself runs as root, switch SELinux off so nothing blocks it, and put the kernel to sleep instead of letting it crash back to normal. Then they set off their own program from another shell.
One bug, two independent teams, the same core technique, and root at the end of both. That is what sets this one apart. A flaw that only one fragile exploit can reach stays a curiosity. A flaw that two separate teams turn into a working exploit is something else, and the numbers back that up. Exodus measured their exploit at better than ninety nine percent success on an idle machine, dropping to around eighty percent under heavy load from a benchmark that puts pressure on the kernel. Those are high figures for a kernel exploit.
None of this stands on its own. nftables has been a steady source of these root bugs for years. The closest relative is CVE-2024-1086, another use-after-free in the same code, traced back to a line written in 2014, patched in early 2024, listed on the US government catalog of vulnerabilities seen in real attacks, and in late 2025 it turned up in ransomware campaigns. The public exploit for that one came from a researcher going by Notselwyn.
The common factor under most of these is a Linux feature called unprivileged user namespaces, which lets a normal account act like root inside its own private sandbox so it can reach kernel code that is otherwise out of bounds. That feature is what puts nftables in reach of a regular user in the first place. It ships switched on by default on many desktops and a fair share of servers, but it is not the same on every system.
On Debian and older Ubuntu a normal user can open that sandbox freely, while Ubuntu 24.04 blocks it by default through AppArmor. The Exodus exploit steps around that restriction with a known bypass, which is the kind of detail that decides whether a given machine is actually exposed.
The fix is as small as the bug. The maintainers removed the stray exclamation mark so the catchall check lines up with the working one, and that single line went out in the February patch. For people running Linux, the move is simple. Update the kernel and reboot, because a kernel patch does nothing until the machine restarts on the new code.
Check what is running and pull the update:
| |
Ubuntu shipped fixes for 22.04, 24.04, and 25.10. Debian patched Bookworm and Trixie and backported the fix to Bullseye. Red Hat, SUSE, and Amazon Linux track it as well, so check your distribution’s advisory for the kernel version that carries the fix.
On systems that have no need for unprivileged user namespaces, like a server that never runs untrusted containers, there is a way to shrink the attack surface. Switching the feature off stops a normal account from creating the sandbox this exploit depends on:
| |
This can break tools that rely on the feature, so test it before rolling it out across a fleet. Patching the kernel stays the move that actually closes the bug.
Turning a normal account into root, finding a flaw this subtle, and building the exploit step by step, leaking kernel addresses, hijacking control flow, and walking out as root and out of a container, that is the kind of exploitation and privilege escalation work my ethical hacking course covers from the ground up:
Hacking is not a hobby but a way of life.
Sources: Exodus Intelligence | FuzzingLabs
Stay updated
Get the latest posts in your inbox every week. Ethical hacking, security news, tutorials, and everything that catches my attention. If that sounds useful, drop your email below.