@@ -8,6 +8,7 @@ module Exploit::Remote::LDAP
8
8
module ActiveDirectory
9
9
include Msf ::Exploit ::Remote ::LDAP
10
10
include Msf ::Exploit ::Remote ::LDAP ::EntryCache
11
+ include Msf ::Exploit ::Remote ::LDAP ::ActiveDirectory ::SecurityDescriptorMatcher
11
12
12
13
LDAP_CAP_ACTIVE_DIRECTORY_OID = '1.2.840.113556.1.4.800' . freeze
13
14
LDAP_SERVER_SD_FLAGS_OID = '1.2.840.113556.1.4.801' . freeze
@@ -16,56 +17,6 @@ module ActiveDirectory
16
17
DACL_SECURITY_INFORMATION = 0x4
17
18
SACL_SECURITY_INFORMATION = 0x8
18
19
19
- # Match an ACE when *any* of the specified permissions are allowed or *all* of the specified permissions are
20
- # denied.
21
- class ACEMatcherAllowAll
22
- attr_reader :permissions
23
-
24
- def initialize ( permissions )
25
- @permissions = Array . wrap ( permissions )
26
- end
27
-
28
- def call ( ace )
29
- target_permissions = ace . body . access_mask . permissions
30
-
31
- if target_permissions . empty?
32
- return false
33
- elsif Rex ::Proto ::MsDtyp ::MsDtypAceType . allowed? ( ace . header . ace_type )
34
- return @permissions . all? { |perm | target_permissions . include? ( perm ) }
35
- elsif Rex ::Proto ::MsDtyp ::MsDtypAceType . denied? ( ace . header . ace_type )
36
- # if any target permission is denied, then all of them can't be allowed
37
- return @permissions . any? { |perm | target_permissions . include? ( perm ) }
38
- end
39
-
40
- false
41
- end
42
- end
43
-
44
- # Match an ACE when *all* of the specified permissions are allowed or *any* of the specified permissions are
45
- # denied.
46
- class ACEMatcherAllowAny
47
- attr_reader :permissions
48
-
49
- def initialize ( permissions )
50
- @permissions = Array . wrap ( permissions )
51
- end
52
-
53
- def call ( ace )
54
- target_permissions = ace . body . access_mask . permissions
55
-
56
- if target_permissions . empty?
57
- return false
58
- elsif Rex ::Proto ::MsDtyp ::MsDtypAceType . allowed? ( ace . header . ace_type )
59
- return @permissions . any? { |perm | target_permissions . include? ( perm ) }
60
- elsif Rex ::Proto ::MsDtyp ::MsDtypAceType . denied? ( ace . header . ace_type )
61
- # if all target permissions are denied, then none of them can be allowed
62
- return @permissions . all? { |perm | target_permissions . include? ( perm ) }
63
- end
64
-
65
- false
66
- end
67
- end
68
-
69
20
# Query the remote server via the provided LDAP connection to determine if it's an Active Directory LDAP server.
70
21
# More specifically, this ensures that it reports active directory capabilities and the whoami extension.
71
22
#
@@ -310,51 +261,45 @@ def adds_sd_grants_permissions?(ldap, security_descriptor, matcher, test_sid: ni
310
261
end
311
262
312
263
test_member_sids = nil
313
- security_descriptor . dacl . aces . each do |ace |
314
- # only processing simple allow and deny types right now
315
- case ace . header . ace_type
316
- when Rex ::Proto ::MsDtyp ::MsDtypAceType ::ACCESS_ALLOWED_ACE_TYPE
317
- eval_result = true
318
- when Rex ::Proto ::MsDtyp ::MsDtypAceType ::ACCESS_ALLOWED_OBJECT_ACE_TYPE
319
- eval_result = true
320
- when Rex ::Proto ::MsDtyp ::MsDtypAceType ::ACCESS_DENIED_ACE_TYPE
321
- eval_result = false
322
- when Rex ::Proto ::MsDtyp ::MsDtypAceType ::ACCESS_DENIED_OBJECT_ACE_TYPE
323
- eval_result = false
324
- else
325
- next # skip ACEs that are neither allow or deny
326
- end
327
264
328
- next unless matcher . call ( ace )
265
+ dacl_aces = [ ]
266
+ # because deny entries take precedence, process them first
267
+ dacl_aces += security_descriptor . dacl . aces . select { |ace | Rex ::Proto ::MsDtyp ::MsDtypAceType . deny? ( ace . header . ace_type ) }
268
+ dacl_aces += security_descriptor . dacl . aces . select { |ace | Rex ::Proto ::MsDtyp ::MsDtypAceType . allow? ( ace . header . ace_type ) }
269
+
270
+ dacl_aces . each do |ace |
271
+ next if matcher . ignore_ace? ( ace )
329
272
330
273
case ace . body . sid
331
274
when Rex ::Proto ::Secauthz ::WellKnownSids ::SECURITY_WORLD_SID
332
- return eval_result
275
+ matcher . apply_ace! ( ace )
333
276
when Rex ::Proto ::Secauthz ::WellKnownSids ::SECURITY_PRINCIPAL_SELF_SID
334
- return eval_result if self_sid == test_sid
277
+ matcher . apply_ace! ( ace ) if self_sid == test_sid
335
278
when Rex ::Proto ::Secauthz ::WellKnownSids ::SECURITY_CREATOR_OWNER_SID
336
- return eval_result if security_descriptor . owner_sid == test_sid
279
+ matcher . apply_ace! ( ace ) if security_descriptor . owner_sid == test_sid
337
280
when Rex ::Proto ::Secauthz ::WellKnownSids ::SECURITY_CREATOR_GROUP_SID
338
- return eval_result if security_descriptor . group_sid == test_sid
281
+ matcher . apply_ace! ( ace ) if security_descriptor . group_sid == test_sid
339
282
when test_sid
340
- return eval_result
283
+ matcher . apply_ace! ( ace )
341
284
else
342
285
ldap_object = adds_get_object_by_sid ( ldap , ace . body . sid )
343
286
next unless ldap_object && ldap_object [ :objectClass ] . include? ( 'group' )
344
287
345
- member_sids = adds_query_group_members ( ldap , ldap_object [ :dN ] . first , inherited : false ) . map { |member | Rex ::Proto ::MsDtyp ::MsDtypSid . read ( member [ :objectSid ] . first ) }
346
- return eval_result if member_sids . include? ( test_sid )
288
+ member_sids = adds_query_group_members ( ldap , ldap_object . dn , inherited : false ) . map { |member | Rex ::Proto ::MsDtyp ::MsDtypSid . read ( member [ :objectSid ] . first ) }
289
+ matcher . apply_ace! ( ace ) if member_sids . include? ( test_sid )
347
290
348
291
if test_member_sids . nil?
349
292
test_obj = adds_get_object_by_sid ( ldap , test_sid )
350
- test_member_sids = adds_query_member_groups ( ldap , test_obj [ :dN ] . first , inherited : true ) . map { |member | Rex ::Proto ::MsDtyp ::MsDtypSid . read ( member [ :objectSid ] . first ) }
293
+ test_member_sids = adds_query_member_groups ( ldap , test_obj . dn , inherited : true ) . map { |member | Rex ::Proto ::MsDtyp ::MsDtypSid . read ( member [ :objectSid ] . first ) }
351
294
end
352
295
353
- return eval_result if member_sids . any? { |member_sid | test_member_sids . include? ( member_sid ) }
296
+ matcher . apply_ace! ( ace ) if member_sids . any? { |member_sid | test_member_sids . include? ( member_sid ) }
354
297
end
298
+
299
+ break if matcher . satisfied?
355
300
end
356
301
357
- false
302
+ matcher . affirmative?
358
303
end
359
304
360
305
# Determine if a security descriptor will grant the permissions identified by *matcher* to the
0 commit comments