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使用十分廣泛,并且這個漏洞很容易被攻擊者利用,它應該被視為一個高危的漏洞。目前此漏洞威脅的風險情況會更具利用此漏洞的攻擊數量增加而提升。
如果還沒有被攻擊,讀者應該盡快修補他們的系統。