Class: Metasploit::Aggregator::ConnectionManager

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/metasploit/aggregator/connection_manager.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeConnectionManager

Returns a new instance of ConnectionManager.



16
17
18
19
20
21
# File 'lib/metasploit/aggregator/connection_manager.rb', line 16

def initialize
  @cables = []
  @manager_mutex = Mutex.new
  @router = Router.instance
  @details_cache = SessionDetailService.instance
end

Class Method Details

.ssl_generate_certificateObject



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/metasploit/aggregator/connection_manager.rb', line 23

def self.ssl_generate_certificate
  yr   = 24*3600*365
  vf   = Time.at(Time.now.to_i - rand(yr * 3) - yr)
  vt   = Time.at(vf.to_i + (10 * yr))
  cn   = 'localhost'
  key  = OpenSSL::PKey::RSA.new(2048){ }
  cert = OpenSSL::X509::Certificate.new
  cert.version    = 2
  cert.serial     = (rand(0xFFFFFFFF) << 32) + rand(0xFFFFFFFF)
  cert.subject    = OpenSSL::X509::Name.new([["CN", cn]])
  cert.issuer     = OpenSSL::X509::Name.new([["CN", cn]])
  cert.not_before = vf
  cert.not_after  = vt
  cert.public_key = key.public_key

  ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
  cert.extensions = [
      ef.create_extension("basicConstraints","CA:FALSE")
  ]
  ef.issuer_certificate = cert

  cert.sign(key, OpenSSL::Digest::SHA256.new)

  [key, cert, nil]
end

Instance Method Details

#add_cable_http(host, port) ⇒ Object



83
84
85
86
87
88
89
90
91
92
# File 'lib/metasploit/aggregator/connection_manager.rb', line 83

def add_cable_http(host, port)
  @manager_mutex.synchronize do
    forwarder = Metasploit::Aggregator::HttpForwarder.new
    forwarder.log_messages = true
    server = TCPServer.new(host, port)

    handler = connect_cable(server, host, port, forwarder)
    @cables << Cable.new(handler, server, forwarder)
  end
end

#add_cable_https(host, port, certificate) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/metasploit/aggregator/connection_manager.rb', line 64

def add_cable_https(host, port, certificate)
  @manager_mutex.synchronize do
    forwarder = Metasploit::Aggregator::HttpsForwarder.new
    forwarder.log_messages = true
    server = TCPServer.new(host, port)
    ssl_context = OpenSSL::SSL::SSLContext.new
    unless certificate.nil?
      ssl_context.key, ssl_context.cert = ssl_parse_certificate(certificate)
    else
      ssl_context.key, ssl_context.cert = Metasploit::Aggregator::ConnectionManager.ssl_generate_certificate
    end
    ssl_server = OpenSSL::SSL::SSLServer.new(server, ssl_context)

    handler = connect_cable(ssl_server, host, port, forwarder)
    @cables << Cable.new(handler, server, forwarder)
    handler
  end
end

#cablesObject



129
130
131
132
133
134
135
136
# File 'lib/metasploit/aggregator/connection_manager.rb', line 129

def cables
  local_cables = []
  @cables.each do |cable|
    addr = cable.server.local_address
    local_cables << addr.ip_address + ':' + addr.ip_port.to_s
  end
  local_cables
end

#connect_cable(server, host, port, forwarder) ⇒ Object



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/metasploit/aggregator/connection_manager.rb', line 138

def connect_cable(server, host, port, forwarder)
  Logger.log "Listening on port #{host}:#{port}"

  handler = Thread.new do
    begin
      loop do
        Logger.log "waiting for connection on #{host}:#{port}"
        connection = server.accept
        Logger.log "got connection on #{host}:#{port}"
        Thread.new do
          begin
            forwarder.forward(connection)
          rescue
            Logger.log $!
          end
          Logger.log "completed connection on #{host}:#{port}"
        end
      end
    end
  end
  handler
end

#connection_details(payload) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/metasploit/aggregator/connection_manager.rb', line 112

def connection_details(payload)
  detail_map = {}
  details = @details_cache.session_details(payload)
  unless details.nil?
    details.each_pair do |key, value|
      detail_map[key] = value.to_s
      end
  end
  @cables.each do |cable|
    next unless cable.forwarder.connections.include?(payload)
    # TODO: improve how time is exposed for live connections
    time = cable.forwarder.connection_info(payload)['TIME']
    detail_map['LAST_SEEN'] = (Time.now - time).to_s unless time.nil?
  end
  detail_map
end

#connectionsObject



104
105
106
107
108
109
110
# File 'lib/metasploit/aggregator/connection_manager.rb', line 104

def connections
  connections = {}
  @cables.each do |cable|
    connections = connections.merge cable.forwarder.connections
  end
  connections
end

#park(payload) ⇒ Object



187
188
189
190
# File 'lib/metasploit/aggregator/connection_manager.rb', line 187

def park(payload)
  @router.add_route(nil, payload)
  Logger.log "parking #{payload}"
end

#register_forward(uuid, payload_list = nil) ⇒ Object



94
95
96
97
98
99
100
101
102
# File 'lib/metasploit/aggregator/connection_manager.rb', line 94

def register_forward(uuid, payload_list = nil)
  if payload_list.nil?
    @router.add_route(uuid, nil)
  else
    payload_list.each do |payload|
      @router.add_route(uuid, payload)
    end
  end
end

#remove_cable(host, port) ⇒ Object



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/metasploit/aggregator/connection_manager.rb', line 161

def remove_cable(host, port)
  @manager_mutex.synchronize do
    closed_servers = []
    @cables.each do |cable|
      addr = cable.server.local_address
      if addr.ip_address == host && addr.ip_port == port.to_i
        cable.server.close
        cable.thread.exit
        closed_servers << cable
      end
    end
    @cables -= closed_servers
  end
  return true
end

#stopObject



178
179
180
181
182
183
184
185
# File 'lib/metasploit/aggregator/connection_manager.rb', line 178

def stop
  @manager_mutex.synchronize do
    @cables.each do |listener|
      listener.server.close
      listener.thread.exit
    end
  end
end