Linux 内核本地提权严重漏洞预警

发表于:2019-2-28 09:41

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:信息安全搬运工    来源:今日头条

  漏洞编号和级别
  CVE 编号:CVE-2019-8912,危险级别:严重,CVSS 分值:9.8
  影响版本
  Linux 2 .6 ~ Linux 4.20.11
  Red Hat Enterprise Linux 7,Package: kernel-alt
  Debian,Release:Jessie,Version:3.16.56-1+deb8u1
  Debian,Release:Jessie (security),Version:3.16.56-1
  Debian,Release:stretch,Version:4.9.144-3
  Debian,Release:stretch (security),Version:4.9.110-3+deb9u6
  Debian,Release:buster,Version:4.19.16-1
  Debian,Release:sid,Version:4.19.20-1
  漏洞概述
  近日,Linux git 中发布一个 commit 补丁,该补丁对应的漏洞是一个本地提权漏洞 CVE-2019-8912,漏洞影响范围较广。根据 git 中的 commit 信息可知,该漏洞出现在内核 'crypto/af_alg.c'中的af_alg_release 函数中,可以通过 sockfs_setattr 函数触发,漏洞类型是 use after free,可以导致本地代码执行进行权限提升。
  Linux Crypto 模块简介Linux 内核从版本2.5 开始引入了加密机制,为内核提供加密功 能,应用包括:硬件加密设备驱动、内核代码签名、硬件随机数生成器、文件系统加密等。 从版本 2.6.6 之后,内核源码提供了丰富的密码学算法支持,并可以通过配置编译选项将加 密算法作为模块编入内核。内核编译配置如下图所示:
  
  但是该加密功能提供的 API 接口只能在内核层进行使用,用户层无法调用。2010 年, 有位维护者向Linux Crypto 维护组提交了一份 Crypato API 用户接口,类似于netlink,基 于socket 进行通信,便于用户层访问内核加密子系统。功能实现代码在文件crypto/af_alg.c 中。
  漏洞验证
  漏洞存在于 crypto 模块中的 af_alg_release()函数中。af_alg_release()函数在进行对象 释放时,未将对象置空。对应commit:9060cb719e61b685ec0102574e10337fa5f445ea 补 丁代码如下,补丁添加了一行代码:sock->sk = NULL;
 
  在未添加补丁之前,如果该 sock->sk 引用计数是1,当调用sock_put()进行释放后没有 置空,就直接返回,会产生一个 sock->sk 悬挂指针。
  为了分析这个漏洞的前因后果,先分析下相关的socket 代码。对每个新创建的socket, Linux 内核都将在 sockfs 中创建一个新的 inode。Sockfs_*系列函数就是用来操作 sockfs 文 件系统的。Sockfs_setattr()函数就是设置 socket 文件属性的。在 net/socket.c 文件中 sockfs_setattr()函数将会使用sock->sk 对象。
  根据提交的commit:9060cb719e61b685ec0102574e10337fa5f445ea 细节可知,在该 漏洞披露之前,Linux 已经修复了sock_close()和sockfs_setattr()之间的条件竞争漏洞,对应 commit 为 6d8c50dcb029872b298eea68cc6209c866fd3e14,具体先看下 sockfs_setattr() 函数中的补丁。补丁代码如下:
  
  行 544,首先判断 sock->sk 是否为空,如果不为空,行 545 再将用户层传进来的 iattr->ia_uid 赋值为sock->sk->sk_uid。然后看sock_close ()函数中的补丁。补丁代码如下:
  
  行1186,替换成了新函数__sock_release(),该函数多了一个参数inode。__sock_release() 函数实现如下:
  行 601,对 inode 进行判断,如果不为空,然后调用 inode_lock()函数对其进行上锁。 其实该 inode 本身和要进行释放的 socket 对象是对应的。行 603,调用 ops 中 release()函 数进行释放操作。这个ops 中release()函数只是一个函数指针,最终会根据用户注册哪种套 接字类型决定。行 604,再次判断 inode 是否为空,如果不为空,再进行解锁。通过对 inode 加锁,防止在对socket 对象释放时进行其他操作。
  从 commit :6d8c50dcb029872b298eea68cc6209c866fd3e14 提供的细节可知, sock_close()函数和 sockfs_setattr()函数之间的条件竞争可以通过用户层 fchownat()函数引 发。根据man 手册可知,该函数是用于设置文件属性的,例如 uid 和gid,在内核中对应的 sockfs_setattr()函数,如下图所示:
  
  细节中描述,该函数不会保持文件 fd 的引用计数,这也是导致存在条件竞争的原因。 根据前文可知,sockfs_setattr()函数其实就是设置 UID 才操作sock->sk 对象的。
  如果再继续向前追溯的话,从 commit:86741ec25462e4c8cdce6df2f41ead05568c7d5e 提供的细节可知UID 的来龙去脉。该补丁提交于2016 年。由于socket 协议中的结构体struct sock 在大多时候都是和用户层的 sockets 一一映射的,sockets 对应的内核结构体为 struct socket。考虑到方便操作,便通过向 struct sock 添加一个sk_uid 字段来简化对struct socket中的UID 的匹配,也因此添加了一个关键函数。如下图所示:
 
  由此可知,本来存在于 sock_close()和sockfs_setattr 之间的条件竞争已经被修复,由于 crypto/af_alg.c 中af_alg_release()函数没有将释放后的 sock->sk 及时置空,导致前面所做的 安全补丁全部失效。
  修复建议
  该漏洞补丁已经给出,请及时升级到最新版本。https://github.com/torvalds/linux/co mmit/9060cb719e61b685ec0102574e10337fa5f445ea
  参考链接
  https://access.redhat.com/security/cve/cve-2019-8912
  https://nvd.nist.gov/vuln/detail/CVE-2019-8912
  https://mp.weixin.qq.com/s?__biz=MzAwNTI1NDI3MQ==&mid=2649613887&idx=1 &sn=04b441a67101ef2463e264336b7ccc28&chksm=83063b2fb471b239f308e8906fabb5 1a768b3f492b1f88ed4ab259ca062c1ff1e2bcefaaed29&mpshare=1&scene=1&srcid=0225 kHPQ674XTCwBWcOAH1ef#rd

     上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号