漏洞背景
2018年1月11日,OSS-SEC邮件组披露Libc中的Realpath函数存在缓冲区下溢漏洞,CVE编号为CVE-2018-1000001。漏洞的产生是由于GNU C库没有正确处理getcwd()系统调用返回的相对路径,并且没有对缓冲区边界进行检查,其他库也很可能受此影响。
经过360CERT评估,该漏洞可利用风险等级高,可用于Linux操作系统恶意本地提权root,建议受影响用户尽快完成相应更新。
漏洞影响
Ubuntu受影响情况
链接:https://people.canonical.com/~ubuntu-security/cve/2018/CVE-2018-1000001.html
Debian 受影响情况
链接:https://security-tracker.debian.org/tracker/CVE-2018-1000001
Red Hat 受影响情况
链接:https://access.redhat.com/security/cve/cve-2018-1000001
SUSE 受影响版本
Openstack Cloud Magnum Orchestration 7
SUSE CaaS Platform ALL SUSE Linux Enterprise Desktop 12 SP2
SUSE Linux Enterprise Desktop 12 SP3
SUSE Linux Enterprise Point of Sale 11 SP3
SUSE Linux Enterprise Server 11 SP3-LTSS
SUSE Linux Enterprise Server 11 SP4
SUSE Linux Enterprise Server 12 SP1-LTSS
SUSE Linux Enterprise Server 12 SP2
SUSE Linux Enterprise Server 12 SP3
SUSE Linux Enterprise Server 12-LTSS
SUSE Linux Enterprise Server for Raspberry Pi 12 SP2
SUSE Linux Enterprise Software Development Kit 11 SP4
SUSE Linux Enterprise Software Development Kit 12 SP2
SUSE Linux Enterprise Software Development Kit 12 SP3
SUSE Linux Enterprise for SAP 12 SP1
SUSE OpenStack Cloud 6
openSUSE Leap 42.2
openSUSE Leap 42.3
链接:https://www.suse.com/security/cve/CVE-2018-1000001/
archlinux 受影响情况
链接:https://security.archlinux.org/CVE-2018-1000001
Fedora 所有版本受影响
链接:https://bodhi.fedoraproject.org/updates/FEDORA-2018-8e27ad96ed
漏洞分析
该漏洞涉及到两个方面:
(1)kernel的getcwd系统调用
(2)glibc的realpath函数
虽然官方认为这不是内核的问题,但是内核还是提供了补丁。
linux kernel 补丁地址:
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=52a713fdd0a30e1bd79818e2e3c4ab44ddca1a94
getcwd()系统调用会返回当前工作目录的绝对路径,如果当前目录不属于当前进程的根目录(例如:该进程使用chroot设置了一个新的文件系统根目录,但是没有将当前目录的根目录替换成新的),从linux 2.6.36开始,getcwd会返回“(unreachable)”。通过改变当前目录到另一个挂载的用户空间,普通用户可以完成上述的行为。所以当处理不可信来源的路径时,应该检查返回的路径是否以”/”或”(“开头,避免返回一个不可达地址,被认为是相对地址。
漏洞发生处:glibc stdlib/canonicalize.c 的__realpath函数:
如果解析的是一个相对路径(不是以’/’开头的路径)时,就会调用__getcwd()
if (name[0] != '/')
{
if (!__getcwd (rpath, path_max))
{
rpath[0] = '\0';
goto error;
}
dest = __rawmemchr (rpath, '\0');
}
else
{
rpath[0] = '/';
dest = rpath + 1;
}
如果__getcwd()此时返回的是”(unreachable)”,则接下来在解析路径时,发现路径开头并不包含’/’,会在while循环中不断读取dest之前的地址,产生缓冲区下溢。
else if (end - start == 2 && start[0] == '.' && start[1] == '.')
{
/* Back up to previous component, ignore if at root already. */
if (dest > rpath + 1)
while ((--dest)[-1] != '/');
}
之后操作的dest地址就是溢出的地址。
漏洞攻击效果图:
(根据网上公布的exp代码)
补丁分析
************************************************************
--- stdlib/canonicalize.c 2018-01-05 07:28:38.000000000 +0000
+++ stdlib/canonicalize.c 2018-01-05 14:06:22.000000000 +0000
@@ -91,6 +91,11 @@
goto error;
}
dest = __rawmemchr (rpath, '\0');
+/* If path is empty, kernel failed in some ugly way. Realpath
+has no error code for that, so die here. Otherwise search later
+on would cause an underrun when getcwd() returns an empty string.
+Thanks Willy Tarreau for pointing that out. */
+ assert (dest != rpath);
}
else
{
@@ -118,8 +123,17 @@
else if (end - start == 2 && start[0] == '.' && start[1] == '.')
{
/* Back up to previous component, ignore if at root already. */
- if (dest > rpath + 1)
- while ((--dest)[-1] != '/');
+ dest--;
+ while ((dest != rpath) && (*--dest != '/'));
+ if ((dest == rpath) && (*dest != '/') {
+ /* Return EACCES to stay compliant to current documentation:
+ "Read or search permission was denied for a component of the
+ path prefix." Unreachable root directories should not be
+ accessed, see https://www.halfdog.net/Security/2017/LibcRealpathBufferUnderflow/ */
+ __set_errno (EACCES);
+ goto error;
+ }
+ dest++;
}
else
{
************************************************************
补丁对产生溢出的地方加了一个判断,一旦发现路径不是以’/’开头,便产生报错。
修复方案
相关受影响产品已经提供了安全更新,360CERT强烈建议所有受影响用户,及时进行安全更新。
时间线
2018-01-01至2018-01-01 OSS-SEC邮件组披露该漏洞
2018-01-24至2018-01-24 360CERT完成分析预警报告
发表评论
您还未登录,请先登录。
登录