308 lines
6.2 KiB
Ruby
308 lines
6.2 KiB
Ruby
# -*- coding: binary -*-
|
|
require 'msf/core/exploit/tcp_server'
|
|
|
|
module Msf
|
|
|
|
module EvasiveTCP
|
|
attr_accessor :_send_size, :_send_delay, :evasive
|
|
|
|
def denagle
|
|
begin
|
|
setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
|
rescue ::Exception
|
|
end
|
|
end
|
|
|
|
def write(buf, opts={})
|
|
|
|
return super(buf, opts) if not @evasive
|
|
|
|
ret = 0
|
|
idx = 0
|
|
len = @_send_size || buf.length
|
|
|
|
while(idx < buf.length)
|
|
|
|
if(@_send_delay and idx > 0)
|
|
::IO.select(nil, nil, nil, @_send_delay)
|
|
end
|
|
|
|
pkt = buf[idx, len]
|
|
|
|
res = super(pkt, opts)
|
|
flush()
|
|
|
|
idx += len
|
|
ret += res if res
|
|
end
|
|
ret
|
|
end
|
|
end
|
|
|
|
###
|
|
#
|
|
# This module provides methods for establish a connection to a remote host and
|
|
# communicating with it.
|
|
#
|
|
###
|
|
module Exploit::Remote::Tcp
|
|
|
|
#
|
|
# Initializes an instance of an exploit module that exploits a
|
|
# vulnerability in a TCP server.
|
|
#
|
|
def initialize(info = {})
|
|
super
|
|
|
|
register_options(
|
|
[
|
|
Opt::RHOST,
|
|
Opt::RPORT
|
|
], Msf::Exploit::Remote::Tcp
|
|
)
|
|
|
|
register_advanced_options(
|
|
[
|
|
OptBool.new('SSL', [ false, 'Negotiate SSL/TLS for outgoing connections', false]),
|
|
OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL/TLS to be used (TLS and SSL23 are auto-negotiate)', 'TLS1', ['SSL2', 'SSL3', 'SSL23', 'TLS', 'TLS1', 'TLS1.1', 'TLS1.2']]),
|
|
OptEnum.new('SSLVerifyMode', [ false, 'SSL verification method', 'PEER', %W{CLIENT_ONCE FAIL_IF_NO_PEER_CERT NONE PEER}]),
|
|
OptString.new('SSLCipher', [ false, 'String for SSL cipher - "DHE-RSA-AES256-SHA" or "ADH"']),
|
|
Opt::Proxies,
|
|
Opt::CPORT,
|
|
Opt::CHOST,
|
|
OptInt.new('ConnectTimeout', [ true, 'Maximum number of seconds to establish a TCP connection', 10])
|
|
], Msf::Exploit::Remote::Tcp
|
|
)
|
|
|
|
register_evasion_options(
|
|
[
|
|
OptInt.new('TCP::max_send_size', [false, 'Maxiumum tcp segment size. (0 = disable)', 0]),
|
|
OptInt.new('TCP::send_delay', [false, 'Delays inserted before every send. (0 = disable)', 0])
|
|
], Msf::Exploit::Remote::Tcp
|
|
)
|
|
end
|
|
|
|
#
|
|
# Establishes a TCP connection to the specified RHOST/RPORT
|
|
#
|
|
# @see Rex::Socket::Tcp
|
|
# @see Rex::Socket::Tcp.create
|
|
def connect(global = true, opts={})
|
|
|
|
dossl = false
|
|
if(opts.has_key?('SSL'))
|
|
dossl = opts['SSL']
|
|
else
|
|
dossl = ssl
|
|
if (datastore.default?('SSL') and rport.to_i == 443)
|
|
dossl = true
|
|
end
|
|
end
|
|
|
|
nsock = Rex::Socket::Tcp.create(
|
|
'PeerHost' => opts['RHOST'] || rhost,
|
|
'PeerPort' => (opts['RPORT'] || rport).to_i,
|
|
'LocalHost' => opts['CHOST'] || chost || "0.0.0.0",
|
|
'LocalPort' => (opts['CPORT'] || cport || 0).to_i,
|
|
'SSL' => dossl,
|
|
'SSLVersion' => opts['SSLVersion'] || ssl_version,
|
|
'SSLVerifyMode' => opts['SSLVerifyMode'] || ssl_verify_mode,
|
|
'SSLCipher' => opts['SSLCipher'] || ssl_cipher,
|
|
'Proxies' => proxies,
|
|
'Timeout' => (opts['ConnectTimeout'] || connect_timeout || 10).to_i,
|
|
'Context' =>
|
|
{
|
|
'Msf' => framework,
|
|
'MsfExploit' => self,
|
|
})
|
|
|
|
# enable evasions on this socket
|
|
set_tcp_evasions(nsock)
|
|
|
|
# Set this socket to the global socket as necessary
|
|
self.sock = nsock if (global)
|
|
|
|
# Add this socket to the list of sockets created by this exploit
|
|
add_socket(nsock)
|
|
|
|
return nsock
|
|
end
|
|
|
|
# Enable evasions on a given client
|
|
def set_tcp_evasions(socket)
|
|
|
|
if( datastore['TCP::max_send_size'].to_i == 0 and datastore['TCP::send_delay'].to_i == 0)
|
|
return
|
|
end
|
|
|
|
return if socket.respond_to?('evasive')
|
|
|
|
socket.extend(EvasiveTCP)
|
|
|
|
if ( datastore['TCP::max_send_size'].to_i > 0)
|
|
socket._send_size = datastore['TCP::max_send_size']
|
|
socket.denagle
|
|
socket.evasive = true
|
|
end
|
|
|
|
if ( datastore['TCP::send_delay'].to_i > 0)
|
|
socket._send_delay = datastore['TCP::send_delay']
|
|
socket.evasive = true
|
|
end
|
|
end
|
|
|
|
def handler(nsock = self.sock)
|
|
# If the handler claims the socket, then we don't want it to get closed
|
|
# during cleanup
|
|
if ((rv = super) == Handler::Claimed)
|
|
if (nsock == self.sock)
|
|
self.sock = nil
|
|
end
|
|
|
|
# Remove this socket from the list of sockets so that it will not be
|
|
# aborted.
|
|
remove_socket(nsock)
|
|
end
|
|
|
|
return rv
|
|
end
|
|
|
|
#
|
|
# Closes the TCP connection
|
|
#
|
|
def disconnect(nsock = self.sock)
|
|
begin
|
|
if (nsock)
|
|
nsock.shutdown
|
|
nsock.close
|
|
end
|
|
rescue IOError
|
|
end
|
|
|
|
if (nsock == sock)
|
|
self.sock = nil
|
|
end
|
|
|
|
# Remove this socket from the list of sockets created by this exploit
|
|
remove_socket(nsock)
|
|
end
|
|
|
|
#
|
|
# Performs cleanup, disconnects the socket if necessary
|
|
#
|
|
def cleanup
|
|
super
|
|
disconnect
|
|
end
|
|
|
|
def print_prefix
|
|
if rhost
|
|
super + peer + " - "
|
|
else
|
|
super
|
|
end
|
|
end
|
|
|
|
##
|
|
#
|
|
# Wrappers for getters
|
|
#
|
|
##
|
|
|
|
#
|
|
# Returns the local host for outgoing connections
|
|
#
|
|
def chost
|
|
datastore['CHOST']
|
|
end
|
|
|
|
#
|
|
# Returns the TCP connection timeout
|
|
#
|
|
def connect_timeout
|
|
datastore['ConnectTimeout']
|
|
end
|
|
|
|
#
|
|
# Returns the local port for outgoing connections
|
|
#
|
|
def cport
|
|
datastore['CPORT']
|
|
end
|
|
|
|
#
|
|
# Returns the local host
|
|
#
|
|
def lhost
|
|
datastore['LHOST']
|
|
end
|
|
|
|
#
|
|
# Returns the local port
|
|
#
|
|
def lport
|
|
datastore['LPORT']
|
|
end
|
|
|
|
# Returns the rhost:rport
|
|
def peer
|
|
"#{rhost}:#{rport}"
|
|
end
|
|
|
|
#
|
|
# Returns the proxy configuration
|
|
#
|
|
def proxies
|
|
datastore['Proxies']
|
|
end
|
|
|
|
#
|
|
# Returns the target host
|
|
#
|
|
def rhost
|
|
datastore['RHOST']
|
|
end
|
|
|
|
#
|
|
# Returns the remote port
|
|
#
|
|
def rport
|
|
datastore['RPORT']
|
|
end
|
|
|
|
#
|
|
# Returns the boolean indicating SSL
|
|
#
|
|
def ssl
|
|
datastore['SSL']
|
|
end
|
|
|
|
#
|
|
# Returns the string indicating SSLVersion
|
|
#
|
|
def ssl_version
|
|
datastore['SSLVersion']
|
|
end
|
|
|
|
#
|
|
# Returns the SSL certification verification mechanism
|
|
#
|
|
def ssl_verify_mode
|
|
datastore['SSLVerifyMode']
|
|
end
|
|
|
|
#
|
|
# Returns the SSL cipher to use for the context
|
|
#
|
|
def ssl_cipher
|
|
datastore['SSLCipher']
|
|
end
|
|
|
|
protected
|
|
|
|
attr_accessor :sock
|
|
|
|
end
|
|
|
|
end
|