CVE-2022-25636内核越界写入漏洞对容器的影响分析
0x 漏洞影响
影响范围:Linux内核版本5.4-5.6.10
漏洞危害:漏洞允许低权限用户获得root权限
漏洞组件:Netfilter
补丁情况:各发行版均已发布补丁
Poc情况:已知公开Poc可在特定版本内核一定概率实现提权,尚无稳定利用。
容器影响:此漏洞本质是由越界写入引发的内核任意代码执行,所以容器环境中如果成功利用会直接导致逃逸事件发生。但是由于利用漏洞至少需要CAP_NET_ADMIN,一定程度上可以缓解容器中的利用。
1x 漏洞原理
漏洞的成因是一个内存越界写入。
位于linux\net\netfilter\nf_dup_netdev.c的nft_fwd_dup_netdev_offload函数中,第67行,在给entry赋值的时候引用了来自外部的ctx->num_actions,并且进行了自增操作,但是在此之前没有对它进行边界检查。导致特定情况下entry指向flow结构以外,并且接下来对entry进行了写操作,这就构成了内核的内存越界写入。
通过查看调用来源,我们发现nft_fwd_dup_netdev_offload函数在linux\net\netfilter\nf_tables_offload.c的nft_flow_rule_create函数中被调用,我们检查一下调用的部分代码:
可以看到nft_flow_rule_create函数首先遍历了传入的rule,也就是用户传入的规则,然后对包含NFT_OFFLOAD_F_ACTION标记的规则进行了计数,保存在num_actions中。紧接着,根据num_actions的大小,为flow申请了空间。这时,flow的大小有可能无法容纳全部的规则(因为不包含NFT_OFFLOAD_F_ACTION标记的规则没有被统计)。而在不远处,代码里再一次对rule进行了遍历,并且没有判断NFT_OFFLOAD_F_ACTION标记,而在这段代码中,将flow作为参数传入nft_fwd_dup_netdev_offload函数。
回顾一下nft_fwd_dup_netdev_offload函数的代码,其中对ctx->num_actions进行了自增操作。
这意味着如果传入的rule中存在一部分不包含NFT_OFFLOAD_F_ACTION标记的规则,ctx->num_actions最终会大于flow的大小,造成越界访问,而紧接着的两行赋值代码,则会造成内核的越界写入。
2x 漏洞利用
根据公开的Exp,漏洞利用很不稳定,作者称只有约40%成功率,经过笔者测试,实际稳定利用率比作者宣称的还要低。由于Exp中使用了大量硬编码地址,在不同版本内核,甚至相同版本但不同参数编译的内核中,公开的Exp可能会失效并导致内核崩溃。即使是成功的利用,由于利用过程中使用了内核堆喷射、UAF利用及ROP等技术,可能会覆盖内核堆中的一些重要数据,依然有不小的概率导致利用成功后内核崩溃。
3x Exp
虽然成功利用的概率不高,并且公开的Exp并不通用,但是作为一个利用难度极高的漏洞,Exp的构造非常巧妙,值得一提。
在Exp的开头,使用fuse注册了一个用户态文件系统,这将用于替代userfaulted对特定地址进行覆盖。
紧接着是泄露net_device的地址,由于需要泄露两个不同的net_device地址,采用了双进程,一个在父进程泄露,一个在子进程泄露。
在leak_heap中,实际调用了do_heap_leak来实现功能。在do_heap_leak
中,使用了msg_msg技术来实现地址泄露。
先通过喷射特定大小的msg实现堆内存布局,然后释放掉其中一部分,紧接着vuln函数内部试图抢占刚刚释放的内存,并且实现越界写入,以覆盖紧邻的msg结构中的一部分。紧接着通过check_heap_leak函数接收全部msg,查看其中是否有越界写入的内容,而这个内容就是一个net_device指针。
紧接着又进行了一次msg喷射,这次的目的是释放掉net_device所占用的内存
这次在vuln函数中使用net_device地址覆盖了msg_msg->security,这导致在接下来的get_msg操作中将net_device释放。
释放掉net_device结构后,紧接着利用setxattr和fuse尝试申请刚刚被释放的内存,并且对net_device结构进行篡改(此时的net_device所占用的内存被释放并重写,但是内核其他部分代码中对它的引用依然有效),在这里将dev_addr 指针替换为为netdev_ops 指针。
完成操作后,通过ioctl读取SIOCGIFHWADDR就拿到了loopback_ops的地址。
接着通过loopback_ops地址计算出了KALSR的偏移,有了这个,就可以准备ROP代码了。准备完成后,通过一次同样的setxattr+fuse操作,不过这次是直接篡改net_device 的ethtool_ops为ROP代码地址,这样在执行ioctl(fd, SIOCETHTOOL, &ifr)的时候,就实现了劫持RIP。
整体Exp构思非常巧妙,实现了对一个内核越界写入的完美利用。但依然存在以下缺陷:
1. 成功率不够高。不过这也是这类漏洞的通病,通过堆喷射实现利用几乎不可能做到100%成功。
2. 无法通用。由于ROP代码使用了硬编码,加之Linux内核版本众多,无法实现通用化。
3. 利用失败后果严重。由于是内核越界写入,利用过程中很容易破坏内核内存,导致内核崩溃。
4x 容器化环境的影响
此漏洞本质是由越界写入引发的内核任意代码执行,所以容器环境中如果成功利用会直接导致逃逸事件发生。但是由于利用漏洞至少需要CAP_NET_ADMIN,一定程度上可以缓解容器中的利用。同时由于Exp需要针对精确的内核版本硬编码ROP,所以在大多数环境中不太可能真的用于提权,但是通过写入无效RIP导致host拒绝服务是很容易实现的。
往期推荐
2022-03-10
2021-12-30
2021-12-16
2021-12-10