Skip to content

Commit

Permalink
GPO file permission analysis added, bugfix for local machine file per…
Browse files Browse the repository at this point in the history
…missions analysis
  • Loading branch information
lkarlslund committed Jan 20, 2022
1 parent e3d8392 commit 8601189
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 15 deletions.
18 changes: 18 additions & 0 deletions modules/analyze/html/graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,24 @@ var cytostyle = [{
"background-color": "lightgreen"
}
},
{
selector: 'node[type="Directory"]',
style: {
shape: "diamond",
"background-image": "icons/source_black_24dp.svg",
"background-color": "lightblue"
}
},
{
selector: 'node[type="File"]',
style: {
shape: "diamond",
"background-image": "icons/article_black_24dp.svg",
"background-color": "lightblue"
}
},


{
selector: 'node[type="GroupPolicyContainer"]',
style: {
Expand Down
1 change: 1 addition & 0 deletions modules/analyze/html/icons/article_black_24dp.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion modules/analyze/webservicefuncs.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ func analysisfuncs(ws *webservice) {
}

resulttypes := make(map[string]int)
for i := 0; i < engine.OBJECTTYPEMAX; i++ {
for i := engine.ObjectType(0); i < engine.OBJECTTYPEMAX; i++ {
if objecttypes[i] > 0 {
resulttypes[engine.ObjectType(i).String()] = objecttypes[i]
}
Expand Down
8 changes: 7 additions & 1 deletion modules/engine/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ const (
ObjectTypeTrust
ObjectTypeService
ObjectTypeExecutable
OBJECTTYPEMAX = iota - 1
ObjectTypeDirectory
ObjectTypeFile
OBJECTTYPEMAX = iota
)

type Object struct {
Expand Down Expand Up @@ -351,6 +353,10 @@ func (o *Object) Type() ObjectType {
o.objecttype = ObjectTypeService
case "Executable":
o.objecttype = ObjectTypeExecutable
case "Directory":
o.objecttype = ObjectTypeDirectory
case "File":
o.objecttype = ObjectTypeFile
default:
o.objecttype = ObjectTypeOther
}
Expand Down
8 changes: 5 additions & 3 deletions modules/engine/objecttype_enumer.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 56 additions & 5 deletions modules/integrations/activedirectory/analyze/gpoimport.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package analyze
import (
"encoding/xml"
"fmt"
"path/filepath"
"regexp"
"strings"

Expand All @@ -16,6 +17,14 @@ import (

var (
gPCFileSysPath = engine.NewAttribute("gPCFileSysPath").Merge(nil)

PwnOwns = engine.NewPwn("Owns")
PwnFSPartOfGPO = engine.NewPwn("FSPartOfGPO")
PwnFileCreate = engine.NewPwn("FileCreate")
PwnDirCreate = engine.NewPwn("DirCreate")
PwnFileWrite = engine.NewPwn("FileWrite")
PwnTakeOwnership = engine.NewPwn("FileTakeOwnership")
PwnModifyDACL = engine.NewPwn("FileModifyDACL")
)

func ImportGPOInfo(ginfo activedirectory.GPOdump, ao *engine.Objects) error {
Expand All @@ -24,19 +33,61 @@ func ImportGPOInfo(ginfo activedirectory.GPOdump, ao *engine.Objects) error {
// Pwns(gpoobject)

for _, item := range ginfo.Files {
relativepath := strings.ToLower(strings.ReplaceAll(item.RelativePath, "\\", "/"))

absolutepath := filepath.Join(ginfo.Path, relativepath)

objecttype := "File"
if item.IsDir {
objecttype = "Directory"
}

itemobject, _ := ao.FindOrAdd(gPCFileSysPath, engine.AttributeValueString(absolutepath),
engine.DisplayName, engine.AttributeValueString(relativepath),
engine.ObjectCategorySimple, engine.AttributeValueString(objecttype),
)

if relativepath == "/" {
itemobject.Pwns(gpoobject, PwnFSPartOfGPO)
} else {
parentpath := filepath.Join(ginfo.Path, filepath.Dir(relativepath))
parent, _ := ao.FindOrAdd(gPCFileSysPath, engine.AttributeValueString(parentpath))
itemobject.Pwns(parent, PwnFSPartOfGPO)
}

if !item.OwnerSID.IsNull() {
owner, _ := ao.FindOrAdd(engine.ObjectSid, engine.AttributeValueString(item.OwnerSID))
owner.Pwns(itemobject, PwnOwns)
}

if item.DACL != nil {
dacl, err := engine.ParseACL(item.DACL)
if err != nil {
return err
}
for _, acl := range dacl.Entries {
// log.Debug().Msgf("ACL: %v", acl.String(ao))
_ = acl
for _, entry := range dacl.Entries {
entrysidobject, _ := ao.FindOrAdd(activedirectory.ObjectSid, engine.AttributeValueSID(entry.SID))

if entry.Type == engine.ACETYPE_ACCESS_ALLOWED && entry.SID.Component(2) == 21 {
if item.IsDir && entry.Mask&engine.FILE_ADD_FILE != 0 {
entrysidobject.Pwns(itemobject, PwnFileCreate)
}
if item.IsDir && entry.Mask&engine.FILE_ADD_SUBDIRECTORY != 0 {
entrysidobject.Pwns(itemobject, PwnDirCreate)
}
if !item.IsDir && entry.Mask&engine.FILE_WRITE_DATA != 0 {
entrysidobject.Pwns(itemobject, PwnFileWrite)
}
if entry.Mask&engine.RIGHT_WRITE_OWNER != 0 {
entrysidobject.Pwns(itemobject, PwnTakeOwnership) // Not sure about this one
}
if entry.Mask&engine.RIGHT_WRITE_DACL != 0 {
entrysidobject.Pwns(itemobject, PwnModifyDACL)
}
}
}
}

relativepath := strings.ToLower(strings.ReplaceAll(item.RelativePath, "\\", "/"))

switch relativepath {
case "/machine/preferences/groups/groups.xml", "/machine/microsoft/windows nt/secedit/gpttmpl.inf":
var pairs []SIDpair
Expand Down
10 changes: 5 additions & 5 deletions modules/integrations/localmachine/analyze/analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ func ImportCollectorInfo(cinfo localmachine.Info, ao *engine.Objects) error {
if sd, err := engine.ParseACL(service.RegistryDACL); err == nil {
for _, entry := range sd.Entries {
entrysid := entry.SID
if entry.Type&engine.ACETYPE_ACCESS_ALLOWED != 0 && entrysid.Component(2) == 21 {
if entry.Type == engine.ACETYPE_ACCESS_ALLOWED && entrysid.Component(2) == 21 {

if localsid != originalsid && entrysid.StripRID() == originalsid {
// Replace SID
Expand Down Expand Up @@ -424,7 +424,7 @@ func ImportCollectorInfo(cinfo localmachine.Info, ao *engine.Objects) error {
if sd, err := engine.ParseACL(service.ImageExecutableDACL); err == nil {
for _, entry := range sd.Entries {
entrysid := entry.SID
if entry.Type&engine.ACETYPE_ACCESS_ALLOWED != 0 && entrysid.Component(2) == 21 {
if entry.Type == engine.ACETYPE_ACCESS_ALLOWED && entrysid.Component(2) == 21 {
if localsid != originalsid && entrysid.StripRID() == originalsid {
// Replace SID
entrysid = localsid.AddComponent(entrysid.RID())
Expand All @@ -433,13 +433,13 @@ func ImportCollectorInfo(cinfo localmachine.Info, ao *engine.Objects) error {
o, _ := ao.FindOrAdd(
activedirectory.ObjectSid, engine.AttributeValueSID(entrysid),
)
if entry.Mask&engine.FILE_WRITE_DATA != engine.FILE_WRITE_DATA {
if entry.Mask&engine.FILE_WRITE_DATA != 0 {
o.Pwns(serviceimageobject, PwnFileWrite)
}
if entry.Mask&engine.RIGHT_WRITE_OWNER != engine.RIGHT_WRITE_OWNER {
if entry.Mask&engine.RIGHT_WRITE_OWNER != 0 {
o.Pwns(serviceimageobject, PwnFileTakeOwnership) // Not sure about this one
}
if entry.Mask&engine.RIGHT_WRITE_DACL != engine.RIGHT_WRITE_DACL {
if entry.Mask&engine.RIGHT_WRITE_DACL != 0 {
o.Pwns(serviceimageobject, PwnFileModifyDACL)
}
}
Expand Down

0 comments on commit 8601189

Please sign in to comment.