导语:2015年5月,安全研究人员在Red Hat Enterprise Linux多个版本DHCP客户端软件包的NetworkManager集成脚本中发现了命令注入漏洞(CVE-2018-1111)。攻击者借助该漏洞,可以通过恶意DHCP服务器或本地网络上的恶意构造DHCP响应来实现攻击。

概述

2015年5月,安全研究人员在Red
Hat Enterprise
Linux多个版本DHCP客户端软件包的NetworkManager集成脚本中发现了命令注入漏洞(CVE-2018-1111)。攻击者借助该漏洞,可以通过恶意DHCP服务器或本地网络上的恶意构造DHCP响应来实现攻击。该攻击成功后,攻击者就可以在使用NetworkManager且已经配置DHCP的系统上以root权限执行任意命令。目前,该漏洞已经在新版本中修复。

这一漏洞针对使用Red Hat Enterprise Linux 6或7版本的用户造成严重威胁,相关用户应该及时打上补丁。

本文主要对这一漏洞展开详细分析,帮助用户进一步了解该漏洞的潜在风险,并提供针对此漏洞的安全防护建议。

漏洞详情

NetworkManager是一个Linux程序,用于在DHCP网络模式情况下管理系统网络。具体而言,NetworkManager会启动dhclient以发送DHCP请求,如下图所示。

1.png

在上述示例中,大家可能会注意到另一个配置文件(/var/lib/NetworkManager/dhclient-eth0.conf)从NetworkManager传递给了dhclient。正如我们在下面示例所看到的,默认情况下,dhclient会被配置成请求多个DHCP数据包选项,其中也包括WPAD。

2.png

当dhclient发送DHCP服务器的原始请求时,请求中就会包含这一WPAD(代码252)选项,如下所示:

3.png

由于CVE-2018-1111漏洞,攻击者可以构造一个格式错误的响应,并将其作为对这一DHCP请求的响应。举例来说,攻击者可能会使用以下数据进行响应,如下图所示:

xxx'&touch /tmp/test #

4.png

收到此响应后,默认的11-dhclient脚本最终会将这一数据传递给eval()语句,这将导致主机会通过touch命令创建/tmp/test。

技术分析

从被攻击系统收到特殊构造的DHCP响应后到创建/tmp/test之前的这段时间里,还会发生许多其他事情。首先,dhclient调用client_option_envadd()函数,将值保存到变量中,这一过程我们通过阅读源代码可以发现。在第3154行,client_envadd()函数负责执行这一过程。

5.png

在上面的源代码中,我们还可以看到,在设置变量之前会调用pretty_print_option()函数,这一函数通过在特殊符号之前添加“\”来实现过滤。举例来说:

‘字符将变为\‘

&字符将变为\&

在我们的示例中,原本要发送的数据如下:

xxx’&touch /tmp/test #

但经过转义后,就变成了:

xxx\’\&touch /tmp/test #

如下图所示,该函数会对接收到的数据进行转义:

6.png

在完成转义后,它会继续调用check_option_values()函数,然后再将值存储到变量中。该函数的作用是检查某些特定的选项中是否包含特殊字符。目前我们已经发现,会对HOST_NAME或DOMAIN_NAME进行检查,如下图所示。

检查源代码中,是否包含特定选项:

7.png

当提供NETBIOS_SCOPE选项时,下述代码将被执行:

8.png

从代码中可以看出,WPAD选项并不会被检查。至此我们知道,由于该选项没有经过严格的检查,我们有可能借助修改DHCP响应中这一选项的数据来实现攻击。

接下来,dhclient通过设置参数的方式来启动/usr/libexec/nm-dhcp-helper进程,然后将这些变量保存到dbus服务中。

另一个名为nm-dispatcher的进程会由NetworkManager启动,然后从dbus服务中读取变量。它会将WPAD

DHCP选项的值保存到环境变量DHCP4_WPAD中,然后继续启动位于/etc/NetworkManager/dispatcher.d/的11-dhclient脚本。

下面,让我们来关注一下11-dhclient脚本,其中包含如下内容:

9.png

我们来深入分析一下这个脚本。

在eval()语句中,它以“declare”命令开始。这个“declare”命令会输出系统上所有环境变量。大家可能更熟悉“env”这个变量,其实它与“declare”的运行方式类似。尽管二者在输出上比较相似,但还是存在着一些关键差异,如下图所示。

10.png

如上所见,“declare”命令将会执行另外两项操作:

1、如果变量中包含特殊字符(例如空格或单引号),会在变量的两侧添加’符号;

2、将变量中的’字符转换为’\’’(由原来的1个字符变成4个字符)。

由于变量值为xxx\’\&touch /tmp/test #,因此“declare”的输出将会变为‘xxx\’\”\&touch /tmp/test #’。

运行“declare”命令后,脚本将只会搜索以“DHCP4_”开头的环境变量。接下来就会执行“read”命令。如果未提供此参数,这一命令将会读取转义字符。具体而言,\’就将变为’。

回到我们在DHCP响应的WPAD选项中提供的数据,‘xxx\’\”\&touch /tmp/test #’将会变为‘xxx”’&touch /tmp/test #’。由于使用了不含任何参数的“read”命令,原本应该转义的字符现在未被转义。

其它的命令会将解析的环境变量数据设置为一系列变量,但最后一个命令中包含可能被利用的代码。存在问题的代码如下:

echo "export $optname=$optvalue"

假如使用我们示例中的字符串,将会在系统上执行以下代码:

eval "$(echo "export new_wpad='xxx'''&touch /tmp/test #' ")"

如下图,我们在命令行中进行演示:

11.png

由于引用没有被转义,并且其后面跟着一个&符号,所以我们就可以向这个eval()语句附加一个额外的命令。在我们的示例中,我们添加了一个touch /tmp/test的命令,这样一来就可以使其在/tmp/目录下创建一个名为test的空文件。

如果引号和&符号被转义,那么我们的尝试就会失败,如下所示:

12.png

请注意,其他字符也可能用于执行此类攻击,例如|和;。

漏洞修复方式

针对这一漏洞,修复方式非常简单,只需要在“read”命令中添加“-r”选项就可以保证各类字符都被转义。我们看到,补丁中的修复方式如下:

13.png

根据官方文档中“read”命令的说明,“-r”选项可以防止命令将反斜杠作为转义字符读取。换而言之,使用“-r”后将会保留数据中的所有反斜杠。这样一来,也就能有效的抵御命令注入攻击。

漏洞披露状态

在漏洞被发现后不久,2018年5月16日,PoC已经通过Twitter被公开:

14.png

此外,在GitHub也发布了一个能够轻松测试该漏洞是否存在的工具:

https://github.com/knqyf263/CVE-2018-1111

总结

考虑到NetworkManager已经被广泛使用,并且这一漏洞非常容易被攻击者利用,因此我们应该将其视为一个严重漏洞。目前,恶意攻击者仍然在利用这一漏洞实现攻击。因此,建议广大用户及时通过补丁的方式实现修复。

源链接

Hacking more

...