eea8fa86dc
Also actually handle the 'Auto' option that we had in the crawler and remove hardcoded defaults in modules that do not need them.
245 lines
5.8 KiB
Ruby
245 lines
5.8 KiB
Ruby
# -*- coding: binary -*-
|
|
|
|
module Msf
|
|
|
|
###
|
|
#
|
|
# This mixin provides a generic interface for running a TCP server of some
|
|
# sort that is designed to exploit clients. Exploits that include this mixin
|
|
# automatically take a passive stance.
|
|
#
|
|
###
|
|
module Exploit::Remote::TcpServer
|
|
|
|
def initialize(info = {})
|
|
super(update_info(info,
|
|
'Stance' => Msf::Exploit::Stance::Passive))
|
|
|
|
register_options(
|
|
[
|
|
OptBool.new('SSL', [ false, 'Negotiate SSL for incoming connections', false]),
|
|
# SSLVersion is currently unsupported for TCP servers (only supported by clients at the moment)
|
|
OptPath.new('SSLCert', [ false, 'Path to a custom SSL certificate (default is randomly generated)']),
|
|
OptAddress.new('SRVHOST', [ true, "The local host to listen on. This must be an address on the local machine or 0.0.0.0", '0.0.0.0' ]),
|
|
OptPort.new('SRVPORT', [ true, "The local port to listen on.", 8080 ]),
|
|
|
|
], Msf::Exploit::Remote::TcpServer)
|
|
|
|
register_advanced_options(
|
|
[
|
|
OptString.new('ListenerComm', [ false, 'The specific communication channel to use for this service']),
|
|
OptBool.new('SSLCompression', [ false, 'Enable SSL/TLS-level compression', false ])
|
|
], Msf::Exploit::Remote::TcpServer)
|
|
|
|
register_evasion_options(
|
|
[
|
|
OptInt.new('TCP::max_send_size', [false, 'Maximum 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
|
|
|
|
#
|
|
# This mixin overrides the exploit method so that it can initiate the
|
|
# service that corresponds with what the client has requested.
|
|
#
|
|
def exploit
|
|
|
|
start_service()
|
|
print_status("Server started.")
|
|
|
|
# Call the exploit primer
|
|
primer
|
|
|
|
# Wait on the service to stop
|
|
self.service.wait
|
|
end
|
|
|
|
#
|
|
# Primer method to call after starting service but before handling connections
|
|
#
|
|
def primer
|
|
end
|
|
|
|
#
|
|
# Stops the service, if one was created.
|
|
#
|
|
def cleanup
|
|
super
|
|
if(service)
|
|
stop_service()
|
|
print_status("Server stopped.")
|
|
end
|
|
end
|
|
|
|
#
|
|
# Called when a client connects.
|
|
#
|
|
def on_client_connect(client)
|
|
end
|
|
|
|
#
|
|
# Called when a client has data available for reading.
|
|
#
|
|
def on_client_data(client)
|
|
end
|
|
|
|
#
|
|
# Called when a client has disconnected.
|
|
#
|
|
def on_client_close(client)
|
|
end
|
|
|
|
#
|
|
# Starts the service.
|
|
#
|
|
def start_service(*args)
|
|
begin
|
|
|
|
comm = datastore['ListenerComm']
|
|
if comm == "local"
|
|
comm = ::Rex::Socket::Comm::Local
|
|
else
|
|
comm = nil
|
|
end
|
|
|
|
self.service = Rex::Socket::TcpServer.create(
|
|
'LocalHost' => srvhost,
|
|
'LocalPort' => srvport,
|
|
'SSL' => ssl,
|
|
'SSLCert' => ssl_cert,
|
|
'SSLCompression' => ssl_compression,
|
|
'Comm' => comm,
|
|
'Context' =>
|
|
{
|
|
'Msf' => framework,
|
|
'MsfExploit' => self,
|
|
})
|
|
|
|
self.service.on_client_connect_proc = Proc.new { |client|
|
|
on_client_connect(client)
|
|
}
|
|
self.service.on_client_data_proc = Proc.new { |client|
|
|
on_client_data(client)
|
|
}
|
|
self.service.on_client_close_proc = Proc.new { |client|
|
|
on_client_close(client)
|
|
}
|
|
|
|
# Start the listening service
|
|
self.service.start
|
|
|
|
rescue ::Errno::EACCES => e
|
|
if (srvport.to_i < 1024)
|
|
print_line(" ")
|
|
print_error("Could not start the TCP server: #{e}.")
|
|
print_error(
|
|
"This module is configured to use a privileged TCP port (#{srvport}). " +
|
|
"On Unix systems, only the root user account is allowed to bind to privileged ports." +
|
|
"Please run the framework as root to use this module."
|
|
)
|
|
print_error(
|
|
"On Microsoft Windows systems, this error is returned when a process attempts to "+
|
|
"listen on a host/port combination that is already in use. For example, Windows XP "+
|
|
"will return this error if a process attempts to bind() over the system SMB/NetBIOS services."
|
|
)
|
|
print_line(" ")
|
|
end
|
|
raise e
|
|
end
|
|
end
|
|
|
|
#
|
|
# Stops the service.
|
|
#
|
|
def stop_service
|
|
if (service)
|
|
begin
|
|
self.service.deref if self.service.kind_of?(Rex::Service)
|
|
if self.service.kind_of?(Rex::Socket)
|
|
self.service.close
|
|
self.service.stop
|
|
end
|
|
|
|
self.service = nil
|
|
rescue ::Exception
|
|
end
|
|
end
|
|
end
|
|
|
|
#
|
|
# Returns the local host that is being listened on.
|
|
#
|
|
def srvhost
|
|
datastore['SRVHOST']
|
|
end
|
|
|
|
#
|
|
# Returns the local port that is being listened on.
|
|
#
|
|
def srvport
|
|
datastore['SRVPORT']
|
|
end
|
|
|
|
#
|
|
# Returns the SSL option
|
|
#
|
|
def ssl
|
|
datastore['SSL']
|
|
end
|
|
|
|
#
|
|
# Returns the SSLCert option
|
|
#
|
|
def ssl_cert
|
|
datastore['SSLCert']
|
|
end
|
|
|
|
# @return [Bool] enable SSL/TLS-level compression
|
|
def ssl_compression
|
|
datastore['SSLCompression']
|
|
end
|
|
|
|
#
|
|
# Re-generates the payload, substituting the current RHOST and RPORT with
|
|
# the supplied client host and port from the socket.
|
|
#
|
|
def regenerate_payload(cli, arch = nil, platform = nil, target = nil)
|
|
|
|
ohost = datastore['RHOST']
|
|
oport = datastore['RPORT']
|
|
p = nil
|
|
|
|
begin
|
|
# Update the datastore with the supplied client peerhost/peerport
|
|
datastore['RHOST'] = cli.peerhost
|
|
datastore['RPORT'] = cli.peerport
|
|
|
|
if ((p = super(arch, platform, target)) == nil)
|
|
print_error("Failed to generate payload")
|
|
return nil
|
|
end
|
|
|
|
# Allow the payload to start a new handler
|
|
add_handler({
|
|
'RHOST' => datastore['RHOST'],
|
|
'RPORT' => datastore['RPORT']
|
|
})
|
|
|
|
ensure
|
|
datastore['RHOST'] = ohost
|
|
datastore['RPORT'] = oport
|
|
end
|
|
|
|
p
|
|
end
|
|
|
|
protected
|
|
|
|
attr_accessor :service # :nodoc:
|
|
|
|
end
|
|
|
|
end
|
|
|