2015年5月,在Red Hat Enterprise Linux多个版本的DHCP客户端软件包所包含的NetworkManager集成脚本中发现了命令注入漏洞(CVE-2018-1111),该漏洞目前已经进行了修补。攻击者可以通过本地网络上的恶意DHCP服务器或使用恶意的虚假DHCP响应来利用此漏洞进行攻击,一旦攻击成功,则可以在配置了DHCP的NetworkManager的系统上以root权限执行任意命令。
此漏洞可对运行了带有它的Red Hat Enterprise Linux6、7版本的个人或组织构成严重威胁,受到威胁着应立即使用补丁。
本文通过提供此漏洞的概述来帮助您进行风险评估和了解漏洞,并提供读者如何进行防护等详细信息。
NetworkManager是一个Linux程序,用于在配置DHCP网络模式时管理系统网络,在这种情况下,NetworkManager将启动dhclient来发送DHCP请求,如图1所示。
图1.通过NetworkManager运行的dhclient进程
在上面的示例中,你可能会注意到另一个配置文件(/var/lib/NetworkManager/dhclient-eth0.conf)被从NetworkManager传递给了dhclient。正如下图,dhclient默认配置为请求多个DHCP数据包,其中包括了WPAD。
图2.传递给dhclient的配置文件
当dhclient发送DHCP服务器的初始化请求时,它被配置为在请求中包含此WPAD(代码252)选项,如下图中所示:
图3.初始数据包中的DHCP请求WPAD选项
有了CVE-2018-1111漏洞,攻击者可以通过错误格式的响应对此DHCP请求进行响应。例如,攻击者可能会使用以下数据进行响应,如图4所示:
xxx '&touch /tmp/test #
图4.攻击者在DHCP响应中使用恶意格式的WPAD选项进行响应
收到此响应后,默认的11-dhclient脚本最终会将此数据传递给eval()语句,这就会导致通过touch命令来创建/tmp/test。
在受害者的系统收到恶意格式的DHCP响应再创建/tmp/test之前,还会发生许多其他的事情。首先,dhclient调用client_option_envadd()函数将值保存到变量中,这可以在下图的源代码中看到,它通过client_envadd()函数在3154行特意执行。
图5.证明如何处理DHCP数据包选项的dhclient源码
在上面的源码中,在设置变量之前调用了pretty_print_option()函数,通过在特殊字符之前添加反斜杠(’‘)来清理值。举个例子:
'
字符将转换为了'
&
字符将转换为了&
在我们的示例中,发送的初始数据如下:
然后将转换为以下内容:
下图中显示了此函数转换了收到的数据:
图6.由pretty_print函数修改的WPAD选项的示例
进行转换后,它会继续调用check_option_values()函数,然后将值存储到变量中,并检查以确认在给定某些选项的情况下它是否包含特殊字符。此类选项的示例包括提供HOST_NAME或DOMAIN_NAME时,如图8和图9所示。
图8.检查是否提供了特定选项的源码
图9.在提供NETBIOS_SCOPE选项的情况下执行的代码
从代码中可以看出,未选中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脚本:
图10. 11-dhclient脚本的内容
让我们深入了解这个脚本中发生了什么。
在eval()语句中,以“declare”命令开头,这个“declare”命令将输出系统上的所有环境变量,读者可能更熟悉“env”命令,它的方式运行类似,但虽然输出相似,结果仍存在一些关键差异,如下图11所示。
图11. declare和env命令之间的差异
正如您在上面所看到的,“declare”命令会执行另外两项操作:
'
。'
转换为'''
**(将一个字符转换为四个字符)。由于变量的值为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 #' ")"
图12中进行了演示:
图12.示例基于WPAD DHCP选项提供的代码执行的结果
因为引用没有被转义,并且因为它后跟了一个&
符号,所以它允许我们向这个eval()语句附加一个额外的命令,在我们的示例中,我们输入了touch /tmp/test
的辅助命令,这导致我们在/tmp/
目录中创建一个名为test
的空文件。
如果引号字符和&符号被转义,我们的攻击就将失败,如下所示:
图13.尝试使用转义的cahracters执行相同的命令
重要的是要注意其他字符也可能被用于执行此攻击,例如|
或;
。
在这个特定情况下,修复非常简单,只需在“read”命令中添加“-r”选项即可防止各种字符不被转义,就像下图的修复补丁里所示的一样:
图14. CVE-2018-1111的补丁
根据“read”命令的文档描述,“-r”选项可防止命令将反斜杠作为转义字符读取。换句话说,它将保留提供给它的数据中的所有反斜杠,这样就可以防御命令注入攻击。
在漏洞被发现后不久,POC代码就于2018年5月16日通过Twitter被发布到网络中:
图15.推特CVE-2018-111 PoC演示
此外,也可以在GitHub中配置代码以测试是否存在此漏洞:
https://github.com/knqyf263/CVE-2018-1111
考虑到NetworkManager使用十分广泛,并且这个漏洞很容易被攻击者利用,它应该被视为一个高危的漏洞。目前此漏洞威胁的风险情况会更具利用此漏洞的攻击数量增加而提升。
如果还没有被攻击,读者应该尽快修补他们的系统。