Skip to content

Commit c241018

Browse files
author
Brent Cook
committed
Land rapid7#5394, UUID registration and tracking
2 parents 6669665 + 6d488c6 commit c241018

File tree

12 files changed

+210
-23
lines changed

12 files changed

+210
-23
lines changed

lib/msf/base/serializer/readable_text.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,8 +589,11 @@ def self.dump_sessions_verbose(framework, opts={})
589589
sess_via = session.via_exploit.to_s
590590
sess_type = session.type.to_s
591591
sess_uuid = session.payload_uuid.to_s
592+
sess_puid = session.payload_uuid.respond_to?(:puid_hex) ? session.payload_uuid.puid_hex : nil
593+
592594
sess_checkin = "<none>"
593595
sess_machine_id = session.machine_id.to_s
596+
sess_registration = "No"
594597

595598
if session.respond_to? :platform
596599
sess_type << (" " + session.platform)
@@ -600,6 +603,13 @@ def self.dump_sessions_verbose(framework, opts={})
600603
sess_checkin = "#{(Time.now.to_i - session.last_checkin.to_i)}s ago @ #{session.last_checkin.to_s}"
601604
end
602605

606+
if session.payload_uuid.respond_to?(:puid_hex) && (uuid_info = framework.uuid_db[sess_puid])
607+
sess_registration = "Yes"
608+
if uuid_info['name']
609+
sess_registration << " - Name=\"#{uuid_info['name']}\""
610+
end
611+
end
612+
603613
out << " Session ID: #{sess_id}\n"
604614
out << " Type: #{sess_type}\n"
605615
out << " Info: #{sess_info}\n"
@@ -608,6 +618,10 @@ def self.dump_sessions_verbose(framework, opts={})
608618
out << " UUID: #{sess_uuid}\n"
609619
out << " MachineID: #{sess_machine_id}\n"
610620
out << " CheckIn: #{sess_checkin}\n"
621+
out << " Registered: #{sess_registration}\n"
622+
623+
624+
611625
out << "\n"
612626
end
613627

lib/msf/core/framework.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ module Offspring
7373
require 'msf/core/plugin_manager'
7474
require 'msf/core/db_manager'
7575
require 'msf/core/event_dispatcher'
76-
76+
require 'rex/json_hash_file'
7777

7878
#
7979
# Creates an instance of the framework context.
@@ -91,6 +91,7 @@ def initialize(options={})
9191
self.datastore = DataStore.new
9292
self.jobs = Rex::JobContainer.new
9393
self.plugins = PluginManager.new(self)
94+
self.uuid_db = Rex::JSONHashFile.new(::File.join(Msf::Config.config_directory, "payloads.json"))
9495

9596
# Configure the thread factory
9697
Rex::ThreadFactory.provider = Metasploit::Framework::ThreadFactoryProvider.new(framework: self)
@@ -187,6 +188,12 @@ def version
187188
# unloading of plugins.
188189
#
189190
attr_reader :plugins
191+
#
192+
# The framework instance's payload uuid database. The payload uuid
193+
# database is used to record and match the unique ID values embedded
194+
# into generated payloads.
195+
#
196+
attr_reader :uuid_db
190197

191198
# The framework instance's db manager. The db manager
192199
# maintains the database db and handles db events
@@ -243,6 +250,7 @@ def threads?
243250
attr_writer :jobs # :nodoc:
244251
attr_writer :plugins # :nodoc:
245252
attr_writer :db # :nodoc:
253+
attr_writer :uuid_db # :nodoc:
246254
end
247255

248256
class FrameworkEventSubscriber

lib/msf/core/handler/reverse_http.rb

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ def initialize(info = {})
5656
OptAddress.new('ReverseListenerBindAddress', [ false, 'The specific IP address to bind to on the local system']),
5757
OptInt.new('ReverseListenerBindPort', [ false, 'The port to bind to on the local system if different from LPORT' ]),
5858
OptBool.new('OverrideRequestHost', [ false, 'Forces clients to connect to LHOST:LPORT instead of keeping original payload host', false ]),
59-
OptString.new('HttpUnknownRequestResponse', [ false, 'The returned HTML response body when the handler receives a request that is not from a payload', '<html><body><h1>It works!</h1></body></html>' ])
59+
OptString.new('HttpUnknownRequestResponse', [ false, 'The returned HTML response body when the handler receives a request that is not from a payload', '<html><body><h1>It works!</h1></body></html>' ]),
60+
OptBool.new('IgnoreUnknownPayloads', [false, 'Whether to drop connections from payloads using unknown UUIDs', false])
6061
], Msf::Handler::ReverseHttp)
6162
end
6263

@@ -153,6 +154,10 @@ def setup_handler
153154

154155
print_status("Started #{scheme.upcase} reverse handler on #{listener_uri}")
155156
lookup_proxy_settings
157+
158+
if datastore['IgnoreUnknownPayloads']
159+
print_status("Handler is ignoring unknown payloads, there are #{framework.uuid_db.keys.length} UUIDs whitelisted")
160+
end
156161
end
157162

158163
#
@@ -228,6 +233,21 @@ def on_request(cli, req, obj)
228233
conn_id = generate_uri_uuid(URI_CHECKSUM_CONN, uuid)
229234
end
230235

236+
# Validate known UUIDs for all requests if IgnoreUnknownPayloads is set
237+
if datastore['IgnoreUnknownPayloads'] && ! framework.uuid_db[uuid.puid_hex]
238+
print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Ignoring request with unknown UUID")
239+
info[:mode] = :unknown_uuid
240+
end
241+
242+
# Validate known URLs for all session init requests if IgnoreUnknownPayloads is set
243+
if datastore['IgnoreUnknownPayloads'] && info[:mode].to_s =~ /^init_/
244+
allowed_urls = framework.uuid_db[uuid.puid_hex]['urls'] || []
245+
unless allowed_urls.include?(req.relative_resource)
246+
print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Ignoring request with unknown UUID URL #{req.relative_resource}")
247+
info[:mode] = :unknown_uuid_url
248+
end
249+
end
250+
231251
self.pending_connections += 1
232252

233253
# Process the requested resource.
@@ -374,7 +394,9 @@ def on_request(cli, req, obj)
374394
})
375395

376396
else
377-
print_status("#{cli.peerhost}:#{cli.peerport} Unknown request to #{req.relative_resource} #{req.inspect}...")
397+
unless [:unknown_uuid, :unknown_uuid_url].include?(info[:mode])
398+
print_status("#{cli.peerhost}:#{cli.peerport} Unknown request to #{req.relative_resource} with UA #{req.headers['User-Agent']}...")
399+
end
378400
resp.code = 200
379401
resp.message = "OK"
380402
resp.body = datastore['HttpUnknownRequestResponse'].to_s

lib/msf/core/payload/php/reverse_tcp.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
require 'msf/core'
55
require 'msf/core/payload/php/send_uuid'
6-
require 'msf/core/payload/uuid_options'
6+
require 'msf/core/payload/uuid/options'
77

88
module Msf
99

@@ -16,7 +16,7 @@ module Msf
1616
module Payload::Php::ReverseTcp
1717

1818
include Msf::Payload::Php::SendUUID
19-
include Msf::Payload::UUIDOptions
19+
include Msf::Payload::UUID::Options
2020

2121
#
2222
# Generate the first stage
@@ -76,7 +76,7 @@ def generate_reverse_tcp(opts={})
7676

7777
php << php_send_uuid if include_send_uuid
7878

79-
php << %Q^switch ($s_type) {
79+
php << %Q^switch ($s_type) {
8080
case 'stream': $len = fread($s, 4); break;
8181
case 'socket': $len = socket_read($s, 4); break;
8282
}
@@ -90,7 +90,7 @@ def generate_reverse_tcp(opts={})
9090
9191
$b = '';
9292
while (strlen($b) < $len) {
93-
switch ($s_type) {
93+
switch ($s_type) {
9494
case 'stream': $b .= fread($s, $len-strlen($b)); break;
9595
case 'socket': $b .= socket_read($s, $len-strlen($b)); break;
9696
}

lib/msf/core/payload/transport_config.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
# -*- coding: binary -*-
22

3-
require 'msf/core/payload/uuid_options'
3+
require 'msf/core/payload/uuid/options'
44

55
##
66
# This module contains helper functions for creating the transport
77
# configuration stubs that are used for Meterpreter payloads.
88
##
99
module Msf::Payload::TransportConfig
1010

11-
include Msf::Payload::UUIDOptions
11+
include Msf::Payload::UUID::Options
1212

1313
def transport_config_reverse_tcp(opts={})
1414
config = transport_config_bind_tcp(opts)

lib/msf/core/payload/uuid_options.rb renamed to lib/msf/core/payload/uuid/options.rb

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#
88
# This module provides datastore option definitions and helper methods for payload modules that support UUIDs
99
#
10-
module Msf::Payload::UUIDOptions
10+
module Msf::Payload::UUID::Options
1111

1212
include Rex::Payloads::Meterpreter::UriChecksum
1313

@@ -17,6 +17,8 @@ def initialize(info = {})
1717
[
1818
Msf::OptString.new('PayloadUUIDSeed', [ false, 'A string to use when generating the payload UUID (deterministic)']),
1919
Msf::OptString.new('PayloadUUIDRaw', [ false, 'A hex string representing the raw 8-byte PUID value for the UUID']),
20+
Msf::OptString.new('PayloadUUIDName', [ false, 'A human-friendly name to reference this unique payload (requires tracking)']),
21+
Msf::OptBool.new('PayloadUUIDTracking', [ true, 'Whether or not to automatically register generated UUIDs', false]),
2022
], self.class)
2123
end
2224

@@ -31,7 +33,7 @@ def initialize(info = {})
3133
def generate_uri_uuid_mode(mode,len=nil)
3234
sum = uri_checksum_lookup(mode)
3335

34-
# The URI length may not have room for an embedded checksum
36+
# The URI length may not have room for an embedded UUID
3537
if len && len < URI_CHECKSUM_UUID_MIN_LEN
3638
# Throw an error if the user set a seed, but there is no room for it
3739
if datastore['PayloadUUIDSeed'].to_s.length > 0 ||datastore['PayloadUUIDRaw'].to_s.length > 0
@@ -40,7 +42,11 @@ def generate_uri_uuid_mode(mode,len=nil)
4042
return "/" + generate_uri_checksum(sum, len, prefix="")
4143
end
4244

43-
generate_uri_uuid(sum, generate_payload_uuid, len)
45+
uuid = generate_payload_uuid
46+
uri = generate_uri_uuid(sum, uuid, len)
47+
record_payload_uuid_url(uuid, uri)
48+
49+
uri
4450
end
4551

4652
# Generate a Payload UUID
@@ -66,7 +72,48 @@ def generate_payload_uuid
6672
conf[:puid] = puid_raw
6773
end
6874

69-
Msf::Payload::UUID.new(conf)
75+
if datastore['PayloadUUIDName'].to_s.length > 0 && ! datastore['PayloadUUIDTracking']
76+
raise ArgumentError, "The PayloadUUIDName value is ignored unless PayloadUUIDTracking is enabled"
77+
end
78+
79+
# Generate the UUID object
80+
uuid = Msf::Payload::UUID.new(conf)
81+
record_payload_uuid(uuid)
82+
83+
uuid
84+
end
85+
86+
# Store a UUID in the JSON database if tracking is enabled
87+
def record_payload_uuid(uuid, info={})
88+
return unless datastore['PayloadUUIDTracking']
89+
90+
uuid_info = info.merge({
91+
arch: uuid.arch,
92+
platform: uuid.platform,
93+
timestamp: uuid.timestamp,
94+
payload: self.fullname,
95+
datastore: self.datastore
96+
})
97+
98+
if datastore['PayloadUUIDSeed'].to_s.length > 0
99+
uuid_info[:seed] = datastore['PayloadUUIDSeed']
100+
end
101+
102+
if datastore['PayloadUUIDName'].to_s.length > 0
103+
uuid_info[:name] = datastore['PayloadUUIDName']
104+
end
105+
106+
framework.uuid_db[uuid.puid_hex] = uuid_info
107+
end
108+
109+
# Store a UUID URL in the JSON database if tracking is enabled
110+
def record_payload_uuid_url(uuid, url)
111+
return unless datastore['PayloadUUIDTracking']
112+
uuid_info = framework.uuid_db[uuid.puid_hex]
113+
uuid_info['urls'] ||= []
114+
uuid_info['urls'] << url
115+
uuid_info['urls'].uniq!
116+
framework.uuid_db[uuid.puid_hex] = uuid_info
70117
end
71118

72119
end

lib/msf/core/payload/windows/reverse_http.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
require 'msf/core/payload/transport_config'
55
require 'msf/core/payload/windows/block_api'
66
require 'msf/core/payload/windows/exitfunk'
7-
require 'msf/core/payload/uuid_options'
7+
require 'msf/core/payload/uuid/options'
88

99
module Msf
1010

@@ -20,7 +20,7 @@ module Payload::Windows::ReverseHttp
2020
include Msf::Payload::Windows
2121
include Msf::Payload::Windows::BlockApi
2222
include Msf::Payload::Windows::Exitfunk
23-
include Msf::Payload::UUIDOptions
23+
include Msf::Payload::UUID::Options
2424

2525
#
2626
# Register reverse_http specific options

lib/msf/core/payload/windows/x64/reverse_http.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
require 'msf/core/payload/transport_config'
55
require 'msf/core/payload/windows/x64/block_api'
66
require 'msf/core/payload/windows/x64/exitfunk'
7-
require 'msf/core/payload/uuid_options'
7+
require 'msf/core/payload/uuid/options'
88

99
module Msf
1010

@@ -20,7 +20,7 @@ module Payload::Windows::ReverseHttp_x64
2020
include Msf::Payload::Windows
2121
include Msf::Payload::Windows::BlockApi_x64
2222
include Msf::Payload::Windows::Exitfunk_x64
23-
include Msf::Payload::UUIDOptions
23+
include Msf::Payload::UUID::Options
2424

2525
#
2626
# Register reverse_http specific options

0 commit comments

Comments
 (0)