Skip to content

Commit

Permalink
Fix for swapping the wrong UUID, added AutoEnroll permission and Vood…
Browse files Browse the repository at this point in the history
…ooBit detector
  • Loading branch information
lkarlslund committed Oct 6, 2022
1 parent ee4760f commit 3cb3855
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 30 deletions.
56 changes: 33 additions & 23 deletions modules/engine/securitydescriptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,15 +174,15 @@ func ParseACLentry(odata []byte) (ACE, []byte, error) {
if err != nil {
return ace, data, err
}
ace.InheritedObjectType = util.SwapUUIDEndianess(ace.InheritedObjectType)
ace.ObjectType = util.SwapUUIDEndianess(ace.ObjectType)
data = data[16:]
}
if ace.Flags&INHERITED_OBJECT_TYPE_PRESENT != 0 {
ace.InheritedObjectType, err = uuid.FromBytes(data[0:16])
if err != nil {
return ace, data, err
}
ace.ObjectType = util.SwapUUIDEndianess(ace.ObjectType)
ace.InheritedObjectType = util.SwapUUIDEndianess(ace.InheritedObjectType)
data = data[16:]
}
}
Expand All @@ -194,6 +194,9 @@ func ParseACLentry(odata []byte) (ACE, []byte, error) {
return ace, odata[acesize:], nil
}

var ExtendedRightCertificateEnroll, _ = uuid.FromString("0e10c968-78fb-11d2-90d4-00c04f79dc55")
var ExtendedRightCertificateAutoEnroll, _ = uuid.FromString("a05b8cc2-17bc-4802-a710-e7c15ab866a2")

func (a ACL) IsObjectClassAccessAllowed(index int, testObject *Object, mask Mask, guid uuid.UUID, ao *Objects) bool {
if a.Entries[index].Type == ACETYPE_ACCESS_DENIED || a.Entries[index].Type == ACETYPE_ACCESS_DENIED_OBJECT {
return false
Expand Down Expand Up @@ -269,6 +272,9 @@ func (a ACE) matchObjectClassAndGUID(o *Object, requestedAccess Mask, g uuid.UUI
// This ACE only applies to some kinds of attributes / extended rights?
if !a.ObjectType.IsNil() {
typematch := a.ObjectType == g
if typematch && requestedAccess == RIGHT_DS_CONTROL_ACCESS {
typematch = true
}
if !typematch {
// Lets chack if this requested guid is part of a group which is allowed
cachedset, found := objectSecurityGUIDcache.Load(g)
Expand Down Expand Up @@ -341,7 +347,7 @@ func (a ACE) String(ao *Objects) string {

if a.Flags&OBJECT_TYPE_PRESENT != 0 {
// ui.Debug().Msgf("Looking for right %v", a.ObjectType)
result += "OBJECT_TYPE_PRESENT "
result += " OBJECT_TYPE_PRESENT"
av := AttributeValueGUID(a.ObjectType)
if ao != nil {
if o, found := ao.Find(RightsGUID, av); found {
Expand Down Expand Up @@ -382,65 +388,69 @@ func (a ACE) String(ao *Objects) string {
result += fmt.Sprintf("MASK %08x", a.Mask)

var rights []string
if a.Mask&RIGHT_GENERIC_READ != 0 {
if a.Mask&RIGHT_GENERIC_READ == RIGHT_GENERIC_READ {
rights = append(rights, "GENERIC_READ")
}
if a.Mask&RIGHT_GENERIC_WRITE != 0 {
if a.Mask&RIGHT_GENERIC_WRITE == RIGHT_GENERIC_WRITE {
rights = append(rights, "GENERIC_WRITE")
}
if a.Mask&RIGHT_GENERIC_EXECUTE != 0 {
if a.Mask&RIGHT_GENERIC_EXECUTE == RIGHT_GENERIC_EXECUTE {
rights = append(rights, "GENERIC_EXECUTE")
}
if a.Mask&RIGHT_GENERIC_ALL != 0 {
if a.Mask&RIGHT_GENERIC_ALL == RIGHT_GENERIC_ALL {
rights = append(rights, "GENERIC_ALL")
}
if a.Mask&RIGHT_MAXIMUM_ALLOWED != 0 {
if a.Mask&RIGHT_MAXIMUM_ALLOWED == RIGHT_MAXIMUM_ALLOWED {
rights = append(rights, "MAXIMUM_ALLOWED")
}
if a.Mask&RIGHT_ACCESS_SYSTEM_SECURITY != 0 {
if a.Mask&RIGHT_ACCESS_SYSTEM_SECURITY == RIGHT_ACCESS_SYSTEM_SECURITY {
rights = append(rights, "ACCESS_SYSTEM_SECURITY")
}
if a.Mask&RIGHT_SYNCRONIZE != 0 {
if a.Mask&RIGHT_SYNCRONIZE == RIGHT_SYNCRONIZE {
rights = append(rights, "SYNCRONIZE")
}
if a.Mask&RIGHT_WRITE_OWNER != 0 {
if a.Mask&RIGHT_WRITE_OWNER == RIGHT_WRITE_OWNER {
rights = append(rights, "WRITE_OWNER")
}
if a.Mask&RIGHT_WRITE_DACL != 0 {
if a.Mask&RIGHT_WRITE_DACL == RIGHT_WRITE_DACL {
rights = append(rights, "WRITE_DACL")
}
if a.Mask&RIGHT_READ_CONTROL != 0 {
if a.Mask&RIGHT_READ_CONTROL == RIGHT_READ_CONTROL {
rights = append(rights, "READ_CONTROL")
}
if a.Mask&RIGHT_DELETE != 0 {
if a.Mask&RIGHT_DELETE == RIGHT_DELETE {
rights = append(rights, "DELETE")
}
if a.Mask&RIGHT_DS_CONTROL_ACCESS != 0 {
if a.Mask&RIGHT_DS_CONTROL_ACCESS == RIGHT_DS_CONTROL_ACCESS {
rights = append(rights, "DS_CONTROL_ACCESS")
}

if a.Mask&RIGHT_DS_LIST_OBJECT != 0 {
if a.Mask&RIGHT_DS_VOODOO_BIT == RIGHT_DS_VOODOO_BIT {
rights = append(rights, "DS_VOODOO_BIT")
}

if a.Mask&RIGHT_DS_LIST_OBJECT == RIGHT_DS_LIST_OBJECT {
rights = append(rights, "DS_LIST_OBJECT")
}
if a.Mask&RIGHT_DS_DELETE_TREE != 0 {
if a.Mask&RIGHT_DS_DELETE_TREE == RIGHT_DS_DELETE_TREE {
rights = append(rights, "DS_DELETE_TREE")
}
if a.Mask&RIGHT_DS_WRITE_PROPERTY != 0 {
if a.Mask&RIGHT_DS_WRITE_PROPERTY == RIGHT_DS_WRITE_PROPERTY {
rights = append(rights, "DS_WRITE_PROPERTY")
}
if a.Mask&RIGHT_DS_READ_PROPERTY != 0 {
if a.Mask&RIGHT_DS_READ_PROPERTY == RIGHT_DS_READ_PROPERTY {
rights = append(rights, "DS_READ_PROPERTY")
}
if a.Mask&RIGHT_DS_WRITE_PROPERTY_EXTENDED != 0 {
if a.Mask&RIGHT_DS_WRITE_PROPERTY_EXTENDED == RIGHT_DS_WRITE_PROPERTY_EXTENDED {
rights = append(rights, "DS_WRITE_PROPERTY_EXTENDED")
}
if a.Mask&RIGHT_DS_LIST_CONTENTS != 0 {
if a.Mask&RIGHT_DS_LIST_CONTENTS == RIGHT_DS_LIST_CONTENTS {
rights = append(rights, "DS_LIST_CONTENTS")
}
if a.Mask&RIGHT_DS_DELETE_CHILD != 0 {
if a.Mask&RIGHT_DS_DELETE_CHILD == RIGHT_DS_DELETE_CHILD {
rights = append(rights, "DS_DELETE_CHILD")
}
if a.Mask&RIGHT_DS_CREATE_CHILD != 0 {
if a.Mask&RIGHT_DS_CREATE_CHILD == RIGHT_DS_CREATE_CHILD {
rights = append(rights, "DS_CREATE_CHILD")
}
result += " " + strings.Join(rights, " | ")
Expand Down
48 changes: 42 additions & 6 deletions modules/integrations/activedirectory/analyze/analyze-ad.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (

// Interesting permissions on AD
var (
ResetPwd = uuid.UUID{0x00, 0x29, 0x95, 0x70, 0x24, 0x6d, 0x11, 0xd0, 0xa7, 0x68, 0x00, 0xaa, 0x00, 0x6e, 0x05, 0x29}
ResetPwd, _ = uuid.FromString("{00299570-246d-11d0-a768-00aa006e0529}")
DSReplicationGetChanges = uuid.UUID{0x11, 0x31, 0xf6, 0xaa, 0x9c, 0x07, 0x11, 0xd1, 0xf7, 0x9f, 0x00, 0xc0, 0x4f, 0xc2, 0xdc, 0xd2}
DSReplicationGetChangesAll = uuid.UUID{0x11, 0x31, 0xf6, 0xad, 0x9c, 0x07, 0x11, 0xd1, 0xf7, 0x9f, 0x00, 0xc0, 0x4f, 0xc2, 0xdc, 0xd2}
DSReplicationSyncronize = uuid.UUID{0x11, 0x31, 0xf6, 0xab, 0x9c, 0x07, 0x11, 0xd1, 0xf7, 0x9f, 0x00, 0xc0, 0x4f, 0xc2, 0xdc, 0xd2}
Expand All @@ -33,12 +33,13 @@ var (
AttributeAltSecurityIdentitiesGUID, _ = uuid.FromString("{00FBF30C-91FE-11D1-AEBC-0000F80367C1}")
AttributeProfilePathGUID, _ = uuid.FromString("{bf967a05-0de6-11d0-a285-00aa003049e2}")
AttributeScriptPathGUID, _ = uuid.FromString("{bf9679a8-0de6-11d0-a285-00aa003049e2}")
AttributeMSDSManagedPasswordId, _ = uuid.FromString("0e78295a-c6d3-0a40-b491-d62251ffa0a6")
AttributeMSDSManagedPasswordId, _ = uuid.FromString("{0e78295a-c6d3-0a40-b491-d62251ffa0a6}")

ExtendedRightCertificateEnroll, _ = uuid.FromString("0e10c968-78fb-11d2-90d4-00c04f79dc55")
ExtendedRightCertificateEnroll, _ = uuid.FromString("{0e10c968-78fb-11d2-90d4-00c04f79dc55}")
ExtendedRightCertificateAutoEnroll, _ = uuid.FromString("{a05b8cc2-17bc-4802-a710-e7c15ab866a2}")

ValidateWriteSelfMembership, _ = uuid.FromString("bf9679c0-0de6-11d0-a285-00aa003049e2")
ValidateWriteSPN, _ = uuid.FromString("f3a64788-5306-11d1-a9c5-0000f80367c1")
ValidateWriteSelfMembership, _ = uuid.FromString("{bf9679c0-0de6-11d0-a285-00aa003049e2}")
ValidateWriteSPN, _ = uuid.FromString("{f3a64788-5306-11d1-a9c5-0000f80367c1}")

ObjectGuidUser = uuid.UUID{0xbf, 0x96, 0x7a, 0xba, 0x0d, 0xe6, 0x11, 0xd0, 0xa2, 0x85, 0x00, 0xaa, 0x00, 0x30, 0x49, 0xe2}
ObjectGuidComputer = uuid.UUID{0xbf, 0x96, 0x7a, 0x86, 0x0d, 0xe6, 0x11, 0xd0, 0xa2, 0x85, 0x00, 0xaa, 0x00, 0x30, 0x49, 0xe2}
Expand Down Expand Up @@ -676,13 +677,48 @@ func init() {
continue
}
for index, acl := range sd.DACL.Entries {
if sd.DACL.IsObjectClassAccessAllowed(index, o, engine.RIGHT_DS_CONTROL_ACCESS, ExtendedRightCertificateEnroll, ao) {
// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-crtd/211ab1e3-bad6-416d-9d56-8480b42617a4
if sd.DACL.IsObjectClassAccessAllowed(index, o, engine.RIGHT_DS_CONTROL_ACCESS, ExtendedRightCertificateEnroll, ao) ||
sd.DACL.IsObjectClassAccessAllowed(index, o, engine.RIGHT_DS_VOODOO_BIT, uuid.Nil, ao) {
ao.FindOrAddAdjacentSID(acl.SID, o).EdgeTo(o, activedirectory.EdgeCertificateEnroll)
}
}
}
}, "Permission to enroll into a certificate template", engine.BeforeMergeFinal)

Loader.AddProcessor(func(ao *engine.Objects) {
for _, o := range ao.Slice() {
if o.Type() != engine.ObjectTypeCertificateTemplate {
continue
}
sd, err := o.SecurityDescriptor()
if err != nil {
continue
}
for index, acl := range sd.DACL.Entries {
// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-crtd/211ab1e3-bad6-416d-9d56-8480b42617a4
if sd.DACL.IsObjectClassAccessAllowed(index, o, engine.RIGHT_DS_CONTROL_ACCESS, ExtendedRightCertificateAutoEnroll, ao) ||
sd.DACL.IsObjectClassAccessAllowed(index, o, engine.RIGHT_DS_VOODOO_BIT, uuid.Nil, ao) {
ao.FindOrAddAdjacentSID(acl.SID, o).EdgeTo(o, activedirectory.EdgeCertificateAutoEnroll)
}
}
}
}, "Permission to auto-enroll into a certificate template", engine.BeforeMergeFinal)

Loader.AddProcessor(func(ao *engine.Objects) {
for _, o := range ao.Slice() {
sd, err := o.SecurityDescriptor()
if err != nil {
continue
}
for index, acl := range sd.DACL.Entries {
if sd.DACL.IsObjectClassAccessAllowed(index, o, engine.RIGHT_DS_VOODOO_BIT, uuid.Nil, ao) {
ao.FindOrAddAdjacentSID(acl.SID, o).EdgeTo(o, activedirectory.EdgeVoodooBit)
}
}
}
}, "Has the Voodoo Bit set", engine.BeforeMergeFinal)

Loader.AddProcessor(func(ao *engine.Objects) {
for _, o := range ao.Slice() {
if o.Type() != engine.ObjectTypeDomainDNS {
Expand Down
4 changes: 3 additions & 1 deletion modules/integrations/activedirectory/pwns.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ var (
EdgeGenericAll = engine.NewEdge("GenericAll")
EdgeWriteAll = engine.NewEdge("WriteAll")
EdgeWritePropertyAll = engine.NewEdge("WritePropertyAll")
EdgeWriteExtendedAll = engine.NewEdge("ExtendedAll")
EdgeWriteExtendedAll = engine.NewEdge("WriteExtendedAll")
EdgeTakeOwnership = engine.NewEdge("TakeOwnership")
EdgeWriteDACL = engine.NewEdge("WriteDACL")
EdgeWriteSPN = engine.NewEdge("WriteSPN").RegisterProbabilityCalculator(func(source, target *engine.Object) engine.Probability {
Expand Down Expand Up @@ -77,4 +77,6 @@ var (
EdgeWriteProfilePath = engine.NewEdge("WriteProfilePath")
EdgeWriteScriptPath = engine.NewEdge("WriteScriptPath")
EdgeCertificateEnroll = engine.NewEdge("CertificateEnroll")
EdgeCertificateAutoEnroll = engine.NewEdge("CertificateAutoEnroll")
EdgeVoodooBit = engine.NewEdge("VoodooBit")
)

0 comments on commit 3cb3855

Please sign in to comment.