前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CVE-2022-0435:Linux 内核中的远程堆栈溢出

CVE-2022-0435:Linux 内核中的远程堆栈溢出

作者头像
Khan安全团队
发布2022-02-11 09:15:34
1.8K0
发布2022-02-11 09:15:34
举报
文章被收录于专栏:Khan安全团队
代码语言:javascript
复制
远程发现了一个&
用于透明进程间
通信 (TIPC) 协议的 Linux 内核网络模块中的本地可访问堆栈溢出。

虽然该模块可以在大多数主要发行版中找到,但必须
加载它才能被利用。此外,对于远程利用
,目标需要已经设置了 TIPC 承载,即
漏洞扩展到使用 TIPC 的系统。
利用是微不足道的,并且可能通过内核恐慌

导致拒绝服务。在没有或绕过堆栈金丝雀/KASLR 的情况下,
漏洞可能导致任意
有效载荷的控制流劫持。
自内核版本 4.8 中引入 TIPC 监控框架

以来,该漏洞一直存在。
- 引入:commit 35c55c9877f8(“tipc:添加邻居监控框架”)
- 修正:https ://github.com/torvalds/linux/commit/9aa422ad326634b76309e8ff342c246800621216 
================= ==================================================== =====
分析
============================================== =============================
透明进程间通信(TIPC)是一种
为集群内通信设计的IPC机制。集群拓扑被管理




围绕节点的概念以及这些节点之间的链接。

TIPC 模块的众多功能之一是其监控框架。
该框架于 2016 年 6 月引入内核(提交 35c55c9),允许节点监控网络拓扑并与
同一域中的
其他节点共享其视图。
对等点状态通过`struct tipc_peer`跟踪:
代码语言:javascript
复制
    /* struct tipc_peer: state of a peer node and its domain
     * @addr: tipc node identity of peer
     * @head_map: shows which other nodes currently consider peer 'up'
     * @domain: most recent domain record from peer
     * @hash: position in hashed lookup list
     * @list: position in linked list, in circular ascending order by 'addr'
     * @applied: number of reported domain members applied on this monitor list
     * @is_up: peer is up as seen from this node
     * @is_head: peer is assigned domain head as seen from this node
     * @is_local: peer is in local domain and should be continuously monitored
     * @down_cnt: - numbers of other peers which have reported this on lost
     */
    struct tipc_peer {
        u32 addr;
        struct tipc_mon_domain *domain;
        struct hlist_node hash;
        struct list_head list;
        u8 applied;
        u8 down_cnt;
        bool is_up;
        bool is_head;
        bool is_local;
    };
...

`struct tipc_mon_domain` referends a domain record, used to define that
peers view of the TIPC topology:

...
    #define MAX_MON_DOMAIN       64
    ...

    /* struct tipc_mon_domain: domain record to be transferred between peers
     * @len: actual size of domain record
     * @gen: current generation of sender's domain
     * @ack_gen: most recent generation of self's domain acked by peer
     * @member_cnt: number of domain member nodes described in this record
     * @up_map: bit map indicating which of the members the sender considers up
     * @members: identity of the domain members
     */
    struct tipc_mon_domain {
        u16 len;
        u16 gen;
        u16 ack_gen;
        u16 member_cnt;
        u64 up_map;
        u32 members[MAX_MON_DOMAIN];
    };
代码语言:javascript
复制
这些记录在对等点之间传输,每个节点都会
在 `tipc_peer->domain` 字段中保存
从每个对等点接收到的最新域记录的副本。
记录由函数 `tipc_mon_rcv` 处理,该函数检查
从对等方接收到的`STATE_MSG`,以查看消息正文是否包含
有效的`struct tipc_mon_domain`:
...

代码语言:javascript
复制
   /* tipc_mon_rcv - process monitor domain event message
     *
     * @data: STATE_MSG body
     * @dlen: STATE_MSG body size (taken from TIPC header)
     */
    void tipc_mon_rcv(struct net *net, void *data, u16 dlen, u32 addr,
        struct tipc_mon_state *state, int bearer_id)
    {
        ...
        struct tipc_mon_domain *arrv_dom = data;
        struct tipc_mon_domain dom_bef;
        ...

        /* Sanity check received domain record */                        [0]
        if (dlen < dom_rec_len(arrv_dom, 0))                             [1]
            return;
        if (dlen != dom_rec_len(arrv_dom, new_member_cnt))               [2]
            return;
        if (dlen < new_dlen || arrv_dlen != new_dlen)                    [3]
            return;
        ...

        /* Drop duplicate unless we are waiting for a probe response */
        if (!more(new_gen, state->peer_gen) && !probing)                 [4]
            return;
        ...

        /* Cache current domain record for later use */
        dom_bef.member_cnt = 0;
        dom = peer->domain;
        if (dom)                                                         [5]
            memcpy(&dom_bef, dom, dom->len);                             [6]

        /* Transform and store received domain record */
        if (!dom || (dom->len < new_dlen)) {
            kfree(dom);
            dom = kmalloc(new_dlen, GFP_ATOMIC);                         [7]
            peer->domain = dom;
            if (!dom)
                goto exit;
        }

代码语言:javascript
复制
该函数执行一些基本的健全性检查 [0 
        ]
以确保 a)
消息正文实际上包含域记录,并且 b) 它是否包含
有效的 `struct tipc_mon_domain`。
其中 `data` 是消息正文, `dlen` 是
从消息头中获取的 `data` 的长度,该函数检查:



- `data` 的长度足以至少保存一个空记录 [1] - `data` 的长度与
  给定的 `member_cnt` 字段
的域记录的预期大小匹配[2] 
- `data' 的长度` 匹配提供的 `len` 字段 [3]
稍后我们获取发送对等方 `struct peer` 以查看我们是否已经
从他们那里收到了域记录 [5]。如果有,我们想
暂时缓存一份旧记录的副本,以便稍后进行比较 [6]。
然后,确定它是一条新的有效记录,我们将
使用新信息更新 `struct peer->domain` 字段。如果它是第一个域
记录,我们将为此 [7] 创建一个新的“kmalloc”,或者如果它大于
最后一个,我们将重新分配它。



-----------------
漏洞
-----------------

漏洞在于,在初始健全性
检查期间,函数不会检查 `member_cnt` 是否低于
MAX_MON_DOMAIN,它定义了 `members` 数组的最大大小。

通过伪装成对等节点并在本地或远程与目标建立链接
,我们能够首先提交
包含任意有效负载的恶意域记录;只要 len/member_cnt
字段与健全性检查相匹配,这将被 kmallocated 罚款。

接下来,我们可以发送一个更新的域记录,这将导致以前的
恶意记录被 memcpy 到一个 272 字节的本地
`struct tipc_mon_domain` &dom_bef [6] 触发堆栈溢出。
这允许我们使用来自首先提交的恶意域记录
的任意成员缓冲区覆盖 &dom_bef

之后的堆栈内容;其大小受媒体
MTU(以太网、UDP、Inifiband)限制
================================= =========================================

 
================================= =========================================
补救
========== ==================================================== ============自
2016 年 6 月首次引入

监控框架以来,此漏洞一直存在,影响 4.8 版本。
下面的补丁是在提交 9aa422ad3266 中引入的,因此更新您的
系统以包含此补丁是缓解 CVE-2022-0435 的最佳方法,
其中包括由 Eric Dumazet 发现的额外 u16 溢出。


必须加载 TIPC 模块以使系统易受攻击,
此外,要远程定位系统需要
启用 TIPC 承载。如果您不需要使用 TIPC 或不确定是否需要,
您可以采取以下步骤:

- `$ lsmod | grep tipc` 将让您知道模块当前是否已
  加载,
- `modprobe -r tipc` 可能允许您卸载已加载的模块,
  但是您可能需要重新启动系统
- `$ echo "install tipc /bin/true" >> /etc/modprobe.d/disable-tipc.conf`
  会阻止模块被加载,如果你
  没有理由使用它,这是一个好主意如果

你需要使用TIPC并且不能立即给你的系统打补丁, 看
强制执行任何阻止或限制
攻击者模仿集群中节点的能力的配置。选项包括 TIPC
协议级加密、IPSec/MACSec、网络分离等。

还值得注意的是,当前的“CONFIG_FORTIFY_SRC=y”是
利用 CVE-2022-0435 进行控制流劫持的硬性缓解措施,因为它
会进行边界检查关于有问题的 memcpy 的大小并导致
内核恐慌。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档