Module: Msf::Exploit::Remote::HttpServer::Relay

Includes:
Auxiliary::MultipleTargetHosts, Msf::Exploit::Remote::HttpServer, Relay::NTLM::HashCapture
Defined in:
lib/msf/core/exploit/remote/http_server/relay.rb

Defined Under Namespace

Modules: NTLM

Instance Attribute Summary collapse

Attributes included from SocketServer

#service

Instance Method Summary collapse

Methods included from Msf::Exploit::Remote::HttpServer

#add_resource, #add_robots_resource, #autofilter, #check_dependencies, #cli, #cli=, #close_client, #create_response, #fingerprint_user_agent, #get_resource, #get_uri, #hardcoded_uripath, #on_request_uri, #print_prefix, #random_uri, #regenerate_payload, #remove_resource, #report_user_agent, #resource_uri, #send_local_redirect, #send_not_found, #send_redirect, #send_response, #send_robots, #srvhost_addr, #srvport, #use_zlib

Methods included from Auxiliary::Report

#active_db?, #create_cracked_credential, #create_credential, #create_credential_and_login, #create_credential_login, #db, #db_warning_given?, #get_client, #get_host, #inside_workspace_boundary?, #invalidate_login, #mytask, #myworkspace, #myworkspace_id, #report_auth_info, #report_client, #report_exploit, #report_host, #report_loot, #report_note, #report_service, #report_vuln, #report_web_form, #report_web_page, #report_web_site, #report_web_vuln, #store_cred, #store_local, #store_loot

Methods included from Metasploit::Framework::Require

optionally, optionally_active_record_railtie, optionally_include_metasploit_credential_creation, #optionally_include_metasploit_credential_creation, optionally_require_metasploit_db_gem_engines

Methods included from TcpServer

#on_client_close, #on_client_connect, #ssl, #ssl_cert, #ssl_cipher, #ssl_compression, #ssl_version

Methods included from SocketServer

#_determine_server_comm, #bindhost, #bindport, #cleanup_service, #exploit, #on_client_data, #primer, #regenerate_payload, #srvhost, #srvhost_addr, #srvport, #via_string

Methods included from Auxiliary::MultipleTargetHosts

#check, #has_check?

Instance Attribute Details

#loggerObject (readonly)

Returns the value of attribute logger.



12
13
14
# File 'lib/msf/core/exploit/remote/http_server/relay.rb', line 12

def logger
  @logger
end

Instance Method Details

#cleanupObject



100
101
102
103
104
105
106
# File 'lib/msf/core/exploit/remote/http_server/relay.rb', line 100

def cleanup
  if @http_relay_service
    @http_relay_service.remove_resource('/')
    Rex::ServiceManager.stop_service(@http_relay_service)
  end
  super
end

#initialize(info = {}) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/msf/core/exploit/remote/http_server/relay.rb', line 14

def initialize(info = {})
  super
  register_options(
    [
      OptPort.new('SRVPORT', [true, 'The local port to listen on.', 80]),
      OptAddress.new('SRVHOST', [ true, 'The local host to listen on.', '0.0.0.0' ]),
      OptAddressRange.new('RHOSTS', [true, 'Target address range or CIDR identifier to relay to'], aliases: ['LDAPHOST', 'RELAY_TARGETS']),
      OptInt.new('RELAY_TIMEOUT', [true, 'Seconds that the relay socket will wait for a response after the client has initiated communication.', 25])
    ], self.class
  )
  @relay_clients = {}
  @relay_clients_mutex = Mutex.new
end

#on_relay_request(cli, req) ⇒ Object



42
43
44
45
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
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/msf/core/exploit/remote/http_server/relay.rb', line 42

def on_relay_request(cli, req)
  client_id = Rex::Socket.to_authority(cli.peerhost, cli.peerport)
  cli.keepalive = true
  relay_client = nil
  print_status("Received #{req.method} request for #{req.uri} from #{client_id}")

  # When the 307 redirect is sent to the client, it reconnects on a different port. So the relay server has to keep
  # track of the redirect URIs and associate them with the same client session. This allows the state machine to
  # continue seamlessly even if the client is bouncing between ports. Tracking the client ports but not redirect
  # URI's ends up in an infinite loop of 307 redirects because the client appears to be a new session on each
  # request. Tracking the redirect URI's allows us to correlate the new connection with the existing session
  # and avoid the redirect loop.

  @relay_clients_mutex.synchronize do
    #  Try to find the client by their exact TCP connection
    if @relay_clients.key?(client_id)
      relay_client = @relay_clients[client_id]
      relay_client.cli = cli
    else
      previous_client_id = @relay_clients.keys.find { |k| @relay_clients[k].redirect_uri == req.uri && req.uri != '/' }

      if previous_client_id
        # Seamlessly transfer the state machine from the old port to the new port
        relay_client = @relay_clients.delete(previous_client_id)
        relay_client.cli = cli
        @relay_clients[client_id] = relay_client
      else
        # This is a truly new client session
        relay_client = Msf::Exploit::Remote::HttpServer::Relay::NTLM::ServerClient.new(
          cli,
          relay_targets,
          logger,
          datastore['RELAY_TIMEOUT']
        )
        relay_client.redirect_uri = req.uri # Track their starting path
        @relay_clients[client_id] = relay_client
      end
    end
  end

  relay_client.process_request(req)

  @relay_clients_mutex.synchronize do
    if relay_client.finished? && @relay_clients[client_id].equal?(relay_client)
      @relay_clients.delete(client_id)
    end
  end
end

#send_auth_challenge(cli) ⇒ Object



91
92
93
94
95
96
97
98
# File 'lib/msf/core/exploit/remote/http_server/relay.rb', line 91

def send_auth_challenge(cli)
  res = Rex::Proto::Http::Response.new
  res.code = 401
  res.message = "Unauthorized"
  res.headers['WWW-Authenticate'] = "NTLM"

  cli.put(res.to_s)
end

#start_service(opts = {}) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/msf/core/exploit/remote/http_server/relay.rb', line 28

def start_service(opts = {})
  @logger = opts['Logger'] || self

  super

  @http_relay_service = self.service

  relay_path = '/'
  add_resource(
    'Proc' => Proc.new { |cli, req| on_relay_request(cli, req) },
    'Path' => relay_path
  )
end