@@ -50,9 +50,9 @@ def initialize(info = {})
50
50
allows enrollment in and which SIDs are authorized to use that certificate server to
51
51
perform this enrollment operation.
52
52
53
- Currently the module is capable of checking for certificates that are vulnerable to ESC1, ESC2, ESC3, ESC13 ,
54
- and ESC15. The module is limited to checking for these techniques due to them being identifiable remotely from
55
- a normal user account by analyzing the objects in LDAP.
53
+ Currently the module is capable of checking for certificates that are vulnerable to ESC1, ESC2, ESC3, ESC4 ,
54
+ ESC13, and ESC15. The module is limited to checking for these techniques due to them being identifiable
55
+ remotely from a normal user account by analyzing the objects in LDAP.
56
56
} ,
57
57
'Author' => [
58
58
'Grant Willcox' , # Original module author
@@ -247,7 +247,7 @@ def query_ldap_server_certificates(esc_raw_filter, esc_id, notes: [])
247
247
248
248
def convert_sids_to_human_readable_name ( sids_array )
249
249
output = [ ]
250
- for sid in sids_array
250
+ sids_array . each do | sid |
251
251
sid_entry = get_object_by_sid ( sid )
252
252
if sid_entry . nil?
253
253
print_warning ( "Could not find any details on the LDAP server for SID #{ sid } !" )
@@ -392,8 +392,9 @@ def find_esc4_vuln_cert_templates
392
392
# https://learn.microsoft.com/en-us/windows/win32/adsi/search-filter-syntax?redirectedfrom=MSDN
393
393
filter_with_user = "(|(member:1.2.840.113556.1.4.1941:=#{ our_account [ :dn ] . first } )"
394
394
user_groups . each do |sid |
395
- obj = query_ldap_server ( "(objectSid= #{ sid } )" , [ 'dn' ] ) &. first
395
+ obj = get_object_by_sid ( sid )
396
396
print_error ( 'Failed to lookup SID.' ) unless obj
397
+
397
398
filter_with_user << "(member:1.2.840.113556.1.4.1941:=#{ obj [ :dn ] . first } )" if obj
398
399
end
399
400
filter_with_user << ')'
@@ -442,28 +443,28 @@ def find_esc4_vuln_cert_templates
442
443
443
444
# SIDs that can edit the template that the user we've authenticated with are also a part of
444
445
user_write_priv_sids = [ ]
445
- note = [ ]
446
+ notes = [ ]
446
447
447
448
# Main reason for splitting user_can_edit and group_can_edit is so "note" can be more descriptive
448
449
if user_can_edit
449
450
user_write_priv_sids << user_can_edit
450
- note << "ESC4: The account: #{ sam_account_name } has edit permissions over the template #{ certificate_symbol } making it vulnerable to ESC4"
451
+ notes << "ESC4: The account: #{ sam_account_name } has edit permissions over the template #{ certificate_symbol } making it vulnerable to ESC4"
451
452
end
452
453
453
454
if group_can_edit . any?
454
455
user_write_priv_sids . concat ( group_can_edit . map ( &:to_s ) )
455
- note << "ESC4: The account: #{ sam_account_name } is a part of the following groups: (#{ convert_sids_to_human_readable_name ( group_can_edit ) . map ( &:name ) . join ( ', ' ) } ) which have edit permissions over the template #{ certificate_symbol } making it vulnerable to ESC4 "
456
+ notes << "ESC4: The account: #{ sam_account_name } is a part of the following groups: (#{ convert_sids_to_human_readable_name ( group_can_edit ) . map ( &:name ) . join ( ', ' ) } ) which have edit permissions over the template object "
456
457
end
457
458
458
459
next unless user_write_priv_sids . any?
459
460
460
- if @vuln_certificate_details . key? ( certificate_symbol )
461
- @vuln_certificate_details [ certificate_symbol ] [ :vulns ] << 'ESC4'
462
- @vuln_certificate_details [ certificate_symbol ] [ :notes ] . concat ( note )
463
- @vuln_certificate_details [ certificate_symbol ] [ :certificate_write_priv_sids ] ||= convert_sids_to_human_readable_name ( user_write_priv_sids )
461
+ if @certificate_details . key? ( certificate_symbol )
462
+ @certificate_details [ certificate_symbol ] [ :techniques ] << 'ESC4'
463
+ @certificate_details [ certificate_symbol ] [ :notes ] . concat ( notes )
464
464
else
465
- @vuln_certificate_details [ certificate_symbol ] = { vulns : [ 'ESC4' ] , dn : entry [ :dn ] [ 0 ] , certificate_enrollment_sids : convert_sids_to_human_readable_name ( allowed_sids ) , ca_servers_n_enrollment_sids : { } , certificate_write_priv_sids : convert_sids_to_human_readable_name ( user_write_priv_sids ) , notes : note }
465
+ @certificate_details [ certificate_symbol ] = build_certificate_details ( entry , allowed_sids , techniques : %w[ ESC4 ] , notes : notes )
466
466
end
467
+ @certificate_details [ certificate_symbol ] [ :write_enabled_sids ] ||= convert_sids_to_human_readable_name ( user_write_priv_sids )
467
468
end
468
469
end
469
470
@@ -616,7 +617,7 @@ def find_enrollable_vuln_certificate_templates
616
617
end
617
618
618
619
def print_vulnerable_cert_info
619
- vuln_certificate_details = @certificate_details . select do |_key , hash |
620
+ vuln_certificate_details = @certificate_details . sort . to_h . select do |_key , hash |
620
621
select = true
621
622
select = false unless datastore [ 'REPORT_PRIVENROLLABLE' ] || hash [ :enrollment_sids ] . any? do |sid |
622
623
# compare based on RIDs to avoid issues language specific issues
@@ -698,9 +699,9 @@ def print_vulnerable_cert_info
698
699
end
699
700
end
700
701
701
- if hash [ :certificate_write_priv_sids ]
702
+ if hash [ :write_enabled_sids ]
702
703
print_status ( ' Certificate Template Write-Enabled SIDs:' )
703
- hash [ :certificate_write_priv_sids ] . each do |sid |
704
+ hash [ :write_enabled_sids ] . each do |sid |
704
705
print_status ( " * #{ highlight_sid ( sid ) } " )
705
706
end
706
707
end
0 commit comments