metasploit-framework icon indicating copy to clipboard operation
metasploit-framework copied to clipboard

Add in support for GUIDs, Certificate Handling, and SIDs to ldap_query Module

Open gwillcox-r7 opened this issue 3 years ago • 1 comments

Adds support for GUIDs, reading certificates and outputting their details, and handling SIDs to auxiliary/gather/ldap_query.rb. Also add in some time related element support.

Verification

  • [ ] Install ADCS on either a new or existing domain controller
    • [ ] Open the Server Manager
    • [ ] Select Add roles and features
    • [ ] Select "Active Directory Certificate Services" under the "Server Roles" section
    • [ ] When prompted add all of the features and management tools
    • [ ] On the AD CS "Role Services" tab, leave the default selection of only "Certificate Authority"
    • [ ] Completion the installation and reboot the server
    • [ ] Reopen the Server Manager
    • [ ] Go to the AD CS tab and where it says "Configuration Required", hit "More" then "Configure Active Directory Certificate..."
    • [ ] Select "Certificate Authority" in the Role Services tab
    • [ ] Keep all of the default settings, noting the value of the "Common name for this CA" on the "CA Name" tab (this value corresponds to the CA datastore option)
    • [ ] Accept the rest of the default settings and complete the configuration
  • [ ] Add a new entry to the ldap_queries_default.yaml with the following content (overwrite any existing entries with same name):
  - action: ENUM_ADCS_CAS
    description: 'Enumerate ADCS certificate authorities.'
    base_dn_prefix: 'CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration'
    filter: '(objectClass=pKIEnrollmentService)'
    attributes:
      - cn
      - name
      - cACertificateDN
      - dNSHostname
      - certificateTemplates
      - objectGUID
      - caCertificate
  • [ ] Start msfconsole
  • [ ] use auxiliary/gather/ldap_query
  • [ ] set RHOSTS <target IP>
  • [ ] set ACTION ENUM_ADCS_CAS
  • [ ] set BIND_DN <DOMAIN>\\<USERNAME>
  • [ ] set BIND_PW <PASSWORD>
  • [ ] run
  • [ ] Verify that the cacertificate field looks similar to the following and is no longer a binary blob of data:
 cacertificate         Version: 0x2, Subject: /DC=com/DC=daforest/CN=daforest-WIN-BR0CCBA
                       815B-CA, Issuer: /DC=com/DC=daforest/CN=daforest-WIN-BR0CCBA815B-C
                       A, Signature Algorithm: sha256WithRSAEncryption, Extensions: keyUs
                       age = Digital Signature, Certificate Sign, CRL Sign | basicConstra
                       ints = critical, CA:TRUE | subjectKeyIdentifier = DD:1C:7F:D8:EE:F
                       9:A8:D0:AA:6E:AC:55:61:E0:70:AC:45:03:70:6C | 1.3.6.1.4.1.311.21.1
                        = ...
  • [ ] Verify that the objectguid field is now decoded into a valid GUID. You can verify if the GUID is valid by opening up a Active Directory Module for Powershell prompt and typing in get-adobject -id <OBJECT GUID> and if its valid you should see some output like the following, instead of an object not found error:
PS C:\Users\Administrator> get-adobject -id "87564274-339B-4CFB-8686-8CBE2F4AB035"

DistinguishedName                                          Name    ObjectClass              ObjectGUID
-----------------                                          ----    -----------              ----------
CN=S-1-5-4,CN=ForeignSecurityPrincipals,DC=daforest,DC=com S-1-5-4 foreignSecurityPrincipal 87564274-339b-4cfb-8686-8cbe2f4ab035


PS C:\Users\Administrator>
  • [ ] Finally modify ldap_queries_default.yaml and include the following:
  - action: ENUM_SID
    description: 'Enumerate SIDs.'
    filter: '(objectSID=*)'
    attributes:
      - cn
      - name
      - objectSID
  • [ ] reload
  • [ ] set ACTION ENUM_SID
  • [ ] run
  • Verify you now see output similar to the following with the objectSID field properly decoded into an SID instead of being a binary blob.
CN=DnsUpdateProxy CN=Users DC=daforest DC=com
=============================================

 Name       Attributes
 ----       ----------
 cn         DnsUpdateProxy
 name       DnsUpdateProxy
 objectsid  S-1-5-21-3290009963-1772292745-3260174523-1102
  • [ ] Update the ldap_queries_default.yaml file and add the follow entry:
  - action: ENUM_TIME_ELEMENTS
    description: 'Enumerate time elements'
    filter: '(CreationTime=*)'
    attributes:
      - cn
      - name
      - creationTime
      - lockoutDuration
      - maxPwdAge
      - minPwdAge
      - systemFlags
  • [ ] reload
  • [ ] set ACTION ENUM_TIME_ELEMENTS
  • [ ] run
  • [ ] Verify that you get decoded maxPwdAge, minPwdAge elements, that lockoutDuration is a time string and not an integer anymore, and that systemFlags is decoded into a string and isn't a negative integer anymore.
msf6 auxiliary(gather/ldap_query) > run
[*] Running module against 172.22.163.183

[+] Successfully bound to the LDAP server!
[*] Discovering base DN automatically
[+] 172.22.163.183:389 Discovered base DN: DC=daforest,DC=com
DC=daforest DC=com
==================

 Name             Attributes
 ----             ----------
 creationtime     2022-09-01 19:37:37 UTC
 lockoutduration  0:00:30:00
 maxpwdage        42:00:00:00
 minpwdage        1:00:00:00
 name             daforest
 systemflags      FLAG_DISALLOW_DELETE | FLAG_DOMAIN_DISALLOW_RENAME | FLAG_DOMAIN_DISALLOW_MOVE

CN=Builtin DC=daforest DC=com
=============================

 Name             Attributes
 ----             ----------
 cn               Builtin
 creationtime     2022-08-18 17:48:12 UTC
 lockoutduration  0:00:30:00
 maxpwdage        42:22:47:31
 minpwdage        0:00:00:00
 name             Builtin
 systemflags      FLAG_DISALLOW_DELETE | FLAG_DOMAIN_DISALLOW_RENAME | FLAG_DOMAIN_DISALLOW_MOVE

[*] Auxiliary module execution completed
msf6 auxiliary(gather/ldap_query) > 

gwillcox-r7 avatar Sep 02 '22 21:09 gwillcox-r7

The code all looks reasonable to me. I ran through all the proposed test cases and everything worked as intended :+1: .

The only concern I have is the logic associating the types with the decoders. From the screenshot @adfoster-r7 posted, it looks like other tools are applying similar decoding logic to the binary strings returned by ldap. I know we want to optimize for the most common use case of Active Directory but it seems worth mentioning that a schema could feasibly exist where for example the objectsid is not in the expected format. I think at a minimum we'd want to have exception handling (or basic checks like lenght) that falls back to printing the escaped binary string when the decoding logic fails.

smcintyre-r7 avatar Sep 07 '22 20:09 smcintyre-r7

@msjenkins-r7 test this please.

smcintyre-r7 avatar Oct 26 '22 15:10 smcintyre-r7

Release Notes

This improves the existing ldap_query module by allowing it to decode some data types into a human readable format.

smcintyre-r7 avatar Oct 26 '22 17:10 smcintyre-r7