CIS 5.1.3+5.1.4 (#9642)

This commit is contained in:
Sharon Katz
2023-02-07 13:26:05 -05:00
committed by GitHub
parent 46b8929e64
commit 84fcee9130
11 changed files with 259 additions and 4 deletions
+36
View File
@@ -1270,6 +1270,42 @@ spec:
---
apiVersion: v1
kind: policy
spec:
name: CIS - Ensure Apple Mobile File Integrity (AMFI) Is Enabled (fleetd required)
platforms: macOS
platform: darwin
description: |
Apple Mobile File Integrity (AMFI) was first released in macOS 10.12. The daemon and service block attempts to run unsigned code. AMFI uses launchd, code signatures, certificates, entitlements, and provisioning profiles to create a filtered entitlement dictionary for an app. AMFI is the macOS kernel module that enforces code-signing and library validation.
Note: AMFI cannot be disabled with SIP enabled, but a change attempt can be made that will appear successful, and report incorrectly as successful. If the AMFI audit fails, and the SIP audit passes, this is still an issue the admin should research.
resolution: |
Automated method:
Ask your system administrator to deploy the following script which will Ensure Apple Mobile File Integrity (AMFI) Is Enabled:
/usr/bin/sudo /usr/sbin/nvram boot-args=""
query: SELECT 1 FROM nvram_info WHERE amfi_enabled="1";
purpose: Informational
tags: compliance, CIS, CIS_Level1, CIS5.1.3
contributors: sharon-fdm
---
apiVersion: v1
kind: policy
spec:
name: CIS - Ensure Sealed System Volume (SSV) Is Enabled (fleetd required)
platforms: macOS
platform: darwin
description: |
Sealed System Volume is a security feature introduced in macOS 11.0 Big Sur.
During system installation, a SHA-256 cryptographic hash is calculated for all immutable system files and stored in a Merkle tree which itself is hashed as the Seal. Both are stored in the metadata of the snapshot created of the System volume.
The seal is verified by the boot loader at startup. macOS will not boot if system files have been tampered with. If validation fails, the user will be instructed to reinstall the operating system.
During read operations for files located in the Sealed System Volume, a hash is calculated and compared to the value stored in the Merkle tree.
resolution: |
If SSV has been disabled, assume that the operating system has been compromised. Back up any files, and do a clean install to a known good Operating System.
query: SELECT 1 FROM csrutil_info WHERE ssv_enabled="1";
purpose: Informational
tags: compliance, CIS, CIS_Level1, CIS5.1.4
contributors: sharon-fdm
---
apiVersion: v1
kind: policy
spec:
name: CIS - Ensure Password Account Lockout Threshold Is Configured (Fleetd required)
platforms: macOS
@@ -0,0 +1 @@
- Implement table to hold csrutil_info extension via Orbit
@@ -0,0 +1 @@
- Implement table to hold nvram_info extension via Orbit
@@ -0,0 +1,54 @@
//go:build darwin
// +build darwin
package csrutil_info
import (
"context"
"github.com/osquery/osquery-go/plugin/table"
"github.com/rs/zerolog/log"
"os/exec"
"strings"
"time"
)
// Columns is the schema of the table.
func Columns() []table.ColumnDefinition {
return []table.ColumnDefinition{
table.IntegerColumn("ssv_enabled"),
}
}
// Generate is called to return the results for the table at query time.
// Constraints for generating can be retrieved from the queryContext.
func Generate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
SSVEnabled, err := getSSVEnabled(ctx)
return []map[string]string{
{"ssv_enabled": SSVEnabled},
}, err
}
func getSSVEnabled(ctx context.Context) (SSVEnabled string, err error) {
res, err := runCommand(ctx, "/usr/bin/csrutil", "authenticated-root", "status")
SSVEnabled = ""
if err == nil {
SSVEnabled = "0"
if strings.Contains(res, "Authenticated Root status: enabled") {
SSVEnabled = "1"
}
}
return SSVEnabled, err
}
func runCommand(ctx context.Context, name string, arg ...string) (res string, err error) {
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
cmd := exec.CommandContext(ctx, name, arg...)
out, err := cmd.Output()
if err != nil {
log.Debug().Err(err).Msg("failed while generating csrutil_info table")
return "", err
}
return string(out), nil
}
@@ -0,0 +1,37 @@
//go:build darwin
// +build darwin
package csrutil_info
import (
"github.com/osquery/osquery-go/plugin/table"
"golang.org/x/net/context"
"testing"
"time"
)
func TestGenerate(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
var tbl table.QueryContext
table, err := Generate(ctx, tbl)
if err != nil {
t.Fatalf(`Expected no error. got %s`, err)
}
if table[0]["ssv_enabled"] != "0" && table[0]["ssv_enabled"] != "1" {
t.Fatalf(`ssvEnabled expected 0 or 1. got %s`, table[0]["ssvEnabled"])
}
}
func TestGetSSVEnabled(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
ssvEnabled, err := getSSVEnabled(ctx)
if ssvEnabled != "0" && ssvEnabled != "1" {
t.Fatalf(`ssvEnabled expected 0 or 1. got %s`, ssvEnabled)
}
if err != nil {
t.Fatalf(`Expected no error. got %s`, err)
}
}
+4
View File
@@ -3,6 +3,8 @@
package table
import (
"github.com/fleetdm/fleet/v4/orbit/pkg/table/csrutil_info"
"github.com/fleetdm/fleet/v4/orbit/pkg/table/nvram_info"
"github.com/fleetdm/fleet/v4/orbit/pkg/table/privaterelay"
"github.com/fleetdm/fleet/v4/orbit/pkg/table/pwd_policy"
"github.com/fleetdm/fleet/v4/orbit/pkg/table/user_login_settings"
@@ -22,6 +24,8 @@ func platformTables() []osquery.OsqueryPlugin {
table.NewPlugin("icloud_private_relay", privaterelay.Columns(), privaterelay.Generate),
table.NewPlugin("user_login_settings", user_login_settings.Columns(), user_login_settings.Generate),
table.NewPlugin("pwd_policy", pwd_policy.Columns(), pwd_policy.Generate),
table.NewPlugin("csrutil_info", csrutil_info.Columns(), csrutil_info.Generate),
table.NewPlugin("nvram_info", nvram_info.Columns(), nvram_info.Generate),
// Macadmins extension tables
table.NewPlugin("filevault_users", filevaultusers.FileVaultUsersColumns(), filevaultusers.FileVaultUsersGenerate),
+55
View File
@@ -0,0 +1,55 @@
//go:build darwin
// +build darwin
package nvram_info
import (
"context"
"github.com/osquery/osquery-go/plugin/table"
"github.com/rs/zerolog/log"
"os/exec"
"strings"
"time"
)
// Columns is the schema of the table.
func Columns() []table.ColumnDefinition {
return []table.ColumnDefinition{
table.IntegerColumn("amfi_enabled"),
}
}
// Generate is called to return the results for the table at query time.
// Constraints for generating can be retrieved from the queryContext.
func Generate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
amfiEnabled, err := getAMFIEnabled(ctx)
return []map[string]string{
{"amfi_enabled": amfiEnabled},
}, err
}
func getAMFIEnabled(ctx context.Context) (amfiEnabled string, err error) {
res, err := runCommand(ctx, "/usr/sbin/nvram", "-p")
amfiEnabled = ""
if err == nil {
amfiEnabled = "0"
if !strings.Contains(res, "amfi_get_out_of_my_way=1") {
amfiEnabled = "1"
}
}
return amfiEnabled, err
}
func runCommand(ctx context.Context, name string, arg ...string) (res string, err error) {
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
cmd := exec.CommandContext(ctx, name, arg...)
out, err := cmd.Output()
if err != nil {
log.Debug().Err(err).Msg("failed while generating nvram table")
return "", err
}
return string(out), nil
}
@@ -0,0 +1,37 @@
//go:build darwin
// +build darwin
package nvram_info
import (
"github.com/osquery/osquery-go/plugin/table"
"golang.org/x/net/context"
"testing"
"time"
)
func TestGenerate(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
var tbl table.QueryContext
table, err := Generate(ctx, tbl)
if err != nil {
t.Fatalf(`Expected no error. got %s`, err)
}
if table[0]["amfi_enabled"] != "0" && table[0]["amfi_enabled"] != "1" {
t.Fatalf(`amfiEnabled expected 0 or 1. got %s`, table[0]["amfi_enabled"])
}
}
func TestGetAMFIEnabled(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
amfiEnabled, err := getAMFIEnabled(ctx)
if amfiEnabled != "0" && amfiEnabled != "1" {
t.Fatalf(`amfiEnabled expected 0 or 1. got %s`, amfiEnabled)
}
if err != nil {
t.Fatalf(`Expected no error. got %s`, err)
}
}
+16
View File
@@ -0,0 +1,16 @@
name: csrutil_info
platforms:
- darwin
description: Information from csrutil system call.
columns:
- name: ssv_enabled
type: integer
required: false
description: |
Sealed System Volume is a security feature introduced in macOS 11.0 Big Sur.
During system installation, a SHA-256 cryptographic hash is calculated for all immutable system files and stored in a Merkle tree which itself is hashed as the Seal. Both are stored in the metadata of the snapshot created of the System volume.
The seal is verified by the boot loader at startup. macOS will not boot if system files have been tampered with. If validation fails, the user will be instructed to reinstall the operating system.
During read operations for files located in the Sealed System Volume, a hash is calculated and compared to the value stored in the Merkle tree.
notes: >-
- This table is not a core osquery table. It is included as part of Fleetd, the osquery manager from Fleet.
evented: false
+14
View File
@@ -0,0 +1,14 @@
name: nvram_info
platforms:
- darwin
description: Information from nvram system call.
columns:
- name: amfi_enabled
type: integer
required: false
description: |
Apple Mobile File Integrity (AMFI) was first released in macOS 10.12. The daemon and service block attempts to run unsigned code. AMFI uses lanchd, code signatures, certificates, entitlements, and provisioning profiles to create a filtered entitlement dictionary for an app. AMFI is the macOS kernel module that enforces code-signing and library validation.
Note: AMFI cannot be disabled with SIP enabled, but a change attempt can be made that will appear successful, and report incorrectly as successful. If the AMFI audit fails, and the SIP audit passes, this is still an issue the admin should research.
notes: >-
- This table is not a core osquery table. It is included as part of Fleetd, the osquery manager from Fleet.
evented: false
+4 -4
View File
@@ -3,22 +3,22 @@ platforms:
- darwin
description: Password Policiy (e.g max failed password attempts).
columns:
- name: maxFailedAttempts
- name: max_failed_attempts
type: integer
required: false
description: |
The account lockout threshold specifies the amount of times a user can enter an incorrect password before a lockout will occur. Ensure that a lockout threshold is part of the password policy on the computer.
- name: expiresEveryNDays
- name: expires_every_n_days
type: integer
required: false
description: |
How many days for a new password to expire.
- name: daysToExpiration
- name: days_to_expiration
type: integer
required: false
description: |
How many days are left for the expiration of the current password.
- name: historyDepth
- name: history_depth
type: integer
required: false
description: |