@@ -3,6 +3,7 @@ class MetasploitModule < Msf::Auxiliary
3
3
include Msf ::Auxiliary ::Report
4
4
include Msf ::Exploit ::Remote ::LDAP
5
5
include Msf ::OptionalSession ::LDAP
6
+ include Rex ::Proto ::MsDnsp
6
7
include Rex ::Proto ::Secauthz
7
8
include Rex ::Proto ::LDAP
8
9
@@ -573,31 +574,37 @@ def find_enrollable_vuln_certificate_templates
573
574
allowed_sids = parse_acl ( security_descriptor . dacl ) if security_descriptor . dacl
574
575
next if allowed_sids . empty?
575
576
576
- service = report_service ( {
577
- host : ca_server [ :dnshostname ] [ 0 ] ,
578
- port : 445 ,
579
- proto : 'tcp' ,
580
- name : 'AD CS' ,
581
- info : "AD CS CA name: #{ ca_server [ :name ] [ 0 ] } "
582
- } )
583
-
584
- report_note ( {
585
- data : ca_server [ :dn ] [ 0 ] . to_s ,
586
- service : service ,
587
- host : ca_server [ :dnshostname ] [ 0 ] ,
588
- ntype : 'windows.ad.cs.ca.dn'
589
- } )
590
-
591
- report_host ( {
592
- host : ca_server [ :dnshostname ] [ 0 ] ,
593
- name : ca_server [ :dnshostname ] [ 0 ]
594
- } )
595
-
596
- ca_server_key = ca_server [ :dnshostname ] [ 0 ] . to_sym
577
+ ca_server_fqdn = ca_server [ :dnshostname ] [ 0 ] . to_s . downcase
578
+ ca_server_ip_address = get_ip_addresses_by_fqdn ( ca_server_fqdn ) &.first
579
+
580
+ if ca_server_ip_address
581
+ service = report_service ( {
582
+ host : ca_server_ip_address ,
583
+ port : 445 ,
584
+ proto : 'tcp' ,
585
+ name : 'AD CS' ,
586
+ info : "AD CS CA name: #{ ca_server [ :name ] [ 0 ] } "
587
+ } )
588
+
589
+ report_note ( {
590
+ data : ca_server [ :dn ] [ 0 ] . to_s ,
591
+ service : service ,
592
+ host : ca_server_ip_address ,
593
+ ntype : 'windows.ad.cs.ca.dn'
594
+ } )
595
+
596
+ report_host ( {
597
+ host : ca_server_ip_address ,
598
+ name : ca_server_fqdn
599
+ } )
600
+ end
601
+
602
+ ca_server_key = ca_server_fqdn . to_sym
597
603
next if @certificate_details [ certificate_template ] [ :ca_servers ] . key? ( ca_server_key )
598
604
599
605
@certificate_details [ certificate_template ] [ :ca_servers ] [ ca_server_key ] = {
600
- hostname : ca_server [ :dnshostname ] [ 0 ] . to_s ,
606
+ fqdn : ca_server_fqdn ,
607
+ ip_address : ca_server_ip_address ,
601
608
enrollment_sids : allowed_sids ,
602
609
name : ca_server [ :name ] [ 0 ] . to_s ,
603
610
dn : ca_server [ :dn ] [ 0 ] . to_s
@@ -644,17 +651,17 @@ def print_vulnerable_cert_info
644
651
info = hash [ :notes ] . select { |note | note . start_with? ( prefix ) } . map { |note | note . delete_prefix ( prefix ) . strip } . join ( "\n " )
645
652
info = nil if info . blank?
646
653
647
- hash [ :ca_servers ] . each do |dnshostname , ca_server |
654
+ hash [ :ca_servers ] . each do |ca_fqdn , ca_server |
648
655
service = report_service ( {
649
- host : dnshostname . to_s ,
656
+ host : ca_server [ :ip_address ] ,
650
657
port : 445 ,
651
658
proto : 'tcp' ,
652
659
name : 'AD CS' ,
653
660
info : "AD CS CA name: #{ ca_server [ :name ] } "
654
661
} )
655
662
656
663
vuln = report_vuln (
657
- host : dnshostname . to_s ,
664
+ host : ca_server [ :ip_address ] ,
658
665
port : 445 ,
659
666
proto : 'tcp' ,
660
667
sname : 'AD CS' ,
@@ -667,7 +674,7 @@ def print_vulnerable_cert_info
667
674
report_note ( {
668
675
data : hash [ :dn ] ,
669
676
service : service ,
670
- host : dnshostname . to_s ,
677
+ host : ca_fqdn . to_s ,
671
678
ntype : 'windows.ad.cs.ca.template.dn' ,
672
679
vuln_id : vuln . id
673
680
} )
@@ -702,8 +709,8 @@ def print_vulnerable_cert_info
702
709
end
703
710
704
711
if hash [ :ca_servers ] . any?
705
- hash [ :ca_servers ] . each do |ca_hostname , ca_hash |
706
- print_good ( " Issuing CA: #{ ca_hash [ :name ] } (#{ ca_hostname } )" )
712
+ hash [ :ca_servers ] . each do |ca_fqdn , ca_hash |
713
+ print_good ( " Issuing CA: #{ ca_hash [ :name ] } (#{ ca_fqdn } )" )
707
714
print_status ( ' Enrollment SIDs:' )
708
715
convert_sids_to_human_readable_name ( ca_hash [ :enrollment_sids ] ) . each do |sid |
709
716
print_status ( " * #{ highlight_sid ( sid ) } " )
@@ -769,10 +776,48 @@ def get_object_by_sid(object_sid)
769
776
object
770
777
end
771
778
779
+ def get_ip_addresses_by_fqdn ( host_fqdn )
780
+ return @fqdns [ host_fqdn ] if @fqdns . key? ( host_fqdn )
781
+
782
+ vprint_status ( "Looking up DNS records for #{ host_fqdn } in LDAP." )
783
+ hostname , _ , domain = host_fqdn . partition ( '.' )
784
+ results = query_ldap_server (
785
+ "(&(objectClass=dnsNode)(DC=#{ ldap_escape_filter ( hostname ) } ))" ,
786
+ %w[ dnsRecord ] ,
787
+ base_prefix : "DC=#{ ldap_escape_filter ( domain ) } ,CN=MicrosoftDNS,DC=DomainDnsZones"
788
+ )
789
+ return nil if results . blank?
790
+
791
+ ip_addresses = [ ]
792
+ results . first [ :dnsrecord ] . each do |packed |
793
+ begin
794
+ unpacked = MsDnspDnsRecord . read ( packed )
795
+ rescue ::EOFError
796
+ next
797
+ rescue ::IOError
798
+ next
799
+ end
800
+
801
+ next unless [ DnsRecordType ::DNS_TYPE_A , DnsRecordType ::DNS_TYPE_AAAA ] . include? ( unpacked . record_type )
802
+
803
+ ip_addresses << unpacked . data . to_s
804
+ end
805
+
806
+ @fqdns [ host_fqdn ] = ip_addresses
807
+ if ip_addresses . empty?
808
+ print_warning ( "No A or AAAA DNS records were found for #{ host_fqdn } in LDAP." )
809
+ else
810
+ vprint_status ( "Found #{ ip_addresses . length } IP address#{ ip_addresses . length > 1 ? 'es' : '' } via A and AAAA DNS records." )
811
+ end
812
+
813
+ ip_addresses
814
+ end
815
+
772
816
def run
773
817
# Define our instance variables real quick.
774
818
@base_dn = nil
775
819
@ldap_objects = [ ]
820
+ @fqdns = { }
776
821
@certificate_details = { } # Initialize to empty hash since we want to only keep one copy of each certificate template along with its details.
777
822
778
823
ldap_connect do |ldap |
0 commit comments