Sploitus

Exploit for Use After Free in Linux Linux Kernel

githubexploit Β· 2026-08-08

Exploit Code

README155 lines
## https://sploitus.com/exploit?id=EA81FFC0-451A-5FBE-B06F-CBC5A7B50FB3
# CVE-2023-32233 β€” nf_tables Use-After-Free: Reproduction & Root-Cause Analysis

**What this repo is:** my hands-on reproduction and study of
[CVE-2023-32233](https://nvd.nist.gov/vuln/detail/CVE-2023-32233), a
use-after-free in the Linux kernel Netfilter nf_tables subsystem that allows
local privilege escalation, publicly disclosed in May 2023 by Patryk Sondej
and Piotr Krysiuk.

**Credit:** the PoC (`exploit.c`) and the original write-up are by
[@Liuk3r](https://github.com/Liuk3r/CVE-2023-32233). My work in this repo
is reproducing the exploit in my own lab (Ubuntu 23.04, kernel 6.2.0-20)
and documenting the root cause and exploitation chain below. All testing
was done on dedicated lab machines.

---

## My Analysis Notes

### Root cause

nf_tables processes configuration updates as an atomic batch. The
validation of each operation against the state changes of *previous*
operations in the same batch is insufficient. Concretely:

1. Start with an `nft_rule` containing a `lookup` expression on an
   anonymous `nft_set` that holds some elements.
2. Send a batch with two operations:
   - `NFT_MSG_DELRULE` β€” deletes the rule, which implicitly deletes the
     lookup expression and the anonymous `nft_set`;
   - `NFT_MSG_DELSETELEM` β€” deletes an element of the *already deleted*
     anonymous set.
3. The batch is accepted. `nf_tables_commit_release()` queues resources
   onto `nf_tables_destroy_list`, processed later by
   `nf_tables_trans_destroy_work()`:
   - first `nft_commit_release()` β†’ `nf_tables_rule_destroy()` β†’
     `nft_lookup_destroy()` β†’ `nft_set_destroy()` β†’ `kvfree()` frees the
     `nft_set`;
   - then, for `NFT_MSG_DELSETELEM`, `nf_tables_set_elem_destroy()` calls
     `nft_set_elem_ext()` which dereferences the **freed** `nft_set`:

     ```c
     static inline struct nft_set_ext *nft_set_elem_ext(const struct nft_set *set,
                                                        void *elem)
     {
         return elem + set->ops->elemsize;
     }
     ```

If `set->ops->elemsize` is corrupted, an attacker-chosen memory location
is interpreted as an `nft_set_ext` β€” the primitive everything else builds
on.

### Exploitation chain (as reproduced)

1. **Win the race** against `nf_tables_trans_destroy_work()` running on a
   background worker thread: insert a large set-destroy operation as a
   controlled delay, pin other CPUs busy, and reallocate the freed
   `nft_set` chunk from the same CPU with an `nft_set` of a *different
   type* (different `elemsize`) β†’ type confusion.
2. **Craft corrupted `nft_set_ext` headers** with out-of-range offsets so
   `nf_tables_set_elem_destroy()` walks adjacent chunks as a list of
   `nft_expr` to destroy.
3. **Spray `nft_log` expressions** with controlled `NFTA_LOG_PREFIX`;
   `nft_log_destroy()` frees `priv->prefix`, giving an overlapping
   allocation primitive in kmalloc-{8..192} (NULL-byte-limited at first).
4. **Reclaim with `nft_object->udata`** to lift the NULL-byte restriction
   on the dangling read.
5. **`nft_dynset` element spray** for two stateful expr types:
   - `nft_counter` β€” leaks `nft_counter_ops` β†’ base of `nf_tables.ko`
     (defeats KASLR for the module);
   - `nft_quota` β€” `consumed` pointer gives arbitrary read
     (`NFT_MSG_GETSETELEM` β†’ `nft_quota_do_dump()` β†’ `NFTA_QUOTA_CONSUMED`)
     and arbitrary write (`nft_overquota()` adds `skb->len` to
     `*priv->consumed` on loopback traffic).
6. **Overwrite `modprobe_path`** ("/sbin/modprobe" β†’ "//tmp/modprobe") β†’
   root process execution with attacker-controlled content.

Notably, the primitives chosen avoid anything CFI would block β€” no
indirect-call hijacking needed at any step.

### Defensive takeaways

- **Fix**: upstream validates batch operations against the full
  transaction state; patched kernels reject the DELRULE+DELSETELEM
  sequence on the anonymous set. See the fixing commits referenced in the
  NVD entry.
- **Mitigations that raise the bar**: slab freelist hardening
  (`SLAB_FREELIST_HARDENED`), `INIT_ON_FREE`, and per-CPU slab reuse
  restrictions all attack step 1; CFI (where present) constrains step 3+.
- **Detection ideas**: audit rules on `nf_tables` batch netlink messages
  containing DELRULE+DELSETELEM on anonymous sets; crash triage for
  `nft_set_elem_ext` / `nf_tables_trans_destroy_work` in the stack.
- **Attack surface reduction**: `nftables` requires `CAP_NET_ADMIN`, but
  unprivileged user namespaces grant it β€” this is why
  `kernel.unprivileged_userns_clone=0` is a meaningful hardening knob.

---

## Reproduction Guide

Tested under Ubuntu 23.04 (Lunar Lobster), kernel 6.2.0-20-generic.

### Installing Build Dependencies

```bash
sudo apt install gcc libmnl-dev libnftnl-dev
```

### Building Binary

```bash
gcc -Wall -o exploit exploit.c -lmnl -lnftnl
```

### Profile

The built-in profile targets the Ubuntu 23.04 binary kernels
(`linux-image-6.2.0-20-generic` 6.2.0-20.20). To test other kernels,
extract symbols into a `profile` file:

```bash
modprobe nf_tables
egrep ' (nft_counter_ops|nft_counter_destroy|free_percpu|modprobe_path)(\s|$)' /proc/kallsyms > profile
```

Machine-code layout of `nft_counter_destroy()` varies with compiler and
options; see [ORIGIN.md](ORIGIN.md) for the full parameter reference
(`nft_counter_destroy_call_offset/mask/check`) and race-tuning knobs
(`race_lead_sleep` etc.). Reported success probability is β‰₯80% on idle
bare-metal Intel systems; some microarchitectures (e.g. Alder Lake) need
extra tuning.

### Safety Warning

The PoC leaves the kernel in an unstable state with corrupted memory
after a successful run. **Only test on a dedicated, disposable system or
VM snapshot** β€” never on anything with data you care about.

---

## Files

- `exploit.c` β€” PoC source (by [@Liuk3r](https://github.com/Liuk3r/CVE-2023-32233))
- `ORIGIN.md` β€” original vulnerability & exploitation write-up (by Liuk3r)
- `README.md` β€” this file: reproduction + my analysis notes

## References

- [NVD β€” CVE-2023-32233](https://nvd.nist.gov/vuln/detail/CVE-2023-32233)
- [Liuk3r/CVE-2023-32233 β€” original PoC & write-up](https://github.com/Liuk3r/CVE-2023-32233)
- [Theori β€” CVE-2023-32233: Linux Kernel Privilege Escalation Analysis](https://theori.io/blog/cve-2023-32233-linux-kernel-privilege-escalation)

*Research conducted for defensive/educational purposes in an isolated lab
environment.*