Land #10888, Fix Net::SSH::CommandStream session open failure
parent
20f6226e1f
commit
c2405c2750
|
@ -122,7 +122,14 @@ msf5 auxiliary(scanner/ssh/libssh_auth_bypass) > run
|
||||||
|
|
||||||
[*] 172.28.128.3:2222 - Attempting authentication bypass
|
[*] 172.28.128.3:2222 - Attempting authentication bypass
|
||||||
[+] 172.28.128.3:2222 - SSH-2.0-libssh_0.8.3 appears to be unpatched
|
[+] 172.28.128.3:2222 - SSH-2.0-libssh_0.8.3 appears to be unpatched
|
||||||
[-] 172.28.128.3:2222 - shell/exec channel request failed
|
[-] 172.28.128.3:2222 - Net::SSH::ChannelOpenFailed: Session channel open failed (1)
|
||||||
|
[*] Scanned 1 of 1 hosts (100% complete)
|
||||||
|
[*] Auxiliary module execution completed
|
||||||
|
msf5 auxiliary(scanner/ssh/libssh_auth_bypass) > run
|
||||||
|
|
||||||
|
[*] 172.28.128.3:2222 - Attempting authentication bypass
|
||||||
|
[+] 172.28.128.3:2222 - SSH-2.0-libssh_0.8.3 appears to be unpatched
|
||||||
|
[-] 172.28.128.3:2222 - Net::SSH::ChannelRequestFailed: Shell/exec channel request failed
|
||||||
[*] Scanned 1 of 1 hosts (100% complete)
|
[*] Scanned 1 of 1 hosts (100% complete)
|
||||||
[*] Auxiliary module execution completed
|
[*] Auxiliary module execution completed
|
||||||
msf5 auxiliary(scanner/ssh/libssh_auth_bypass) >
|
msf5 auxiliary(scanner/ssh/libssh_auth_bypass) >
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
# -*- coding: binary -*-
|
# -*- coding: binary -*-
|
||||||
require 'rex'
|
|
||||||
|
|
||||||
module Net
|
class Net::SSH::CommandStream
|
||||||
module SSH
|
|
||||||
|
|
||||||
class CommandStream
|
|
||||||
|
|
||||||
attr_accessor :channel, :thread, :error, :ssh
|
attr_accessor :channel, :thread, :error, :ssh
|
||||||
attr_accessor :lsock, :rsock, :monitor
|
attr_accessor :lsock, :rsock, :monitor
|
||||||
|
@ -17,9 +13,11 @@ class CommandStream
|
||||||
|
|
||||||
def shell_requested(channel, success)
|
def shell_requested(channel, success)
|
||||||
unless success
|
unless success
|
||||||
raise Net::SSH::ChannelRequestFailed, 'shell/exec channel request failed'
|
raise Net::SSH::ChannelRequestFailed, 'Shell/exec channel request failed'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self.channel = channel
|
||||||
|
|
||||||
channel[:data] = ''
|
channel[:data] = ''
|
||||||
channel[:extended_data] = ''
|
channel[:extended_data] = ''
|
||||||
|
|
||||||
|
@ -40,8 +38,6 @@ class CommandStream
|
||||||
self.rsock.write(data)
|
self.rsock.write(data)
|
||||||
channel[:extended_data] << data
|
channel[:extended_data] << data
|
||||||
end
|
end
|
||||||
|
|
||||||
self.channel = channel
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(ssh, cmd = nil, pty: false, cleanup: false)
|
def initialize(ssh, cmd = nil, pty: false, cleanup: false)
|
||||||
|
@ -52,44 +48,39 @@ class CommandStream
|
||||||
|
|
||||||
self.ssh = ssh
|
self.ssh = ssh
|
||||||
self.thread = Thread.new(ssh, cmd, pty, cleanup) do |rssh, rcmd, rpty, rcleanup|
|
self.thread = Thread.new(ssh, cmd, pty, cleanup) do |rssh, rcmd, rpty, rcleanup|
|
||||||
begin
|
info = rssh.transport.socket.getpeername_as_array
|
||||||
info = rssh.transport.socket.getpeername_as_array
|
self.lsock.peerinfo = "#{info[1]}:#{info[2]}"
|
||||||
self.lsock.peerinfo = "#{info[1]}:#{info[2]}"
|
|
||||||
|
|
||||||
info = rssh.transport.socket.getsockname
|
info = rssh.transport.socket.getsockname
|
||||||
self.lsock.localinfo = "#{info[1]}:#{info[2]}"
|
self.lsock.localinfo = "#{info[1]}:#{info[2]}"
|
||||||
|
|
||||||
rssh.open_channel do |rch|
|
channel = rssh.open_channel do |rch|
|
||||||
# A PTY will write us to {u,w}tmp and lastlog
|
# A PTY will write us to {u,w}tmp and lastlog
|
||||||
rch.request_pty if rpty
|
rch.request_pty if rpty
|
||||||
if rcmd.nil?
|
|
||||||
rch.send_channel_request('shell', &method(:shell_requested))
|
if rcmd.nil?
|
||||||
else
|
rch.send_channel_request('shell', &method(:shell_requested))
|
||||||
rch.exec(rcmd, &method(:shell_requested))
|
else
|
||||||
end
|
rch.exec(rcmd, &method(:shell_requested))
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
self.monitor = Thread.new do
|
channel.on_open_failed do |ch, code, desc|
|
||||||
while(true)
|
raise Net::SSH::ChannelOpenFailed.new(code, 'Session channel open failed')
|
||||||
next if not self.rsock.has_read_data?(1.0)
|
end
|
||||||
buff = self.rsock.read(16384)
|
|
||||||
break if not buff
|
self.monitor = Thread.new do
|
||||||
verify_channel
|
while(true)
|
||||||
self.channel.send_data(buff) if buff
|
next if not self.rsock.has_read_data?(1.0)
|
||||||
end
|
buff = self.rsock.read(16384)
|
||||||
|
break if not buff
|
||||||
|
verify_channel
|
||||||
|
self.channel.send_data(buff) if buff
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
while true
|
while true
|
||||||
rssh.process(0.5) { true }
|
rssh.process(0.5) { true }
|
||||||
end
|
|
||||||
|
|
||||||
rescue ::Exception => e
|
|
||||||
# XXX: This won't be set UNTIL there's a failure from a thread
|
|
||||||
self.error = e
|
|
||||||
#::Kernel.warn "BOO: #{e.inspect}"
|
|
||||||
#::Kernel.warn e.backtrace.join("\n")
|
|
||||||
ensure
|
|
||||||
self.monitor.kill if self.monitor
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Shut down the SSH session if requested
|
# Shut down the SSH session if requested
|
||||||
|
@ -97,6 +88,11 @@ class CommandStream
|
||||||
rssh.close
|
rssh.close
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
rescue ::Exception => e
|
||||||
|
# XXX: This won't be set UNTIL there's a failure from a thread
|
||||||
|
self.error = e
|
||||||
|
ensure
|
||||||
|
self.monitor.kill if self.monitor
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -118,6 +114,3 @@ class CommandStream
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
|
@ -130,8 +130,8 @@ class MetasploitModule < Msf::Auxiliary
|
||||||
# XXX: Wait for CommandStream to log a channel request failure
|
# XXX: Wait for CommandStream to log a channel request failure
|
||||||
sleep 0.1
|
sleep 0.1
|
||||||
|
|
||||||
if shell.error
|
if (e = shell.error)
|
||||||
print_error("#{ip}:#{rport} - #{shell.error}")
|
print_error("#{ip}:#{rport} - #{e.class}: #{e.message}")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -139,10 +139,10 @@ class MetasploitModule < Msf::Auxiliary
|
||||||
when 'Shell'
|
when 'Shell'
|
||||||
start_session(self, "#{self.name} (#{version})", {}, false, shell.lsock)
|
start_session(self, "#{self.name} (#{version})", {}, false, shell.lsock)
|
||||||
when 'Execute'
|
when 'Execute'
|
||||||
output = shell.channel[:data].chomp
|
output = shell.channel && (shell.channel[:data] || '').chomp
|
||||||
|
|
||||||
if output.blank?
|
if output.blank?
|
||||||
print_error("Empty or blank output: #{datastore['CMD']}")
|
print_error("#{ip}:#{rport} - Empty or blank command output")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue