远程发现了一个&
用于透明进程间
通信 (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`跟踪:
/* 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];
};
这些记录在对等点之间传输,每个节点都会
在 `tipc_peer->domain` 字段中保存
从每个对等点接收到的最新域记录的副本。
记录由函数 `tipc_mon_rcv` 处理,该函数检查
从对等方接收到的`STATE_MSG`,以查看消息正文是否包含
有效的`struct tipc_mon_domain`:
...
/* 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;
}
该函数执行一些基本的健全性检查 [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 删除。