A new post to the Full Disclosure mailing list today detailed a remote code exploit vulnerability within all available versions of the Nagios Remote Plugin Executor (NRPE), and provided a PoC that included gaining a reverse shell on the target server. Note that this reported exploit relies on a separate (but similar) vulnerability report in CVE-2013-1362. In today’s post, Dawid Golunski properly identifies a weakness within the NRPE argument sanitation that could allow a client to execute arbitrary commands on the remote host within the context of the NRPE user. At first this seems like a pretty serious vulnerability, but further analysis shows that successful exploitation hinges on a series of bad practices not related to NRPE code itself.
A further look at Golunski’s research shows that the following criteria must be met in order to successfully exploit this vulnerability:
- The attacking server must be previously defined within the allowed_hosts directive, which specifies hosts that are allowed to execute NRPE commands on the remote machine. If a disallowed host initiates a NRPE command, the host will immediately shutdown the connection without further parsing the command arguments (note this ‘immediate’ shutdown is down at the application layer, as opposed to ending the TCP session via RST). By default, only 127.0.0.1 is specified in allowed_hosts, so Nagios machines must be manually defined. Thus, successful exploitation of this vulnerability implies exploitation of the Nagios server itself, which adds an added layer of complexity to this attack.
- Remote arguments must be enabled within the NRPE daemon configuration, in the form of setting dont_blame_nrpe to 1. By default, this is disabled- for security reasons. The default nrpe.conf file even specifies this:
12345678910111213# COMMAND ARGUMENT PROCESSING# This option determines whether or not the NRPE daemon will allow clients# to specify arguments to commands that are executed. This option only works# if the daemon was configured with the --enable-command-args configure script# option.## *** ENABLING THIS OPTION IS A SECURITY RISK! ***# Read the SECURITY file for information on some of the security implications# of enabling this variable.## Values: 0=do not allow arguments, 1=allow command argumentsdont_blame_nrpe=0
- NRPE command definitions must be specifically defined to process arbitrary command arguments. This is a relatively common use case, but again, the default NRPE configuration file cautions against this:
123456789101112131415161718192021222324252627282930313233343536373839# COMMAND ARGUMENT PROCESSING# COMMAND DEFINITIONS# Command definitions that this daemon will run. Definitions# are in the following format:## command[<command_name>]=<command_line>## When the daemon receives a request to return the results of <command_name># it will execute the command specified by the <command_line> argument.## Unlike Nagios, the command line cannot contain macros - it must be# typed exactly as it should be executed.## Note: Any plugins that are used in the command lines must reside# on the machine that this daemon is running on! The examples below# assume that you have plugins installed in a /usr/local/nagios/libexec# directory. Also note that you will have to modify the definitions below# to match the argument format the plugins expect. Remember, these are# examples only!# The following examples use hardcoded command arguments...#command[check_users]=/usr/lib/nagios/plugins/check_users -w 5 -c 10#command[check_load]=/usr/lib/nagios/plugins/check_load -w 15,10,5 -c 30,25,20#command[check_hda1]=/usr/lib/nagios/plugins/check_disk -w 20% -c 10% -p /dev/hda1#command[check_zombie_procs]=/usr/lib/nagios/plugins/check_procs -w 5 -c 10 -s Z#command[check_total_procs]=/usr/lib/nagios/plugins/check_procs -w 150 -c 200# The following examples allow user-supplied arguments and can# only be used if the NRPE daemon was compiled with support for# command arguments *AND* the dont_blame_nrpe directive in this# config file is set to '1'. This poses a potential security risk, so# make sure you read the SECURITY file before doing this.command[check_users]=/usr/lib/nagios/plugins/check_users -w $ARG1$ -c $ARG2$command[check_load]=/usr/lib/nagios/plugins/check_load -w $ARG1$ -c $ARG2$command[check_disk]=/usr/lib/nagios/plugins/check_disk -w $ARG1$ -c $ARG2$ -p $ARG3$command[check_procs]=/usr/lib/nagios/plugins/check_procs -w $ARG1$ -c $ARG2$ -s $ARG3$
Once these conditions are met, we were indeed able to successfully bypass the meta character sanitation. Meeting each of these conditions required us to make a deliberate change to our NRPE configuration and reload the daemon.
The combination of requiring dont_blame_nrpe=1 and specifying commands that use arbitrary parameter definitions places the onus of responsibility on the administrator, not the software architecture or implementation. Does a vulnerability exist within the NRPE package? Yes. Golunski’s research does indeed show this, but a rush to judgement over the security of NRPE is unwarranted. The architecture of the software clearly shows forethought and defense-in-depth as a key design feature. However, any vulnerability within a given software package is no excuse for a lack of planning and poor implementation. Additionally, the discovery of this vulnerability reinforces the necessity for observing and implementing key security principles as part of an organization’s monitoring architecture:
- Always limit access to ports serving sensitive information. There is no reason to have a service like NRPE publicly available to the Internet, and the presence of the allowed_hosts directive is not a replacement for limiting access to the NRPE daemon via an ACL. Additionally, even though NRPE traffic is SSL-encrypted, transmitting sensitive data like NRPE (or SNMP, etc) over the public Internet should be done using an encrypted tunnel.
- Review your execution context. Best practice here would be to create a separate user with extremely limited access under which to run the NRPE daemon. RPM and Deb packages automatically do this (creating a new nagios or nrpe user in no additional groups, and setting the shell to /sbin/nologin); manual builds should be implemented with this in mind. NEVER run daemons such as this as root.
- Check third party libraries. NRPE links against openssl libraries to perform in-app encryption. Just gonna leave that there.
Today’s post a good reminder for us to keep track of what we’re running, how we’re running it, who we’re running it as- and always maintain a critical attitude toward any public announcement.
Update – More than 6 weeks after this vulnerability was announced, it still has yet to be patched. Also props to CG for the pingback at Carnal0nage.