CVE-2023-31436 Linux 内核数组越界漏洞分析与利用
字数 1137 2025-08-18 11:36:36

CVE-2023-31436 Linux内核数组越界漏洞分析与利用教学文档

1. 漏洞概述

CVE-2023-31436是Linux内核网络调度器QFQ(Quick Fair Queueing)中的一个数组越界漏洞,存在于net/sched/sch_qfq.c文件中。该漏洞允许本地攻击者通过精心构造的网络数据包实现权限提升。

2. 漏洞分析

2.1 漏洞根源

漏洞位于qfq_change_class()函数中,当用户态没有提供TCA_QFQ_LMAX参数时,会直接使用网卡的MTU作为lmax值,且未进行适当校验:

if (tb[TCA_QFQ_LMAX]) {
    lmax = nla_get_u32(tb[TCA_QFQ_LMAX]);
    if (lmax < QFQ_MIN_LMAX || lmax > (1UL << QFQ_MTU_SHIFT)) {
        pr_notice("qfq: invalid max length %u\n", lmax);
        return -EINVAL;
    }
} else
    lmax = psched_mtu(qdisc_dev(sch)); // [1] 漏洞点

特别地,loopback网卡的MTU可以被设置为2^31-1,这会导致后续计算出现问题。

2.2 漏洞触发路径

  1. qfq_change_class()中未校验的lmax被传递给qfq_init_agg()
  2. qfq_update_agg()中,使用lmax计算索引i
    int i = qfq_calc_index(agg->inv_w, agg->budgetmax, q->min_slot_shift);
    agg->grp = &q->groups[i]; // [4] 越界访问点
    
  3. q->groups数组大小仅为25(QFQ_MAX_INDEX + 1),当i超过25时会导致越界访问

3. 漏洞利用

3.1 利用原语

漏洞提供了两种利用原语:

  1. qfq_slot_insert原语

    • 通过hlist_add_head()实现越界指针写入
    • 通过__set_bit()实现越界位设置
  2. qfq_schedule_agg原语

    • 通过控制grp->index实现__set_bit()的越界写

3.2 利用策略

  1. 堆布局

    • 使用dyn-kmalloc-8192堆喷qdisc_size_table对象
    • 使用kmalloc-128堆喷xdp_umem对象
  2. 类型混淆

    • 通过越界写修改相邻qdisc->filter_list指针
    • 使其指向xdp_umem对象,利用xdp_umem->addrstcf_proto->next重叠的特性
  3. 控制流劫持

    • 用户态控制共享内存中的next指针指向伪造的tcf_proto结构
    • 通过tp->classify函数指针实现ROP

3.3 关键数据结构

struct qfq_sched {
    struct tcf_proto __rcu *filter_list;
    struct tcf_block *block;
    struct Qdisc_class_hash clhash;
    u64 oldV, V;
    struct qfq_aggregate *in_serv_agg;
    u32 wsum;
    u32 iwsum;
    unsigned long bitmaps[QFQ_MAX_STATE];
    struct qfq_group groups[QFQ_MAX_INDEX + 1]; // 大小25
    u32 min_slot_shift;
    u32 max_agg_classes;
    struct hlist_head nonfull_aggs;
};

4. 补丁分析

补丁将lmax的校验移到了所有获取路径之后:

 if (tb[TCA_QFQ_LMAX])
     lmax = nla_get_u32(tb[TCA_QFQ_LMAX]);
 else
     lmax = psched_mtu(qdisc_dev(sch));
+if (lmax < QFQ_MIN_LMAX || lmax > (1UL << QFQ_MTU_SHIFT)) {
+    pr_notice("qfq: invalid max length %u\n", lmax);
+    return -EINVAL;
+}

5. 防御与缓解

  1. 及时更新内核补丁
  2. 限制非特权用户设置网络设备参数的能力
  3. 启用内核地址空间布局随机化(KASLR)
  4. 启用SMAP/SMEP保护

6. 变体分析与审计建议

  1. 审计所有从设备属性获取参数的代码路径
  2. 特别注意loopback等特殊设备的属性设置
  3. 检查所有数组索引计算前的边界校验
  4. 关注网络子系统中类似QFQ的调度器实现

7. 参考资源

  1. 官方补丁
  2. Google安全研究漏洞分析
  3. 侧信道攻击工具
CVE-2023-31436 Linux内核数组越界漏洞分析与利用教学文档 1. 漏洞概述 CVE-2023-31436是Linux内核网络调度器QFQ(Quick Fair Queueing)中的一个数组越界漏洞,存在于 net/sched/sch_qfq.c 文件中。该漏洞允许本地攻击者通过精心构造的网络数据包实现权限提升。 2. 漏洞分析 2.1 漏洞根源 漏洞位于 qfq_change_class() 函数中,当用户态没有提供 TCA_QFQ_LMAX 参数时,会直接使用网卡的MTU作为 lmax 值,且未进行适当校验: 特别地,loopback网卡的MTU可以被设置为 2^31-1 ,这会导致后续计算出现问题。 2.2 漏洞触发路径 qfq_change_class() 中未校验的 lmax 被传递给 qfq_init_agg() 在 qfq_update_agg() 中,使用 lmax 计算索引 i : q->groups 数组大小仅为25( QFQ_MAX_INDEX + 1 ),当 i 超过25时会导致越界访问 3. 漏洞利用 3.1 利用原语 漏洞提供了两种利用原语: qfq_ slot_ insert原语 : 通过 hlist_add_head() 实现越界指针写入 通过 __set_bit() 实现越界位设置 qfq_ schedule_ agg原语 : 通过控制 grp->index 实现 __set_bit() 的越界写 3.2 利用策略 堆布局 : 使用 dyn-kmalloc-8192 堆喷 qdisc_size_table 对象 使用 kmalloc-128 堆喷 xdp_umem 对象 类型混淆 : 通过越界写修改相邻 qdisc->filter_list 指针 使其指向 xdp_umem 对象,利用 xdp_umem->addrs 与 tcf_proto->next 重叠的特性 控制流劫持 : 用户态控制共享内存中的 next 指针指向伪造的 tcf_proto 结构 通过 tp->classify 函数指针实现ROP 3.3 关键数据结构 4. 补丁分析 补丁将 lmax 的校验移到了所有获取路径之后: 5. 防御与缓解 及时更新内核补丁 限制非特权用户设置网络设备参数的能力 启用内核地址空间布局随机化(KASLR) 启用SMAP/SMEP保护 6. 变体分析与审计建议 审计所有从设备属性获取参数的代码路径 特别注意loopback等特殊设备的属性设置 检查所有数组索引计算前的边界校验 关注网络子系统中类似QFQ的调度器实现 7. 参考资源 官方补丁 Google安全研究漏洞分析 侧信道攻击工具