文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

CVE-2020-14386: Linux kernel权限提升漏洞

2024-12-03 18:53

关注

[[345624]]

技术细节

该漏洞来源于net/packet/af_packet.c 文件的tpacket_rcv 函数中,是由于算术问题引发的内存破坏。该漏洞是2008年7月引入的(commit 8913336),从2016年2月开始触发内存破坏(commit 58d19b19cd99),很多开发者都尝试修复该漏洞,但提出的补丁都不足以预防内存破坏。

为触发该漏洞需要创建一个含有TPACKET_V2 ring缓存和 PACKET_RESERVE为特定值的原始包(AF_PACKET domain, SOCK_RAW type )。


headroom 是用户指定大小的缓存,会在ring 缓存接收每个包的真实数据之前分配。该值可以通过setsockopt 系统调用在用户空间来设置:

图 1. Setsockopt设置 – PACKET_RESERVE

如图 1所示,会检查该值是否小于INT_MAX。该值是在补丁(https://lore.kernel.org/patchwork/patch/784412/)中新加的以防packet_set_ring 中最小帧大小计算溢出。然后回验证页面是否是为接收或者传输的ring缓存分配的。这么做的目的是预防tp_reserve 域和ring buffer之间的不连续。

在设置了tp_reserve 值后,就可以通过含有PACKET_RX_RING的setsockopt系统调用来触发ring缓存的分配:

图 2. From manual packet – PACKET_RX_RING option.

这是在packet_set_ring函数中实现的。在ring缓存分配之前,会有许多对从用户空间接收的 tpacket_req结构的检查:

图 3. packet_set_ring 函数中的安全检查

从图 3中可以看出,首先会计算最小的帧大小,然后与从用户空间接收到的值进行对比验证。检查确保了在 tpacket 头结构的每个帧和tp_reserve 字节数之间的有空间。

在做完所有检查之后,ring缓存本身就会通过 alloc_pg_vec调用来分配:

图 4. packet_set_ring 函数中调用ring缓存分配函数

如上图所示,block size(区块大小)是由用户空间控制的。alloc_pg_vec函数会分配 pg_vec数组,然后通过alloc_one_pg_vec_page 函数分配给每一个区块链:

图 5. alloc_pg_vec实现

alloc_one_pg_vec_page 函数会用 __get_free_pages 来分配区块页:

图 6. alloc_one_pg_vec_page 实现

区块分配后,pg_vec 数组就会保存在嵌入在 packet_sock结构中的packet_ring_buffer结构。

当接口接收到包后,与tpacket_rcv函数绑定的socket、包数据、TPACKET 元数据都会写入到ring缓存中。

漏洞

图7是 tpacket_rcv 函数的实现。首先,会调用skb_network_offset 来提取接收到的包的网络头的偏移值到maclen中。在本例中,大小为14字节,即以太网header的大小。之后,会根据TPACKET header、 maclen 和tp_reserve值来计算netoff。

但是计算的过程可能会溢出,因为 tp_reserve的类型是 unsigned int ,netoff的类型是unsigned short,而对tp_reserve 值的唯一限制是小于INT_MAX。 

图 7. tpacket_rcv中的算术计算

如图 7所示,如果包中设置了PACKET_vnet_HDR ,就会加入sizeof(struct virtio_net_hdr) 。最后,以太网header的偏移量会计算会保存到macoff中。

如图 8所示, virtio_net_hdr结构会用 virtio_net_hdr_from_skb函数下入ring缓存中。 h.raw 指向ring 缓存中当前空闲的帧。

图 8. 调用tpacket_rcv中的 virtio_net_hdr_from_skb函数

研究人员设想有可能利用该溢出将netoff变成一个更小的值,所以macoff 可以接收一个大于block size的值,并尝试写入缓存中。

但是存在以下检查,所以无法实现:

图 9. tpacket_rcv 函数中的另一个检查

但是该检查并不足以预防内存破坏,因为仍然可以通过溢出netoff 将macoff变成一个小一点的值。比如,将macoff变成小于10字节的 sizeof(struct virtio_net_hdr),然后用 virtio_net_hdr_from_skb 写入缓存的边界。

原语

通过控制macoff的值,就可以在控制的偏移量中初始化 virtio_net_hdr 结构。 virtio_net_hdr_from_skb 函数会首先将整个struct 零化,然后根据skb结构初始化结构内的所有域。

图 10. virtio_net_hdr_from_skb 函数的实现

但可以设置skb 只让零写入结构中。因此,就可以在__get_free_pages 分配中零化1-10个字节。无需任何堆操作技巧就可以立刻引发kernel 奔溃。

POC

触发该漏洞的PoC代码参见:https://www.openwall.com/lists/oss-security/2020/09/03/3

漏洞利用

漏洞利用过程参见:https://unit42.paloaltonetworks.com/cve-2020-14386/

补丁

研究人员提出的补丁参见:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=acf69c946233259ab4d64f8869d4037a198c7f06

图 11. 研究人员提出的补丁

补丁的思想是如果将netoff 的类型从unsigned short 修改为unsigned int,就可以检查是否会超过USHRT_MAX,如果超过的化就丢弃该包,以防进一步利用。

总结

研究人员其实也很奇怪Linux kernel中至今还会存在如此简单的算术安全问题,而且之前没有被发现过。同时,非特权的用户空间也暴露出了本地权限提升的巨大攻击面。

 

来源:嘶吼网内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯