In May 2018, a command injection flaw was found in the NetworkManager integration script included in the DHCP client packages in multiple versions of Red Hat Enterprise Linux (CVE-2018-1111), which has since been patched. An attacker could attack this vulnerability either through the use of a malicious DHCP server, or malicious, spoofed DHCP responses on the local network. A successful attack could execute arbitrary commands with root privileges on systems using NetworkManager with DHCP configured.
This vulnerability poses a serious threat to individuals or organizations running vulnerable instance of Red Hat Enterprise Linux versions 6 or 7 and patches should be applied immediately.
This blog post serves to help with your risk assessment and understanding of the vulnerability by providing an overview of this particular vulnerability and provides details on how readers may protect themselves.
NetworkManager is a Linux program that is used to manage system networking when DHCP networking mode is configured. In such an event, NetworkManager will launch dhclient to send DHCP requests as seen in Figure 1.
Figure 1. The dhclient process running via NetworkManager
In the above example, you might notice that an additional configuration file (/var/lib/NetworkManager/dhclient-eth0.conf) was passed to dhclient from NetworkManager. As we can see in the following example, by default dhclient is configured to request multiple DHCP packet options, including WPAD.
Figure 2. Configuration file passed to dhclient
When dhclient sends an initial request for a DHCP server, it is configured to include this WPAD (Code 252) option within the request, as we can see in the following example:
Figure 3. DHCP requesting WPAD option in initial packet
Due to the CVE-2018-1111 vulnerability, an attacker can craft a response to this DHCP request with a malformed response. For example, an attacker may respond with the following data, as seen in Figure 4:
xxx'&touch /tmp/test #
Figure 4. Attacker responding with a malformed WPAD option in the DHCP response
Upon receiving this response, the default 11-dhclient script will ultimately pass this data into an eval() statement, which will in turn result in the /tmp/test being created via the touch command.
There are a number of other things that happen after the victim system receives a malformed DHCP response and before /tmp/test is created. First, dhclient will call the client_option_envadd() function to save the value into a variable, which may be observed in the source code below. It is specifically performed on line 3154 via the client_envadd() function.
Figure 5. dhclient source code demonstrating how it handles DHCP packet options
In the above source code, the pretty_print_option() function is called prior to setting the variable, which will sanitize the value by adding a blackslash(‘\’) before the special characters. As an example:
- The ‘ character will be converted to \’
- The & character will converted to \&
In our example case, the initial data sent was as follows:
- xxx’&touch /tmp/test #
This will then be converted to the following:
- xxx\’\&touch /tmp/test #
This can be seen in the following figure where this function converts the data that was received:
Figure 6. Example WPAD option provided being modified by the pretty_print function
After this conversion is made, it proceeds to call the check_option_values() function before storing the value into a variable, where it will check to determine if it contains special characters in the event certain options were given. Example of such options include when a HOST_NAME or DOMAIN_NAME is provided, as seen in Figures 8 and 9.
Figure 8. Source code checking if specific options were provided
Figure 9. Code being executed in the event the NETBIOS_SCOPE option was provided
As you can see from the code, the WPAD option is not checked. As such, it undergoes no additional scrutiny, which enables us to provide any data via this option in the DHCP response.
Next, dhclient will launch /usr/libexec/nm-dhcp-helper process by setting a parameter passed via an argument. These variables are then saved to the dbus service.
Another sibling process named nm-dispatcher, which is launched by NetworkManager, will then read variables from the dbus service. It will save the value of the WPAD DHCP option to an environment variable name DHCP4_WPAD, and proceeds to launch the 11-dhclient script located in /etc/NetworkManager/dispatcher.d/.
Taking a look at this 11-dhclient script, we see it contains the following:
Figure 10. Contents of the 11-dhclient script
Let’s dive into what is exactly happening within this script.
Within the eval() statement, it begins with a “declare” command. This “declare” command will output all of the environment variables on the system. Readers may be familiar with the “env” command, which operates in a similar way. However, while the output is similar, there are some key differences, as shown inFigure 11, below.
Figure 11. Differences between the declare and env commands
As you can see above, the “declare” command will do 2 additional things:
- If the variables include special characters such as spaces or single quotes for example, it will add a ‘ on both sides.
- It will escape inner ‘ to ‘\” (converting one character to four characters).
Since the variable value is xxx\’\&touch /tmp/test #, the output from “declare” will become ‘xxx\’\”\&touch /tmp/test #’.
After the ”declare” command is run, the script will search for only environment variables that begin with “DHCP4_”. This is followed by the “read” command. With no arguments provided, this command will read escaped characters. In other words, \’ will become ‘.
Going back to the data we provided via the WPAD option in the DHCP response, ‘xxx\’\”\&touch /tmp/test #’ will become ‘xxx”’&touch /tmp/test #’. In other words, the previously escaped characters are unescaped as a result of using the “read” command without any arguments.
The remaining commands set the parsed environment variable data to a series of variables. The last command, however, contains code that may be exploited. The line in question is as follows:
echo "export $optname=$optvalue"
Using our example response, the following code will be executed on the system:
eval "$(echo "export new_wpad='xxx'''&touch /tmp/test #' ")"
This is demonstrated on the command-line in Figure 12:
Figure 12. Example execution of evaluating the code provided based on the WPAD DHCP option
Because the quotations are not escaped, and because it is followed by an ampersand, it allows us to append an additional command to this eval() statement. In our example, we supply a secondary command of ‘touch /tmp/test’, which results in us creating an empty file named ‘test’ in the /tmp/ directory.
In the event the quotation characters and the ampersand characters were escaped, our attack would be unsuccessful, as shown in the following example:
Figure 13. Attempt at executing the same code with escaped cahracters
It is important to note that other characters may be used to perform this attack, such as | or ;.
Understanding the Vulnerability Fix
In this particular instance, the fix is very simple. Simply adding the ‘-r’ option to the “read” command prevents the various characters from being unescaped, as shown in the fix pushed out to patch this vulnerability:
Figure 14. Patch for CVE-2018-1111
According to the documentation of the “read” command, the “-r” option prevents the command from reading backslashes as escape characters. In other words, it will keep all backslashes in the data provided to it. In doing so, it can defend against command injection attacks.
Status of this Vulnerability
Shortly after the vulnerability was discovered, proof-of-concept (POC) code was released into the wild on May 16, 2018 via Twitter:
Figure 15. Twitter announcement of CVE-2018-111 PoC
Additionally, in GitHub, there is code that may be configured to easily test for the presence of this vulnerability:
Considering that NetworkManager is so widely used and this vulnerability is so easy to be leveraged by attackers, it should be considered a critical vulnerability. The current threat environment around this is that there is increased risk that it will be used by malicious attackers.
Readers are encouraged to patch their systems if they have not already done so. In the event a patch has not yet been deployed, Palo Alto Networks customers are protected from this vulnerability via signature 40739.