!
也想出现在这里? 联系我们
广告位
当前位置:首页>安全咨询>漏洞复现>Linux内核的本地提权漏洞CVE-2022-1015

Linux内核的本地提权漏洞CVE-2022-1015

漏洞描述

netfilter子系统的linux/net/netfilter/nf_tables_api.c中发现了Linux内核的一个缺陷。此漏洞允许本地用户导致越界写入问题。
 


 

影响版本

Linux内核版本 5.16-rc3
 


 

漏洞分析

初始点

2022 4 月,David Bouman 发布了一篇关于 Linux 内核漏洞的文章。我将兴趣集中在 CVE-2022-1015 上,因为它是我的变体分析的目标。这个漏洞非常有趣,因为一些越界漏洞的发生是因为用户输入检查没有很好地实现。此外,这种错误可以在 Linux 内核和用户态应用程序中找到。与此漏洞相关的错误是位于函数nft_validate_register_load( /net/netfilter/nf_tables_api.c) 中的整数溢出(0)

static int nft_validate_register_load(enum nft_registers reg, unsigned int len)

{
    if (reg < NFT_REG_1 * NFT_REG_SIZE / NFT_REG32_SIZE)
        return -EINVAL;

    if (len == 0)
        return -EINVAL;

    if (reg * NFT_REG32_SIZE + len > sizeof_field(struct nft_regs, data))           <===== (0)
        return -ERANGE;

    return 0;
}

在阅读并理解了这个漏洞的工作原理之后,我决定编写一个 CodeQL 查询来找到这个漏洞。对查询的不同结果的分析导致了 CVE-2022-1015 变体的几个候选者。

错误

其中一个候选人引起了我的注意,它位于函数nft_set_desc_concat_parse( /net/netfilter/nf_tables_api.c) 内部。



(1)处,我们识别与查询匹配的模式。

让我们关注比较的左侧部分len * BITS_PER_BYTE / 32len是从带有 的 netlink 消息中提取的 32 位整数nla_get_be32,因此我们可以假设这是用户可控制的。宏BITS_PER_BYTE定义在/include/linux/bits.h.


乘法len * BITS_PER_BYTE将导致左移三位。下一个算术运算是除以 32,这将导致右移 5 位。我们知道有 5 len被忽略,其中 3 位最重要,2 位较不重要。

现在,让我们看一下比较的右侧。宏NFT_REG32_COUNT在文件中定义/include/uapi/linux/netfilter/nf_tables.h



我们有NFT_REG32_COUNT等于23 - 8 + 1 = 16

如果我们反转条件(1)以得到条件 on len,我们得到len < 64。然而,在这个比较中,五位被忽略了,所以这五位可以用来存储不需要的值(2)

下一步是为随机的非特权用户找到一种方法来访问此错误代码。
 

非特权访问

内核 netfilter 模块可以从定义在/net/netfilter/nfnetlink.c.



at结构的input字段为我们提供了当通过 netfilter netlink 接收到消息时将调用的函数。让我们看看这个处理程序。netlink_kernel_cfg(3)



(4)我们看到由函数完成的能力检查,netlink_net_capable用户必须具有CAP_NET_ADMIN使用 netfilter 的能力。对我们来说幸运的是,这种能力可以通过用户命名空间 ( CONFIG_USER_NS) 获得。在过去的几年里,用户命名空间在 Linux 内核开发中已经改变了游戏规则,他们打开了一组新的攻击面。这有点好笑,因为它们也用于沙盒应用程序,是双刃剑的好例子。

让我们回到我们的主题,我们可以将调用路径从nfnetlink_rcvto映射nft_set_desc_concat_parse如下。



中间函数中没有任何相关信息,所以我们暂时忽略它们。

如果内核编译时CONFIG_USER_NS启用,我们将能够访问易受攻击的代码路径。

Linux内核的本地提权漏洞CVE-2022-1015

 

那么,我们能做些什么呢?

可悲的是,这个错误似乎对 linux 安全性没有任何影响。

实际上, at 的赋值(2)是将 32 位无符号整数转换为 8 1,因为结构的字段类型field_len为。nft_set_descu8



由于无法使用两个较低有效位,因此它大大降低了此溢出的功率。
 

一个陌生的邻居

然而,这并不是冒险的结束。

当我试图利用之前的错误时,有些事情阻止了我:field_count在分配(2).

的父函数nft_set_desc_concat_parsenft_set_desc_concat( /net/netfilter/nf_tables_api.c)



调用nft_set_desc_concat_parse是在 at 完成的,(6)但最有趣的是调用位于从 开始的循环中(5),并且在 body 循环中没有对 的值进行任何验证desc->field_countnla_for_each_nested将遍历用户提供的所有 netlink 属性,如果用户提供超过NFT_REG32_COUNT,则会发生缓冲区溢出。
 

给我给我一个信息泄露

我们将看到如何将此缓冲区溢出转换为内核信息泄漏。将溢出的第一个字节是field_count存储存储在该字段中的元素数量的字段field_len。我们将利用这个领域来实现我们的目标。
 

网络过滤器集

nft_set我们将使用由结构( )表示的 netfilter /include/net/netfilter/nf_tables.h



这些集合被分配到作为易受攻击函数的父函数的函数nf_tables_newset( ) 中。/net/netfilter/nf_tables_api.cnft_set_desc_concat_parse



(8)我们在导致易受攻击的函数的调用处检索。它的第一个参数是局部变量的地址,desc初始化为(7)。这是将被修改为函数的对象nft_set_desc_concat_parse。我们可以看到它的字段field_countfield_len被使用,(10)它们被存储到新分配的nft_set (9)中。因此,如果越界仅用于覆盖值大于 20 的字段(结构结束 + 对齐),则堆栈中的一些数据将被复制到field_len结构at 中。在这种情况下,它还会在结构中产生越界,但它对我们的泄漏没有用处。descnft_set(10)nft_set
 

回到用户区

下一步是找到一种方法将这些信息发送回用户空间。为了做到这一点,我们将使用可以以类似方式访问的函数nf_tables_getset( ) 。 可用于检索有关已注册集的信息。/net/netfilter/nf_tables_api.cnf_tables_newsetnf_tables_getset



nfnetlink_unicast由于at ,此函数将通过 netfilter netlink 将数据发送到用户空间,(12)并且此数据将设置到对nf_tables_fill_set( /net/netfilter/nf_tables_api.c) 的调用中。



(13)处,另一个辅助功能用于管理有关字段field_len和结构field_count的数据nft_set



正如我们在 处看到的(14),我们将迭代set->field_count多次,并且在每次迭代中,set->field_len缓冲区的一个元素将被添加到 处的套接字缓冲区(15)。因此,如果按照前面的解释已经产生了一对一(2),存储在堆栈中的信息将被复制到堆中,(10)最后,由于套接字,用户将能够访问它们。
 


 

漏洞复现

https://github.com/pqlx/CVE-2022-1015



 

给TA打赏
共{{data.count}}人
人已打赏
漏洞复现

PHP任意文件读取CVE-2022-35650

2022-10-9 22:08:16

漏洞复现

Linux netfilter缓冲区溢出漏洞(CVE-2022-34918)

2022-10-9 22:08:56

声明 本站上的部份代码及教程来源于互联网,仅供网友学习交流,若您喜欢本文可附上原文链接随意转载。无意侵害您的权益,请发送邮件至 admin@s9h.cn 或点击右侧 私信:少羽 反馈,我们将尽快处理。
0 条回复A文章作者M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索