From 2819565f8da3d0560b73f8b8f7f91f2106a7c99d Mon Sep 17 00:00:00 2001 From: Lars Karlslund Date: Tue, 17 Aug 2021 19:50:45 +0200 Subject: [PATCH] Fixed some problems with the new DENY logic. Fixed disaplaying of permissions on graph edges. --- acl.go | 13 +++++++++++-- html/custom.js | 8 ++++---- pwn.go | 5 ++--- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/acl.go b/acl.go index d0e89b5..f6bbf0a 100644 --- a/acl.go +++ b/acl.go @@ -214,8 +214,17 @@ func (a ACL) AllowObjectClass(index int, o *Object, mask uint32, g uuid.UUID) bo if a.Entries[index].checkObjectClass(true, o, mask, g) { // See if a prior one denies it for i := 0; i < index; i++ { - if a.Entries[i].checkObjectClass(false, o, mask, g) { - return false // yes, strange, but if a deny matches then you're not allowed + if a.Entries[i].checkObjectClass(false, o, mask, g) && a.Entries[index].SID == a.Entries[i].SID { + if g == NullGUID && a.Entries[i].ObjectType != NullGUID { + // We tested for all properties / extended rights, but the DENY blocks some of these + log.Debug().Msgf("ACL allow/deny detection: %v denies that %v allows", a.Entries[i].String(), a.Entries[index].String()) + return false + } + if a.Entries[i].ObjectType != NullGUID && a.Entries[i].ObjectType == g { + // The DENY is specific to attributes / extended rights etc. so it only blocks if the requested is the same + log.Debug().Msgf("ACL allow/deny detection: %v denies that %v allows", a.Entries[i].String(), a.Entries[index].String()) + return false + } } } return true // No deny match diff --git a/html/custom.js b/html/custom.js index 1a2b455..8923beb 100644 --- a/html/custom.js +++ b/html/custom.js @@ -582,14 +582,14 @@ $(function() { } function renderedge(ele) { - return rendernode(ele.source()) + rendermethods(ele.data()) + rendernode(ele.target()); + return rendernode(ele.source()) + rendermethods(ele) + rendernode(ele.target()); } function rendermethods(methods) { s = "" - for (i in methods) { + for (i in methods.data()) { if (i.startsWith("method_")) { - s += '' + i.substr(7) + ''; + s += '' + i.substr(7) + ''; } } return s @@ -660,7 +660,7 @@ $(function() { if (ele.isNode()) { $("#route").append(rendernode(ele)); } else if (ele.isEdge()) { - $("#route").append(rendermethods(ele.data("methods"))); + $("#route").append(rendermethods(ele)); } }) } else { diff --git a/pwn.go b/pwn.go index 5114285..013dc82 100644 --- a/pwn.go +++ b/pwn.go @@ -48,7 +48,6 @@ var ( AttributeMember = uuid.UUID{0xbf, 0x96, 0x79, 0xc0, 0x0d, 0xe6, 0x11, 0xd0, 0xa2, 0x85, 0x00, 0xaa, 0x00, 0x30, 0x49, 0xe2} AttributeSetGroupMembership = uuid.UUID{0xBC, 0x0A, 0xC2, 0x40, 0x79, 0xA9, 0x11, 0xD0, 0x90, 0x20, 0x00, 0xC0, 0x4F, 0xC2, 0xD4, 0xCF} AttributeSIDHistory = uuid.UUID{0x17, 0xeb, 0x42, 0x78, 0xd1, 0x67, 0x11, 0xd0, 0xb0, 0x02, 0x00, 0x00, 0xf8, 0x03, 0x67, 0xc1} - AttributeSPN = uuid.UUID{0xf3, 0xa6, 0x47, 0x88, 0x53, 0x06, 0x11, 0xd1, 0xa9, 0xc5, 0x00, 0x00, 0xf8, 0x03, 0x67, 0xc1} AttributeAllowedToActOnBehalfOfOtherIdentity, _ = uuid.FromString("{3F78C3E5-F79A-46BD-A0B8-9D18116DDC79}") AttributeMSDSGroupMSAMembership = uuid.UUID{0x88, 0x8e, 0xed, 0xd6, 0xce, 0x04, 0xdf, 0x40, 0xb4, 0x62, 0xb8, 0xa5, 0x0e, 0x41, 0xba, 0x38} AttributeGPLink, _ = uuid.FromString("{F30E3BBE-9FF0-11D1-B603-0000F80367C1}") @@ -662,7 +661,7 @@ var PwnAnalyzers = []PwnAnalyzer{ }, }, { - Method: PwnWriteSPN, + Method: PwnWriteSPN, // Same GUID as Validated writes, just a different permission (?) ObjectAnalyzer: func(o *Object) []*Object { var results []*Object // Only computers and users @@ -674,7 +673,7 @@ var PwnAnalyzers = []PwnAnalyzer{ return results } for index, acl := range sd.DACL.Entries { - if sd.DACL.AllowObjectClass(index, o, RIGHT_DS_WRITE_PROPERTY, AttributeSPN) { + if sd.DACL.AllowObjectClass(index, o, RIGHT_DS_WRITE_PROPERTY, ValidateWriteSPN) { results = append(results, AllObjects.FindOrAddSID(acl.SID)) } }