From 2c03c386ad18e7725c5b213c45a55a4895d8caa2 Mon Sep 17 00:00:00 2001 From: Bryan De Houwer Date: Fri, 27 Oct 2023 00:19:05 +0200 Subject: [PATCH 1/2] Fix bug in extended rights parsing --- certipy/lib/constants.py | 1 + certipy/lib/security.py | 23 ++++++++++++++--------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/certipy/lib/constants.py b/certipy/lib/constants.py index 1b6d13e..4880e46 100755 --- a/certipy/lib/constants.py +++ b/certipy/lib/constants.py @@ -252,6 +252,7 @@ class CERTIFICATE_RIGHTS(IntFlag): GENERIC_ALL = 983551 WRITE_OWNER = 524288 WRITE_DACL = 262144 + EXTENDED_RIGHT = 256 WRITE_PROPERTY = 32 def to_list(self): diff --git a/certipy/lib/security.py b/certipy/lib/security.py index cf2044d..af2270b 100755 --- a/certipy/lib/security.py +++ b/certipy/lib/security.py @@ -10,6 +10,7 @@ ACTIVE_DIRECTORY_RIGHTS, CERTIFICATE_RIGHTS, CERTIFICATION_AUTHORITY_RIGHTS, + EXTENDED_RIGHTS_NAME_MAP, ) @@ -38,18 +39,22 @@ def __init__( "inherited": ace["AceFlags"] & INHERITED_ACE == INHERITED_ACE, } + mask = self.RIGHTS_TYPE(ace["Ace"]["Mask"]["Mask"]) if ace["AceType"] == ldaptypes.ACCESS_ALLOWED_ACE.ACE_TYPE: - self.aces[sid]["rights"] |= self.RIGHTS_TYPE(ace["Ace"]["Mask"]["Mask"]) + self.aces[sid]["rights"] |= mask + if self.RIGHTS_TYPE.EXTENDED_RIGHT & mask: + self.aces[sid]["extended_rights"].append(EXTENDED_RIGHTS_NAME_MAP["All-Extended-Rights"]) if ace["AceType"] == ldaptypes.ACCESS_ALLOWED_OBJECT_ACE.ACE_TYPE: - if ace["Ace"]["Flags"] == 2: - uuid = bin_to_string(ace["Ace"]["InheritedObjectType"]).lower() - elif ace["Ace"]["Flags"] == 1: - uuid = bin_to_string(ace["Ace"]["ObjectType"]).lower() - else: - continue - - self.aces[sid]["extended_rights"].append(uuid) + if self.RIGHTS_TYPE.EXTENDED_RIGHT & mask: + if ace["Ace"]["Flags"] == 2: + uuid = bin_to_string(ace["Ace"]["InheritedObjectType"]).lower() + elif ace["Ace"]["Flags"] == 1: + uuid = bin_to_string(ace["Ace"]["ObjectType"]).lower() + else: + continue + + self.aces[sid]["extended_rights"].append(uuid) class CASecurity(ActiveDirectorySecurity): From 118d9263afe80ffae30afaa03499cd3301f513cd Mon Sep 17 00:00:00 2001 From: Bryan De Houwer Date: Wed, 24 Jul 2024 08:27:12 +0200 Subject: [PATCH 2/2] Fix CASecurity rights parsing --- certipy/lib/security.py | 47 ++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/certipy/lib/security.py b/certipy/lib/security.py index af2270b..800ae96 100755 --- a/certipy/lib/security.py +++ b/certipy/lib/security.py @@ -42,27 +42,50 @@ def __init__( mask = self.RIGHTS_TYPE(ace["Ace"]["Mask"]["Mask"]) if ace["AceType"] == ldaptypes.ACCESS_ALLOWED_ACE.ACE_TYPE: self.aces[sid]["rights"] |= mask + if self.RIGHTS_TYPE.EXTENDED_RIGHT & mask: self.aces[sid]["extended_rights"].append(EXTENDED_RIGHTS_NAME_MAP["All-Extended-Rights"]) - if ace["AceType"] == ldaptypes.ACCESS_ALLOWED_OBJECT_ACE.ACE_TYPE: - if self.RIGHTS_TYPE.EXTENDED_RIGHT & mask: - if ace["Ace"]["Flags"] == 2: - uuid = bin_to_string(ace["Ace"]["InheritedObjectType"]).lower() - elif ace["Ace"]["Flags"] == 1: - uuid = bin_to_string(ace["Ace"]["ObjectType"]).lower() - else: - continue + if ace["AceType"] == ldaptypes.ACCESS_ALLOWED_OBJECT_ACE.ACE_TYPE and \ + self.RIGHTS_TYPE.EXTENDED_RIGHT & mask and \ + ace['Ace'].hasFlag(ldaptypes.ACCESS_ALLOWED_OBJECT_ACE.ACE_OBJECT_TYPE_PRESENT): + + uuid = bin_to_string(ace["Ace"]["ObjectType"]).lower() + self.aces[sid]["extended_rights"].append(uuid) + - self.aces[sid]["extended_rights"].append(uuid) +class CertifcateSecurity(ActiveDirectorySecurity): + RIGHTS_TYPE = CERTIFICATE_RIGHTS -class CASecurity(ActiveDirectorySecurity): +class CASecurity: RIGHTS_TYPE = CERTIFICATION_AUTHORITY_RIGHTS + def __init__( + self, + security_descriptor: bytes, + ): + sd = ldaptypes.SR_SECURITY_DESCRIPTOR() + sd.fromString(security_descriptor) + self.sd = sd -class CertifcateSecurity(ActiveDirectorySecurity): - RIGHTS_TYPE = CERTIFICATE_RIGHTS + self.owner = format_sid(sd["OwnerSid"].getData()) + self.aces = {} + + aces = sd["Dacl"]["Data"] + for ace in aces: + sid = format_sid(ace["Ace"]["Sid"].getData()) + + if sid not in self.aces: + self.aces[sid] = { + "rights": self.RIGHTS_TYPE(0), + "extended_rights": [], + "inherited": ace["AceFlags"] & INHERITED_ACE == INHERITED_ACE, + } + + mask = self.RIGHTS_TYPE(ace["Ace"]["Mask"]["Mask"]) + if ace["AceType"] == ldaptypes.ACCESS_ALLOWED_ACE.ACE_TYPE: + self.aces[sid]["rights"] |= mask def is_admin_sid(sid: str):