Skip to content

Commit 9827e4a

Browse files
committed
Convert ldap modules to use the new ldap session type
1 parent 49fe400 commit 9827e4a

File tree

15 files changed

+167
-62
lines changed

15 files changed

+167
-62
lines changed

lib/msf/core/exploit/remote/kerberos/client.rb

+8-8
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ module Client
2727

2828
# @!attribute client
2929
# @return [Rex::Proto::Kerberos::Client] The kerberos client
30-
attr_accessor :client
30+
attr_accessor :kerberos_client
3131

3232
def initialize(info = {})
3333
super
@@ -96,20 +96,20 @@ def connect(opts={})
9696
protocol: 'tcp'
9797
)
9898

99-
disconnect if client
100-
self.client = kerb_client
99+
disconnect if kerberos_client
100+
self.kerberos_client = kerb_client
101101

102102
kerb_client
103103
end
104104

105105
# Disconnects the Kerberos client
106106
#
107107
# @param kerb_client [Rex::Proto::Kerberos::Client] the client to disconnect
108-
def disconnect(kerb_client = client)
108+
def disconnect(kerb_client = kerberos_client)
109109
kerb_client.close if kerb_client
110110

111-
if kerb_client == client
112-
self.client = nil
111+
if kerb_client == kerberos_client
112+
self.kerberos_client = nil
113113
end
114114
end
115115

@@ -129,7 +129,7 @@ def cleanup
129129
def send_request_as(opts = {})
130130
connect(opts)
131131
req = opts.fetch(:req) { build_as_request(opts) }
132-
res = client.send_recv(req)
132+
res = kerberos_client.send_recv(req)
133133
disconnect
134134
res
135135
end
@@ -143,7 +143,7 @@ def send_request_as(opts = {})
143143
def send_request_tgs(opts = {})
144144
connect(opts)
145145
req = opts.fetch(:req) { build_tgs_request(opts) }
146-
res = client.send_recv(req)
146+
res = kerberos_client.send_recv(req)
147147
disconnect
148148
res
149149
end

lib/msf/core/exploit/remote/ldap.rb

+7-5
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ module Exploit::Remote::LDAP
1212
include Msf::Exploit::Remote::Kerberos::Ticket::Storage
1313
include Msf::Exploit::Remote::Kerberos::ServiceAuthenticator::Options
1414
include Metasploit::Framework::LDAP::Client
15-
include Msf::OptionalSession::LDAP
1615

1716
# Initialize the LDAP client and set up the LDAP specific datastore
1817
# options to allow the client to perform authentication and timeout
@@ -28,6 +27,8 @@ def initialize(info = {})
2827
super
2928

3029
register_options([
30+
Opt::RHOST,
31+
Opt::RPORT(389),
3132
OptBool.new('SSL', [false, 'Enable SSL on the LDAP connection', false]),
3233
Msf::OptString.new('DOMAIN', [false, 'The domain to authenticate to']),
3334
Msf::OptString.new('USERNAME', [false, 'The username to authenticate with'], aliases: ['BIND_DN']),
@@ -95,7 +96,6 @@ def get_connect_opts
9596
# @return [Object] The result of whatever the block that was
9697
# passed in via the "block" parameter yielded.
9798
def ldap_connect(opts = {}, &block)
98-
return yield session.client if session
9999
ldap_open(get_connect_opts.merge(opts), &block)
100100
end
101101

@@ -111,7 +111,6 @@ def ldap_connect(opts = {}, &block)
111111
# @return [Object] The result of whatever the block that was
112112
# passed in via the "block" parameter yielded.
113113
def ldap_open(connect_opts, &block)
114-
return yield session.client if session
115114
opts = resolve_connect_opts(connect_opts)
116115
Rex::Proto::LDAP::Client.open(opts, &block)
117116
end
@@ -136,8 +135,6 @@ def resolve_connect_opts(connect_opts)
136135
# @yieldparam ldap [Rex::Proto::LDAP::Client] The LDAP connection handle to use for connecting to
137136
# the target LDAP server.
138137
def ldap_new(opts = {})
139-
return yield session.client if session
140-
141138
ldap = Rex::Proto::LDAP::Client.new(resolve_connect_opts(get_connect_opts.merge(opts)))
142139

143140
# NASTY, but required
@@ -182,6 +179,11 @@ def ldap.use_connection(args)
182179
# bind request failed.
183180
# @return [Nil] This function does not return any data.
184181
def validate_bind_success!(ldap)
182+
if defined?(:session) && session
183+
vprint_good('Successfully bound to the LDAP server via existing SESSION!')
184+
return
185+
end
186+
185187
bind_result = ldap.get_operation_result.table
186188

187189
# Codes taken from https://ldap.com/ldap-result-code-reference-core-ldapv3-result-codes

lib/msf/core/optional_session/ldap.rb

+26-7
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,38 @@ def initialize(info = {})
3434
)
3535

3636
add_info('New in Metasploit 6.4 - This module can target a %grnSESSION%clr or an %grnRHOST%clr')
37-
else
38-
register_options(
39-
[
40-
Msf::Opt::RHOST,
41-
Msf::Opt::RPORT(389),
42-
]
43-
)
4437
end
4538
end
4639

4740
def optional_session_enabled?
4841
framework.features.enabled?(Msf::FeatureManager::LDAP_SESSION_TYPE)
4942
end
43+
44+
# @see #ldap_open
45+
# @return [Object] The result of whatever the block that was
46+
# passed in via the "block" parameter yielded.
47+
def ldap_connect(opts = {}, &block)
48+
if session && !opts[:base].blank?
49+
session.client.base = opts[:base]
50+
end
51+
return yield session.client if session
52+
ldap_open(get_connect_opts.merge(opts), &block)
53+
end
54+
55+
# Create a new LDAP connection using Rex::Proto::LDAP::Client.new and yield the
56+
# resulting connection object to the caller of this method.
57+
#
58+
# @param opts [Hash] A hash containing the connection options for the
59+
# LDAP connection to the target server.
60+
# @yieldparam ldap [Rex::Proto::LDAP::Client] The LDAP connection handle to use for connecting to
61+
# the target LDAP server.
62+
def ldap_new(opts = {})
63+
if session && !opts[:base].blank?
64+
session.client.base = opts[:base]
65+
end
66+
return yield session.client if session
67+
super
68+
end
5069
end
5170
end
5271
end

lib/rex/proto/kerberos/client.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def initialize(opts = {})
4545
# @raise [RuntimeError] if the connection can not be created
4646
def connect
4747
return connection if connection
48-
48+
raise ArgumentError, 'Missing remote address' unless self.host && self.port
4949
case protocol
5050
when 'tcp'
5151
self.connection = create_tcp_connection

modules/auxiliary/admin/ldap/ad_cs_cert_template.rb

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
class MetasploitModule < Msf::Auxiliary
77

88
include Msf::Exploit::Remote::LDAP
9+
include Msf::OptionalSession::LDAP
910
include Msf::Auxiliary::Report
1011

1112
IGNORED_ATTRIBUTES = [

modules/auxiliary/admin/ldap/rbcd.rb

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
class MetasploitModule < Msf::Auxiliary
77

88
include Msf::Exploit::Remote::LDAP
9+
include Msf::OptionalSession::LDAP
910

1011
ATTRIBUTE = 'msDS-AllowedToActOnBehalfOfOtherIdentity'.freeze
1112

modules/auxiliary/admin/ldap/shadow_credentials.rb

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ class MetasploitModule < Msf::Auxiliary
77

88
include Msf::Auxiliary::Report
99
include Msf::Exploit::Remote::LDAP
10+
include Msf::OptionalSession::LDAP
1011

1112
ATTRIBUTE = 'msDS-KeyCredentialLink'.freeze
1213

modules/auxiliary/admin/ldap/vmware_vcenter_vmdir_auth_bypass.rb

+5-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
class MetasploitModule < Msf::Auxiliary
77

88
include Msf::Exploit::Remote::LDAP
9+
include Msf::OptionalSession::LDAP
910
include Msf::Exploit::Remote::CheckModule
1011

1112
def initialize(info = {})
@@ -42,6 +43,7 @@ def initialize(info = {})
4243
'DefaultAction' => 'Add',
4344
'DefaultOptions' => {
4445
'SSL' => true,
46+
'RPORT' => 636, # SSL/TLS
4547
'CheckModule' => 'auxiliary/gather/vmware_vcenter_vmdir_ldap'
4648
},
4749
'Notes' => {
@@ -53,10 +55,9 @@ def initialize(info = {})
5355
)
5456

5557
register_options([
56-
Opt::RPORT(636), # SSL/TLS
5758
OptString.new('BASE_DN', [false, 'LDAP base DN if you already have it']),
58-
OptString.new('NEW_USERNAME', [false, 'Username of admin user to add']),
59-
OptString.new('NEW_PASSWORD', [false, 'Password of admin user to add'])
59+
OptString.new('NEW_USERNAME', [true, 'Username of admin user to add']),
60+
OptString.new('NEW_PASSWORD', [true, 'Password of admin user to add'])
6061
])
6162
end
6263

@@ -99,7 +100,7 @@ def run
99100
end
100101

101102
ldap_connect do |ldap|
102-
print_status("Bypassing LDAP auth in vmdir service at #{peer}")
103+
print_status("Bypassing LDAP auth in vmdir service at #{ldap.peerinfo}")
103104
auth_bypass(ldap)
104105

105106
print_status("Adding admin user #{new_username} with password #{new_password}")

modules/auxiliary/gather/asrep.rb

+8-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ class MetasploitModule < Msf::Auxiliary
77
include Msf::Exploit::Remote::Kerberos::Client
88
include Msf::Exploit::Remote::LDAP
99
include Msf::Exploit::Remote::LDAP::Queries
10+
include Msf::OptionalSession::LDAP
1011

1112
def initialize(info = {})
1213
super(
@@ -42,11 +43,16 @@ def initialize(info = {})
4243

4344
register_options(
4445
[
46+
Opt::RHOSTS(nil, true, 'The target KDC, see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html'),
4547
OptPath.new('USER_FILE', [ false, 'File containing usernames, one per line' ], conditions: %w[ACTION == BRUTE_FORCE]),
4648
OptBool.new('USE_RC4_HMAC', [ true, 'Request using RC4 hash instead of default encryption types (faster to crack)', true]),
4749
OptString.new('Rhostname', [ true, "The domain controller's hostname"], aliases: ['LDAP::Rhostname']),
4850
]
4951
)
52+
register_option_group(name: 'SESSION',
53+
description: 'Used when connecting to LDAP over an existing SESSION',
54+
option_names: %w[RHOSTS],
55+
required_options: %w[SESSION RHOSTS])
5056
register_advanced_options(
5157
[
5258
OptEnum.new('LDAP::Auth', [true, 'The Authentication mechanism to use', Msf::Exploit::Remote::AuthOption::NTLM, Msf::Exploit::Remote::AuthOption::LDAP_OPTIONS]),
@@ -136,7 +142,8 @@ def roast(username)
136142
client_name: username,
137143
realm: datastore['DOMAIN'],
138144
offered_etypes: etypes,
139-
rport: 88
145+
rport: 88,
146+
rhost: datastore['RHOST']
140147
)
141148
hash = format_as_rep_to_john_hash(res.as_rep)
142149
print_line(hash)

modules/auxiliary/gather/ldap_esc_vulnerable_cert_finder.rb

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
class MetasploitModule < Msf::Auxiliary
22

33
include Msf::Exploit::Remote::LDAP
4+
include Msf::OptionalSession::LDAP
45

56
ADS_GROUP_TYPE_BUILTIN_LOCAL_GROUP = 0x00000001
67
ADS_GROUP_TYPE_GLOBAL_GROUP = 0x00000002
@@ -459,7 +460,7 @@ def run
459460
else
460461
print_status('Discovering base DN automatically')
461462

462-
unless (@base_dn = discover_base_dn(ldap))
463+
unless (@base_dn = ldap.base_dn)
463464
fail_with(Failure::NotFound, "Couldn't discover base DN!")
464465
end
465466
end

0 commit comments

Comments
 (0)