ly4k / Certipy

Tool for Active Directory Certificate Services enumeration and abuse
MIT License
2.23k stars 302 forks source link

Enable Find in Multidomain Environments #151

Open brettgus opened 1 year ago

brettgus commented 1 year ago

I'm working in a multi-domain environment. I'm trying to enumerate ADCS in a foreign domain that has trusts. In my situation, it seems that certipy is able to enumerate the CA in the foreign domain, but then it tries to look up if the templates are vulnerable in the context of my user, and that is when it fails. It would be nice to be able to specify the user you'd like to check against instead (so you could specify a user in that domain.

certipy find -u 'DUMMYUSER@client.com' -p 'REDACTEDPASSWORD' -dc-ip 172.16.2.2 -debug -stdout -debug
Certipy v4.5.1 - by Oliver Lyak (ly4k)

[+] Authenticating to LDAP server
[+] Bound to ldaps://172.16.2.2:636 - ssl
[+] Default path: DC=Foreigndomain,DC=Corp
[+] Configuration path: CN=Configuration,DC=Foreigndomain,DC=Corp
[*] Finding certificate templates
[*] Found 80 certificate templates
[*] Finding certificate authorities
[*] Found 2 certificate authorities
[*] Found 57 enabled certificate templates
[+] Trying to resolve 'PKICA02.Foreigndomain.Corp' at '172.16.2.2'
[*] Trying to get CA configuration for 'Foreigndomain-PKICA02-CA' via CSRA
[+] Trying to get DCOM connection for: 192.168.2.86
[!] Got error while trying to get CA configuration for 'Foreigndomain-PKICA02-CA' via CSRA: CASessionError: code: 0x80070005 - E_ACCESSDENIED - General access denied error.
[*] Trying to get CA configuration for 'Foreigndomain-PKICA02-CA' via RRP
[!] Failed to connect to remote registry. Service should be starting now. Trying again...
[+] Connected to remote registry at 'PKICA02.Foreigndomain.Corp' (192.168.2.86)
[*] Got CA configuration for 'Foreigndomain-PKICA02-CA'
[+] Resolved 'PKICA02.Foreigndomain.Corp' from cache: 192.168.2.86
[+] Connecting to 192.168.2.86:80
[+] Trying to resolve 'PKICA01.Foreigndomain.Corp' at '172.16.2.2'
[*] Trying to get CA configuration for 'foreign' via CSRA
[+] Trying to get DCOM connection for: 192.168.2.85
[!] Got error while trying to get CA configuration for 'foreign' via CSRA: CASessionError: code: 0x80070005 - E_ACCESSDENIED - General access denied error.
[*] Trying to get CA configuration for 'foreign' via RRP
[+] Connected to remote registry at 'PKICA01.Foreigndomain.Corp' (192.168.2.85)
[*] Got CA configuration for 'foreign'
[+] Resolved 'PKICA01.Foreigndomain.Corp' from cache: 192.168.2.85
[+] Connecting to 192.168.2.85:80
[-] Could not find user 'DUMMYUSER'
[-] Got error: 'NoneType' object has no attribute 'get'
Traceback (most recent call last):
  File "/home/kali/.pyenv/versions/3.10.9/lib/python3.10/site-packages/certipy/entry.py", line 60, in main
    actions[options.action](options)
  File "/home/kali/.pyenv/versions/3.10.9/lib/python3.10/site-packages/certipy/commands/parsers/find.py", line 12, in entry
    find.entry(options)
  File "/home/kali/.pyenv/versions/3.10.9/lib/python3.10/site-packages/certipy/commands/find.py", line 1185, in entry
    find.find()
  File "/home/kali/.pyenv/versions/3.10.9/lib/python3.10/site-packages/certipy/commands/find.py", line 458, in find
    output = self.get_output_for_text_and_json(templates, cas)
  File "/home/kali/.pyenv/versions/3.10.9/lib/python3.10/site-packages/certipy/commands/find.py", line 489, in get_output_for_text_and_json
    vulnerabilities = self.get_template_vulnerabilities(template)
  File "/home/kali/.pyenv/versions/3.10.9/lib/python3.10/site-packages/certipy/commands/find.py", line 934, in get_template_vulnerabilities
    user_can_enroll, enrollable_sids = self.can_user_enroll_in_template(template)
  File "/home/kali/.pyenv/versions/3.10.9/lib/python3.10/site-packages/certipy/commands/find.py", line 1027, in can_user_enroll_in_template
    if sid not in self.connection.get_user_sids(self.target.username):
  File "/home/kali/.pyenv/versions/3.10.9/lib/python3.10/site-packages/certipy/lib/ldap.py", line 347, in get_user_sids
    sids.add(user.get("objectSid"))
AttributeError: 'NoneType' object has no attribute 'get'
jgoosey commented 2 months ago

Temporary workaround I just tested on "find", it at least outputs to txt and json and as far as I see no issue on enumeration:

certipy/lib/ldap.py (lines 363 - 383)

        #sids.add(user.get("objectSid"))

        # Everyone, Authenticated Users, Users
        sids |= set(["S-1-1-0", "S-1-5-11", "S-1-5-32-545"])

        # Domain Users, Domain Computers, etc.
        #primary_group_id = user.get("primaryGroupID")
        primary_group_id = None
        if primary_group_id is not None:
            sids.add("%s-%d" % (self.domain_sid, primary_group_id))

        # Add Domain Computers group
        logging.debug(
            "Adding Domain Computers to list of current user's SIDs"
        )
        sids.add("%s-515" % self.domain_sid)

        #dns = [user.get("distinguishedName")]
         dns = []
         for sid in sids:
            object = self.lookup_sid(sid)
            if "dn" in object:
                dns.append(object["dn"])

Update: FWIW, I exploited ESC4 and ESC1 of a trusted domain with these changes to ldap.py and didn't have an issue