Files
metasploit-gs/lib/msf/core/handler/reverse_ssh.rb
T
RageLtMan f0b24339fe Implement Rex::Proto::Ssh::Server scaffold
Create the Rex::Proto::Ssh namespace and implement hrr_rb_ssh
objects in the Rex namespace with Rex' sockets stack, permissive
default connection options to accept any authentication, ACLs for
port forwarding, and a modified Connection #initialize method for
simplified instantiation.

The actual Rex::Proto::Ssh::Server object follow standard Rex
semantics for services to permit use in handlers, exploits, and
auxiliary modules in the same manner as the Http::Server is used
today.

This work is far from complete - the HrrRbSsh low-level objects
should be decomposed into Rex' pattern as they currently depend
heavily on their own Procs and Threads internally which use the
parent Connection object's attributes to look up which Proc should
be called in response to a Channel or Authentication request. This
is a bit difficult to do piecemeal given the intertwined data and
execution dependency inside of HrrRbSsh.

Next steps:
1. Create handler and reverse_ssh command session payloads
1a. POSIX systems generally have SSH already
1b. Windows Powershell is likely able to hotload SSH libs as a
pre-stager.
1c. Other interpreted runtimes usually have client-ssh libraries
2. Implement options parsing, handling, etc for user-customizable
functionality from the Msf namespace.
3. Use libssh2 to permit mettle use of the SSH transport.
3a. Bother @OJ about doing the same for Windows Meterpreter.
3b. Bother @zeroSteiner to implement SSH transport for PyMeterp.
3c. Ask @timwr and @mihi how viable this is for Android/Java.
3d. See if @OJ will do this for CLR-meterp on a livestream.
4. Write a post module which runs this SSH server from a mettle
session using the compromised hosts's own host keys and passwd
file for "valid" authentication while logging and MITMing the
entire command stream remotely - help folks shake off some of the
complacency around "secure shells."
5. Write a plugin which will permit sharing of the entire console
context, specific acquired sessions, or TCP forwards with the
pugin's SSH clients based on the credentials used to connect.
6. Further decompose the server code into Rex to permit writing
client fuzzers, loggers, and other tooling to test the posture of
SSH client implementations.
7. Work to implement SSH client functionality in HrrRbSsh and
convert the rest of Rex/Msf to use this library instead only.
8. Rewrite and import MetaSsh into Metasploit proper using the
new Rex::Proto::Ssh code.

-----

Huge thanks to @hirura for writing HrrRbSsh. I've spent countless
hours on and off working to implement server-side semantics in
net/ssh years ago and it was becoming a pretty full rewrite due
to the ordering of server/client req/resp messages and who sent
what to whom. This library is a much much cleaner implementation
and provides full, modern SSH servers in pure Ruby.
2019-06-22 20:06:15 -04:00

121 lines
2.6 KiB
Ruby

# -*- coding: binary -*-
require 'rex/socket'
require 'thread'
require 'msf/core/handler/reverse_tcp'
module Msf
module Handler
###
#
# This handler implements the SSH tunneling interface.
#
###
module ReverseSsh
include Msf::Handler::ReverseTcp
#
# Returns the string representation of the handler type
#
def self.handler_type
return 'reverse_ssh'
end
#
# Returns the connection-described general handler type, in this case
# 'tunnel'.
#
def self.general_handler_type
"tunnel"
end
# Initializes the reverse SSH handler and ads the options that are required
# for all reverse SSH payloads, like version string and auth params.
#
def initialize(info = {})
super
register_advanced_options(
[
OptString.new('Ssh::Version', [
true,
'The SSH version string to provide',
Rex::Proto::Ssh::Connection.default_options['local_version']
])
], Msf::Handler::ReverseSsh
)
end
# A URI describing where we are listening
#
# @param addr [String] the address that
# @return [String] A URI of the form +ssh://host:port/+
def listener_uri(addr=datastore['ReverseListenerBindAddress'])
addr = datastore['LHOST'] if addr.nil? || addr.empty?
uri_host = Rex::Socket.is_ipv6?(addr) ? "[#{addr}]" : addr
"ssh://#{uri_host}:#{bind_port}"
end
# Create an Ssh listener
#
# @return [void]
def setup_handler
local_addr = nil
local_port = bind_port
ex = false
ssh_opts = Rex::Proto::Ssh::Connection.default_options
ssh_opts['local_version'] = datastore['Ssh::Version']
# Start the SSH server service on this host/port
bind_addresses.each do |ip|
begin
self.service = Rex::ServiceManager.start(Rex::Proto::Ssh::Server,
local_port, ip,
{
'Msf' => framework,
'MsfExploit' => self,
},
comm,
ssh_opts
)
local_addr = ip
rescue
ex = $!
print_error("Handler failed to bind to #{ip}:#{local_port}")
else
ex = false
break
end
end
raise ex if (ex)
print_status("Started SSH reverse handler on #{listener_uri(local_addr)}")
if datastore['IgnoreUnknownPayloads']
print_status("Handler is ignoring unknown payloads")
end
end
# Stops the handler & service
#
# @return [void]
def stop_handler
if self.service
if self.sessions == 0
Rex::ServiceManager.stop_service(self.service)
end
end
end
attr_accessor :service # :nodoc:
protected
end
end
end