Module: Msf::Handler::BindAwsInstanceConnect
- Includes:
- Msf::Handler
- Defined in:
- lib/msf/core/handler/bind_aws_instance_connect.rb
Overview
This module implements the AWS InstanceConnect handler. This means that it will attempt to connect to a remote host through the AWS InstanceConnect pipe for a period of time (typically the duration of an exploit) to see if the agent has started listening.
Defined Under Namespace
Modules: AwsInstanceConnectSessionChannelExt
Constant Summary
Constants included from Msf::Handler
Instance Attribute Summary collapse
-
#conn_threads ⇒ Object
protected
:nodoc:.
-
#listener_pairs ⇒ Object
protected
:nodoc:.
-
#listener_threads ⇒ Object
protected
:nodoc:.
Attributes included from Msf::Handler
#exploit_config, #parent_payload, #pending_connections, #session_waiter_event, #sessions
Class Method Summary collapse
-
.general_handler_type ⇒ Object
Returns the connection oriented general handler type, in this case bind.
-
.handler_type ⇒ Object
Returns the handler specific string representation, in this case ‘bind_aws_instance_connect’.
Instance Method Summary collapse
-
#add_handler(opts = {}) ⇒ Object
Starts a new connecting thread.
-
#cleanup_handler ⇒ Object
Kills off the connection threads if there are any hanging around.
- #comm_string ⇒ Object
-
#human_name ⇒ String
A string suitable for displaying to the user.
-
#initialize(info = {}) ⇒ Object
Initializes a bind handler and adds the options common to all bind payloads, such as local port.
-
#payload_uri ⇒ Object
A URI describing what the payload is configured to use for transport.
-
#start_handler ⇒ Object
Starts monitoring for an outbound connection to become established.
- #stop_handler ⇒ Object
Methods included from Msf::Handler
#handle_connection, #handler, #handler_name, #interrupt_wait_for_session, #register_session, #setup_handler, #wait_for_session, #wfs_delay
Instance Attribute Details
#conn_threads ⇒ Object (protected)
:nodoc:
350 351 352 |
# File 'lib/msf/core/handler/bind_aws_instance_connect.rb', line 350 def conn_threads @conn_threads end |
#listener_pairs ⇒ Object (protected)
:nodoc:
352 353 354 |
# File 'lib/msf/core/handler/bind_aws_instance_connect.rb', line 352 def listener_pairs @listener_pairs end |
#listener_threads ⇒ Object (protected)
:nodoc:
351 352 353 |
# File 'lib/msf/core/handler/bind_aws_instance_connect.rb', line 351 def listener_threads @listener_threads end |
Class Method Details
.general_handler_type ⇒ Object
Returns the connection oriented general handler type, in this case bind.
31 32 33 |
# File 'lib/msf/core/handler/bind_aws_instance_connect.rb', line 31 def self.general_handler_type 'bind' end |
.handler_type ⇒ Object
Returns the handler specific string representation, in this case ‘bind_aws_instance_connect’.
24 25 26 |
# File 'lib/msf/core/handler/bind_aws_instance_connect.rb', line 24 def self.handler_type 'bind_aws_instance_connect' end |
Instance Method Details
#add_handler(opts = {}) ⇒ Object
Starts a new connecting thread
97 98 99 100 101 102 103 104 105 106 |
# File 'lib/msf/core/handler/bind_aws_instance_connect.rb', line 97 def add_handler(opts={}) # Merge the updated datastore values opts.each_pair do |k,v| datastore[k] = v end # Start a new handler start_handler end |
#cleanup_handler ⇒ Object
Kills off the connection threads if there are any hanging around.
81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/msf/core/handler/bind_aws_instance_connect.rb', line 81 def cleanup_handler # Kill any remaining handle_connection threads that might # be hanging around stop_handler conn_threads.each { |thr| begin thr.kill rescue => e elog(e) end } end |
#comm_string ⇒ Object
196 197 198 199 200 201 202 |
# File 'lib/msf/core/handler/bind_aws_instance_connect.rb', line 196 def comm_string if self.listener_pairs[datastore['EC2_ID']].nil? "(setting up)" else "(via #{ssh_url})" end end |
#human_name ⇒ String
A string suitable for displaying to the user
38 39 40 |
# File 'lib/msf/core/handler/bind_aws_instance_connect.rb', line 38 def human_name 'bind AWS InstanceConnect' end |
#initialize(info = {}) ⇒ Object
Initializes a bind handler and adds the options common to all bind payloads, such as local port.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/msf/core/handler/bind_aws_instance_connect.rb', line 46 def initialize(info = {}) super ( [ OptString.new('EC2_ID', [true, 'The EC2 ID of the instance ', '']), OptString.new('REGION', [true, 'AWS region containing the instance', 'us-east-1']), OptString.new('ACCESS_KEY_ID', [false, 'AWS access key', nil]), OptString.new('SECRET_ACCESS_KEY', [false, 'AWS secret key', nil]), OptString.new('INSTANCE_USER', [false, 'Username on the EC2 instance with which to log-in']), OptString.new('ROLE_ARN', [false, 'AWS assumed role ARN', nil]), OptString.new('ROLE_SID', [false, 'AWS assumed role session ID', nil]), OptString.new('USERNAME', [false, 'EC2 instance local username to authenticate with']), OptString.new('PASSWORD', [false, 'EC2 instance local password to authenticate with']) ], Msf::Handler::BindAwsInstanceConnect) ( [ OptString.new('PRIVATE_KEY', [ false, 'The string value of the private key that will be used. If you are using MSFConsole, this value should be set as file:PRIVATE_KEY_PATH. OpenSSH, RSA, DSA, and ECDSA private keys are supported.' ]), OptString.new('KEY_PASS', [false, 'Passphrase for SSH private key(s)']), OptBool.new('SSH_DEBUG', [ false, 'Enable SSH debugging output (Extreme verbosity!)', false]) ], Msf::Handler::BindAwsInstanceConnect) self.listener_threads = [] self.conn_threads = [] self.listener_pairs = {} end |
#payload_uri ⇒ Object
A URI describing what the payload is configured to use for transport
192 193 194 |
# File 'lib/msf/core/handler/bind_aws_instance_connect.rb', line 192 def payload_uri "serial+ssh://#{datastore['EC2_ID']}:#{INSTANCE_PORT}" end |
#start_handler ⇒ Object
Starts monitoring for an outbound connection to become established.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/msf/core/handler/bind_aws_instance_connect.rb', line 111 def start_handler if datastore['EC2_ID'].blank? raise Msf::OptionValidateError.new({ 'EC2_ID' => "EC2_ID cannot be blank" }) end # Maximum number of seconds to run the handler ctimeout = 150 # Maximum number of seconds to await initial API response rtimeout = 5 if (exploit_config and exploit_config['active_timeout']) ctimeout = exploit_config['active_timeout'].to_i end return if self.listener_pairs[datastore['EC2_ID']] self.listener_pairs[datastore['EC2_ID']] = true # Start a new handling thread self.listener_threads << framework.threads.spawn("BindAwsInstanceConnectHandler-#{datastore['EC2_ID']}", false) { instance_connect_client = nil print_status("Started #{human_name} handler against #{datastore['EC2_ID']}:#{datastore['REGION']}") stime = Time.now.to_i while (stime + ctimeout > Time.now.to_i) begin # Call API to start InstanceConnect session if start_instance_connect_session instance_connect_client = connect_ssh else raise Rex::ConnectionError.new('Cannot establish serial connection to ' + datastore['EC2_ID']) end rescue Aws::EC2InstanceConnect::Errors::SerialConsoleSessionLimitExceededException => e vprint_error("Too many active serial console sessions. It takes 30 seconds to tear down a session after you've disconnected from the serial console in order to allow a new session.") rescue Aws::Errors::ServiceError => e vprint_error(e.) rescue Rex::ConnectionError => e vprint_error(e.) rescue StandardError => e vprint_error(e.) elog("Exception caught in InstanceConnect handler: #{$!.class} #{$!}", error: e) break end break if instance_connect_client # Wait a second before trying again Rex::ThreadSafe.sleep(0.5) end # Valid client connection? if (instance_connect_client) # Increment the has connection counter self.pending_connections += 1 # Timeout and datastore options need to be passed through to the client opts = { :datastore => datastore, :expiration => datastore['SessionExpirationTimeout'].to_i, :comm_timeout => datastore['SessionCommunicationTimeout'].to_i, :retry_total => datastore['SessionRetryTotal'].to_i, :retry_wait => datastore['SessionRetryWait'].to_i, :serial_username => datastore['USERNAME'], :serial_password => datastore['PASSWORD'] } self.conn_threads << framework.threads.spawn("BindAwsInstanceConnectHandlerSession", false, instance_connect_client, opts) { |ssh, opts_copy| begin self.listener_pairs[datastore['EC2_ID']] = ssh handle_connection(ssh, opts_copy) rescue => e elog('Exception raised from BindAwsInstanceConnect.handle_connection', error: e) end } else wlog("No connection received before the handler completed") end } end |
#stop_handler ⇒ Object
204 205 206 207 208 209 210 211 |
# File 'lib/msf/core/handler/bind_aws_instance_connect.rb', line 204 def stop_handler # Stop the listener threads self.listener_threads.each do |t| t.kill end self.listener_threads = [] self.listener_pairs = {} end |