diff --git a/ee/cis/macos-15/cis-policy-queries.yml b/ee/cis/macos-15/cis-policy-queries.yml index 5a04c084f8cb..c611f24edd92 100644 --- a/ee/cis/macos-15/cis-policy-queries.yml +++ b/ee/cis/macos-15/cis-policy-queries.yml @@ -2529,15 +2529,26 @@ spec: /usr/bin/sudo /bin/chmod -R og-rwx /Users/ Or like this if there is a need for excutable access: /usr/bin/sudo /bin/chmod -R og-rw /Users/ - query: SELECT 1 WHERE NOT EXISTS ( - SELECT 1 FROM file WHERE ( - path LIKE '/Users/%' - AND path != '/Users/Shared/' - AND mode != "0700" - AND mode !="0701" - AND mode !="0710" - AND mode !="0711" - )); + query: | + SELECT 1 WHERE NOT EXISTS ( + SELECT 1 FROM find_cmd WHERE ( + directory = '/System/Volumes/Data/Users' + AND type = 'd' + AND mindepth = '1' + AND maxdepth = '1' + + /* Only owner can read/write/execute */ + AND not_perm != '700' + + /* Others can execute only */ + AND not_perm != '701' + AND not_perm != '710' + AND not_perm != '711' + + AND path LIKE '%/Shared' + AND path LIKE '%/Guest' + ) + ); purpose: Informational tags: compliance, CIS, CIS_Level1 contributors: sharon-fdm diff --git a/orbit/pkg/table/find_cmd/find_cmd_darwin.go b/orbit/pkg/table/find_cmd/find_cmd_darwin.go index f8955bacb410..9fa806ef45da 100644 --- a/orbit/pkg/table/find_cmd/find_cmd_darwin.go +++ b/orbit/pkg/table/find_cmd/find_cmd_darwin.go @@ -36,6 +36,12 @@ func Columns() []table.ColumnDefinition { table.TextColumn("type"), // perm allows setting find's '-perm' argument. table.TextColumn("perm"), + // not_perm allows setting find's '-not -perm' argument. + table.TextColumn("not_perm"), + // mindepth allows setting find's '-mindepth' argument. + table.TextColumn("mindepth"), + // maxdepth allows setting find's '-maxdepth' argument. + table.TextColumn("maxdepth"), // path are the found directories. table.TextColumn("path"), } @@ -84,6 +90,16 @@ func Generate(ctx context.Context, queryContext table.QueryContext) ([]map[strin } } + notPerm := getArgumentOpEqual("not_perm") + if notPerm != "" { + if !permRegexp.Match([]byte(notPerm)) { + return nil, fmt.Errorf("not_perm must be of the form: %s", permRegexp) + } + } + + minDepth := getArgumentOpEqual("mindepth") + maxDepth := getArgumentOpEqual("maxdepth") + args := []string{directory} if findType != "" { args = append(args, "-type", findType) @@ -91,6 +107,15 @@ func Generate(ctx context.Context, queryContext table.QueryContext) ([]map[strin if perm != "" { args = append(args, "-perm", perm) } + if notPerm != "" { + args = append(args, "-not", "-perm", notPerm) + } + if minDepth != "" { + args = append(args, "-mindepth", minDepth) + } + if maxDepth != "" { + args = append(args, "-maxdepth", maxDepth) + } cmd := exec.Command("/usr/bin/find", args...) stdoutPipe, err := cmd.StdoutPipe() @@ -138,7 +163,10 @@ func Generate(ctx context.Context, queryContext table.QueryContext) ([]map[strin rows = append(rows, map[string]string{ "directory": directory, "perm": perm, + "not_perm": notPerm, "type": findType, + "mindepth": minDepth, + "maxdepth": maxDepth, "path": outDir, }) } diff --git a/orbit/pkg/table/find_cmd/find_cmd_darwin_test.go b/orbit/pkg/table/find_cmd/find_cmd_darwin_test.go index 08c6438cf414..656b490ec4a2 100644 --- a/orbit/pkg/table/find_cmd/find_cmd_darwin_test.go +++ b/orbit/pkg/table/find_cmd/find_cmd_darwin_test.go @@ -185,4 +185,96 @@ func TestGenerate(t *testing.T) { require.NoError(t, err) require.Len(t, rows, 1) require.Equal(t, rows[0]["path"], filepath.Join(testDir, "zoo")) + + // Test with not_perm argument + rows, err = Generate(context.Background(), table.QueryContext{ + Constraints: map[string]table.ConstraintList{ + "directory": { + Affinity: table.ColumnTypeText, + Constraints: []table.Constraint{ + { + Operator: table.OperatorEquals, + Expression: testDir, + }, + }, + }, + "not_perm": { + Affinity: table.ColumnTypeText, + Constraints: []table.Constraint{ + { + Operator: table.OperatorEquals, + Expression: "-2", + }, + }, + }, + }, + }) + require.NoError(t, err) + require.Len(t, rows, 1) + require.Equal(t, rows[0]["path"], testDir) + + // Test with invalid not_perm argument + _, err = Generate(context.Background(), table.QueryContext{ + Constraints: map[string]table.ConstraintList{ + "directory": { + Affinity: table.ColumnTypeText, + Constraints: []table.Constraint{ + { + Operator: table.OperatorEquals, + Expression: testDir, + }, + }, + }, + "not_perm": { + Affinity: table.ColumnTypeText, + Constraints: []table.Constraint{ + { + Operator: table.OperatorEquals, + Expression: "invalid", + }, + }, + }, + }, + }) + require.Error(t, err) + + // Test with mindepth and maxdepth + err = os.MkdirAll(filepath.Join(testDir, "a/b/c"), os.ModePerm) + require.NoError(t, err) + + rows, err = Generate(context.Background(), table.QueryContext{ + Constraints: map[string]table.ConstraintList{ + "directory": { + Affinity: table.ColumnTypeText, + Constraints: []table.Constraint{ + { + Operator: table.OperatorEquals, + Expression: testDir, + }, + }, + }, + "mindepth": { + Affinity: table.ColumnTypeText, + Constraints: []table.Constraint{ + { + Operator: table.OperatorEquals, + Expression: "2", + }, + }, + }, + "maxdepth": { + Affinity: table.ColumnTypeText, + Constraints: []table.Constraint{ + { + Operator: table.OperatorEquals, + Expression: "3", + }, + }, + }, + }, + }) + require.NoError(t, err) + require.Len(t, rows, 2) + require.Equal(t, rows[0]["path"], filepath.Join(testDir, "a/b")) + require.Equal(t, rows[1]["path"], filepath.Join(testDir, "a/b/c")) } diff --git a/schema/osquery_fleet_schema.json b/schema/osquery_fleet_schema.json index 33f950a6a4fa..0f5d8fc22565 100644 --- a/schema/osquery_fleet_schema.json +++ b/schema/osquery_fleet_schema.json @@ -10812,6 +10812,24 @@ "required": false, "description": "Sets the value of the `-perm` flag." }, + { + "name": "not_perm", + "type": "text", + "required": false, + "description": "Sets the value of the `-not -perm` flag to find files that do NOT have the specified permissions." + }, + { + "name": "mindepth", + "type": "text", + "required": false, + "description": "Sets the value of the `-mindepth` flag to specify the minimum directory depth." + }, + { + "name": "maxdepth", + "type": "text", + "required": false, + "description": "Sets the value of the `-maxdepth` flag to specify the maximum directory depth." + }, { "name": "path", "type": "text", diff --git a/schema/tables/find_cmd.yml b/schema/tables/find_cmd.yml index 97633d75344f..e0ac2a73ef21 100644 --- a/schema/tables/find_cmd.yml +++ b/schema/tables/find_cmd.yml @@ -18,6 +18,21 @@ columns: required: false description: |- Sets the value of the `-perm` flag. + - name: not_perm + type: text + required: false + description: |- + Sets the value of the `-not -perm` flag to find files that do NOT have the specified permissions. + - name: mindepth + type: text + required: false + description: |- + Sets the value of the `-mindepth` flag to specify the minimum directory depth. + - name: maxdepth + type: text + required: false + description: |- + Sets the value of the `-maxdepth` flag to specify the maximum directory depth. - name: path type: text required: false