Module: Msf::Handler::BindAwsSsm
- Defined in:
- lib/msf/core/handler/bind_aws_ssm.rb
Defined Under Namespace
Modules: AwsSsmSessionChannelExt Classes: AwsSsmSessionChannel
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_ssm’.
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.
-
#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
Methods included from Rex::Proto::Http::WebSocket::AmazonSsm
Instance Attribute Details
#conn_threads ⇒ Object (protected)
:nodoc:
377 378 379 |
# File 'lib/msf/core/handler/bind_aws_ssm.rb', line 377 def conn_threads @conn_threads end |
#listener_pairs ⇒ Object (protected)
:nodoc:
379 380 381 |
# File 'lib/msf/core/handler/bind_aws_ssm.rb', line 379 def listener_pairs @listener_pairs end |
#listener_threads ⇒ Object (protected)
:nodoc:
378 379 380 |
# File 'lib/msf/core/handler/bind_aws_ssm.rb', line 378 def listener_threads @listener_threads end |
Class Method Details
.general_handler_type ⇒ Object
Returns the connection oriented general handler type, in this case bind.
132 133 134 |
# File 'lib/msf/core/handler/bind_aws_ssm.rb', line 132 def self.general_handler_type 'bind' end |
.handler_type ⇒ Object
Returns the handler specific string representation, in this case ‘bind_aws_ssm’.
125 126 127 |
# File 'lib/msf/core/handler/bind_aws_ssm.rb', line 125 def self.handler_type return 'bind_aws_ssm' end |
Instance Method Details
#add_handler(opts = {}) ⇒ Object
Starts a new connecting thread
188 189 190 191 192 193 194 195 196 197 |
# File 'lib/msf/core/handler/bind_aws_ssm.rb', line 188 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.
175 176 177 178 179 180 181 182 183 |
# File 'lib/msf/core/handler/bind_aws_ssm.rb', line 175 def cleanup_handler # Kill any remaining handle_connection threads that might # be hanging around stop_handler conn_threads.each { |thr| thr.kill } end |
#human_name ⇒ String
A string suitable for displaying to the user
139 140 141 |
# File 'lib/msf/core/handler/bind_aws_ssm.rb', line 139 def human_name 'bind AWS SSM' end |
#initialize(info = {}) ⇒ Object
Initializes a bind handler and adds the options common to all bind payloads, such as local port.
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/msf/core/handler/bind_aws_ssm.rb', line 147 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('ROLE_ARN', [false, 'AWS assumed role ARN', nil]), OptString.new('ROLE_SID', [false, 'AWS assumed role session ID', nil]), ], Msf::Handler::BindAwsSsm) ( [ OptString.new('SSM_SESSION_DOC', [true, 'The SSM document to use for session requests', 'SSM-SessionManagerRunShell']), # AWS-RunShellScript, AWS-RunPowerShellScript, etc OptBool.new('SSM_KEEP_ALIVE', [false, 'Keep AWS SSM session alive with empty messages', true]) ], Msf::Handler::BindAwsSsm) 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
295 296 297 |
# File 'lib/msf/core/handler/bind_aws_ssm.rb', line 295 def payload_uri "ssm://#{datastore['EC2_ID']}:0" end |
#start_handler ⇒ Object
Starts monitoring for an outbound connection to become established.
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
# File 'lib/msf/core/handler/bind_aws_ssm.rb', line 202 def start_handler # 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 # Ignore this if one of the required options is missing return if datastore['EC2_ID'].blank? # Only try the same host/port combination once 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("BindAwsSsmHandler-#{datastore['EC2_ID']}", false) do ssm_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 ssm_client, peer_info = get_ssm_session rescue Rex::ConnectionError => e vprint_error(e.) rescue wlog("Exception caught in AWS SSM handler: #{$!.class} #{$!}") break end break if ssm_client # Wait a half-second before trying again Rex::ThreadSafe.sleep(0.5) end # Valid client connection? if ssm_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 } self.conn_threads << framework.threads.spawn('BindAwsSsmHandlerSession', false, ssm_client, peer_info) do |client_copy, info_copy| begin session_params = { target: datastore['EC2_ID'], document_name: datastore['SSM_SESSION_DOC'] } # Call API to start SSM session session_init = client_copy.start_session(session_params) # Create WebSocket from parameters ssm_sock = connect_ssm_ws(session_init) # Create Channel from WebSocket chan = ssm_sock.to_ssm_channel # Configure Channel chan._start_ssm_keepalive if datastore['SSM_KEEP_ALIVE'] chan.params.comm = Rex::Socket::Comm::Local unless chan.params.comm chan.params.peerhost = peer_info['IpAddress'] chan.params.peerport = 0 chan.params.peerhostname = peer_info['ComputerName'] chan.update_term_size rescue => e print_error("AWS SSM handler failed: #{e.}") elog('Exception raised from BindAwsSsm', error: e) return end self.listener_pairs[datastore['EC2_ID']] = chan handle_connection(chan.lsock, { datastore: datastore, aws_ssm_host_info: peer_info }) end else wlog('No connection received before the handler completed') end end end |
#stop_handler ⇒ Object
299 300 301 302 303 304 305 306 |
# File 'lib/msf/core/handler/bind_aws_ssm.rb', line 299 def stop_handler # Stop the listener threads self.listener_threads.each do |t| t.kill end self.listener_threads = [] self.listener_pairs = {} end |