prefer 'shell' channels over 'exec' channels for ssh

If a command is not specified to CommandStream, request a "shell"
session rather than running exec. This allows targets that do not have a
true "shell" which supports exec to instead return a raw shell session.
This commit is contained in:
Brent Cook 2018-02-08 02:21:16 -06:00
parent d5ae2bb55b
commit b1d0529161
15 changed files with 48 additions and 43 deletions

View File

@ -15,7 +15,34 @@ class CommandStream
attr_accessor :localinfo
end
def initialize(ssh, cmd, cleanup = false)
def shell_requested(channel, success)
raise "could not request ssh shell" unless success
channel[:data] = ''
channel.on_eof do
self.rsock.close rescue nil
self.ssh.close rescue nil
self.thread.kill
end
channel.on_close do
self.rsock.close rescue nil
self.ssh.close rescue nil
self.thread.kill
end
channel.on_data do |ch,data|
self.rsock.write(data)
end
channel.on_extended_data do |ch, ctype, data|
self.rsock.write(data)
end
self.channel = channel
end
def initialize(ssh, cmd = nil, cleanup = true)
self.lsock, self.rsock = Rex::Socket.tcp_socket_pair()
self.lsock.extend(Rex::IO::Stream)
@ -23,7 +50,7 @@ class CommandStream
self.rsock.extend(Rex::IO::Stream)
self.ssh = ssh
self.thread = Thread.new(ssh,cmd,cleanup) do |rssh,rcmd,rcleanup|
self.thread = Thread.new(ssh,cmd,cleanup) do |rssh, rcmd, rcleanup|
begin
info = rssh.transport.socket.getpeername_as_array
@ -33,32 +60,10 @@ class CommandStream
self.lsock.localinfo = "#{info[1]}:#{info[2]}"
rssh.open_channel do |rch|
rch.exec(rcmd) do |c, success|
raise "could not execute command: #{rcmd.inspect}" unless success
c[:data] = ''
c.on_eof do
self.rsock.close rescue nil
self.ssh.close rescue nil
self.thread.kill
end
c.on_close do
self.rsock.close rescue nil
self.ssh.close rescue nil
self.thread.kill
end
c.on_data do |ch,data|
self.rsock.write(data)
end
c.on_extended_data do |ch, ctype, data|
self.rsock.write(data)
end
self.channel = c
if cmd.nil?
rch.send_channel_request("shell", &method(:shell_requested))
else
rch.exec(rsh, &method(:shell_requested))
end
end
@ -85,7 +90,7 @@ class CommandStream
end
# Shut down the SSH session if requested
if(rcleanup)
if rcleanup
rssh.close
end
end

View File

@ -57,7 +57,7 @@ class MetasploitModule < Msf::Auxiliary
return unless ssh_socket
# Create a new session
conn = Net::SSH::CommandStream.new(ssh_socket, '/bin/sh', true)
conn = Net::SSH::CommandStream.new(ssh_socket)
merge_me = {
'USERPASS_FILE' => nil,

View File

@ -72,7 +72,7 @@ class MetasploitModule < Msf::Auxiliary
return unless ssh_socket
# Create a new session from the socket
conn = Net::SSH::CommandStream.new(ssh_socket, '/bin/sh', true)
conn = Net::SSH::CommandStream.new(ssh_socket)
# Clean up the stored data - need to stash the keyfile into
# a datastore for later reuse.

View File

@ -110,7 +110,7 @@ class MetasploitModule < Msf::Exploit::Remote
end
if ssh
conn = Net::SSH::CommandStream.new(ssh, '/bin/sh', true)
conn = Net::SSH::CommandStream.new(ssh)
ssh = nil
return conn
end

View File

@ -106,7 +106,7 @@ class MetasploitModule < Msf::Exploit::Remote
if ssh_socket
# Create a new session from the socket, then dump it.
conn = Net::SSH::CommandStream.new(ssh_socket, '/bin/sh', true)
conn = Net::SSH::CommandStream.new(ssh_socket)
ssh_socket = nil
return conn

View File

@ -94,7 +94,7 @@ class MetasploitModule < Msf::Exploit::Remote
if ssh_socket
# Create a new session from the socket, then dump it.
conn = Net::SSH::CommandStream.new(ssh_socket, '/bin/bash -i', true)
conn = Net::SSH::CommandStream.new(ssh_socket)
ssh_socket = nil
return conn

View File

@ -109,7 +109,7 @@ class MetasploitModule < Msf::Exploit::Remote
return false unless ssh_socket
# Create a new session from the socket, then dump it.
conn = Net::SSH::CommandStream.new(ssh_socket, '/bin/sh', true)
conn = Net::SSH::CommandStream.new(ssh_socket)
ssh_socket = nil
conn
end

View File

@ -103,7 +103,7 @@ class MetasploitModule < Msf::Exploit::Remote
if ssh_socket
# Create a new session from the socket, then dump it.
conn = Net::SSH::CommandStream.new(ssh_socket, '/bin/bash', true)
conn = Net::SSH::CommandStream.new(ssh_socket)
ssh_socket = nil
return conn

View File

@ -102,7 +102,7 @@ class MetasploitModule < Msf::Exploit::Remote
if ssh_socket
# Create a new session from the socket, then dump it.
conn = Net::SSH::CommandStream.new(ssh_socket, '/bin/bash', true)
conn = Net::SSH::CommandStream.new(ssh_socket)
ssh_socket = nil
return conn

View File

@ -114,7 +114,7 @@ class MetasploitModule < Msf::Exploit::Remote
end
if ssh
conn = Net::SSH::CommandStream.new(ssh, 'shell-escape', true)
conn = Net::SSH::CommandStream.new(ssh, 'shell-escape')
return conn
end

View File

@ -117,7 +117,7 @@ class MetasploitModule < Msf::Exploit::Remote
end
if ssh
conn = Net::SSH::CommandStream.new(ssh, '/bin/sh', true)
conn = Net::SSH::CommandStream.new(ssh)
ssh = nil
return conn
end

View File

@ -153,7 +153,7 @@ class MetasploitModule < Msf::Exploit::Remote
private: private_key,
private_type: :ssh_key
)
return Net::SSH::CommandStream.new(ssh, '/bin/sh', true)
return Net::SSH::CommandStream.new(ssh)
end
nil

View File

@ -102,7 +102,7 @@ class MetasploitModule < Msf::Exploit::Remote
if ssh_socket
# Create a new session from the socket, then dump it.
conn = Net::SSH::CommandStream.new(ssh_socket, '/bin/sh', true)
conn = Net::SSH::CommandStream.new(ssh_socket)
self.sockets.delete(ssh_socket.transport.socket)
return conn

View File

@ -186,6 +186,6 @@ class MetasploitModule < Msf::Exploit::Remote
# 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)
Net::SSH::CommandStream.new(ssh, build_command)
end
end

View File

@ -177,7 +177,7 @@ class MetasploitModule < Msf::Exploit::Remote
message = transport.next_message.type
if message.to_i == 6 #SSH2_MSG_SERVICE_ACCEPT
shell = Net::SSH::CommandStream.new(connection, '/bin/sh', true)
shell = Net::SSH::CommandStream.new(connection)
connection = nil
return shell
end