CTF-Writeups

extended-eBPF

Summary

The service runs a custom kernel with an “extended” eBPF verifier bug. A BPF program can build an arbitrary 64-bit offset using a non-constant shift, then add it to a map value pointer without a proper bounds check. This gives out-of-bounds read/write relative to the map value and lets us locate and overwrite the current task’s cred struct to become root and read /flag.

Vulnerability

The program lets a user provide a list of (shift, enable) slots. The BPF program computes:

offset = sum_i ( (1ULL << (shift_i & 63)) * (enable_i & 1) )

The verifier accepts the non-constant shift and the accumulated scalar, then allows adding that scalar to a map value pointer. With 64 slots this builds any 64-bit value, so we can point outside the map value and read/write arbitrary kernel memory near the map allocation. This is the “non-constant shift is too big of an extension” bug hinted by the flag.

Exploit

1) Create a BPF array map with a large value size. The map value is a control structure:

2) Load a BPF program that:

3) Use the read primitive to scan memory around the map value for a cred struct. The scan checks:

4) When a candidate matches, overwrite its fields:

If getuid() becomes 0, spawn a shell and read the flag. If not, restore the original fields and keep scanning.

Reproduction

From the challenge directory:

gcc -O2 -s exploit.c -o exploit
python run_exploit.py

The script solves the PoW, logs in as ctf, uploads the binary, and runs it. You should see uid=0(root) and the flag.

Flag

uoftctf{n0n_c0ns74n7_shif7_is_700_big_0f_4n_3x73nsi0n}