docs/ref/modules/sca/custom-policies.md
When creating custom SCA policy files, you need to consider the following four sections, although not all of them are required.
| Section | Required |
|---|---|
| policy | Yes |
| requirements | No |
| variables | No |
| checks | Yes |
# Security Configuration Assessment
# Audit for UNIX systems
# Copyright (C) 2015, Wazuh Inc.
#
# This program is free software; you can redistribute it
# and/or modify it under the terms of the GNU General Public
# License (version 2) as published by the FSF - Free Software
# Foundation
policy:
id: "unix_audit"
file: "sca_unix_audit.yml"
name: "System audit for Unix based systems"
description: "Guidance for establishing a secure configuration for Unix based systems."
references:
- https://www.ssh.com/ssh/
requirements:
title: "Check that the SSH service and password-related files are present on the system"
description: "Requirements for running the SCA scan against the Unix based systems policy."
condition: any
rules:
- 'f:$sshd_file'
- 'f:/etc/passwd'
- 'f:/etc/shadow'
variables:
$sshd_file: /etc/ssh/sshd_config
$pam_d_files: /etc/pam.d/common-password,/etc/pam.d/password-auth,/etc/pam.d/system-auth,/etc/pam.d/system-auth-ac,/etc/pam.d/passwd
checks:
- id: 3000
title: "SSH Hardening: Port should not be 22"
description: "The ssh daemon should not be listening on port 22 (the default value) for incoming connections."
rationale: "Changing the default port you may reduce the number of successful attacks from zombie bots."
remediation: "Change the Port option value in the sshd_config file."
compliance:
pci_dss: ["2.2.4"]
nist_800_53: ["CM.1"]
mitre:
tactic: ["TA0008"]
technique: ["T1021"]
condition: all
rules:
- 'f:$sshd_file -> !r:^# && r:Port && !r:\s*\t*22$'
- id: 3001
title: "SSH Hardening: Protocol should be set to 2"
Note
If therequirementsare not satisfied for a specific policy file, the scan for that file will not start.
| Field | Mandatory | Type | Allowed values | Description |
|---|---|---|---|---|
| id | Yes | String | Any string | Policy ID |
| file | Yes | String | Any string | Policy filename |
| name | Yes | String | Any string | Policy title |
| description | Yes | String | Any string | Brief description |
| references | No | Array of strings | Any string | Reference links |
| regex_type | No | String | osregex, pcre2 | Regex engine |
| Field | Mandatory | Type | Allowed values |
|---|---|---|---|
| title | Yes | String | Any string |
| description | Yes | String | Any string |
| condition | Yes | String | Any string |
| rules | Yes | Array of strings | Any string |
| Field | Mandatory | Type | Allowed values |
|---|---|---|---|
| variable_name | Yes | Array of strings | Any string |
Note
Theidfield underpolicyandchecksmust be unique across policy files.
Variables are defined in the variables section and are prefixed with $.
Examples:
$list_of_files: /etc/ssh/sshd_config, /etc/sysctl.conf, /var/log/dmesg$list_of_folders: /etc, /var, /tmp$program_name: apache2Example rules using variables:
f:$list_of_files -> r:^Content to be found
c:systemctl is-enabled $program_name -> r:^enabled
There is no limit on the number of variables per rule.
Checks define what actions the agent performs and how results are evaluated.
| Field | Mandatory | Type | Allowed values |
|---|---|---|---|
| id | Yes | Numeric | Any integer |
| title | Yes | String | Any string |
| description | No | String | Any string |
| rationale | No | String | Any string |
| remediation | No | String | Any string |
| compliance | No | Object | See Compliance keys |
| mitre | No | Object | See MITRE keys |
| references | No | Array of strings | Any string |
| condition | Yes | String | all, any, none |
| rules | Yes | Array of strings | Any string |
| regex_type | No | String | pcre2, osregex |
Note A
regex_typedefined at the check level overrides the policy-level regex engine.
The compliance field is an object that maps compliance framework keys to arrays of identifier strings. Only the following keys are allowed:
cmmc, fedramp, gdpr, hipaa, iso_27001, nis2, nist_800_171, nist_800_53, pci_dss, tsc
Unknown keys are rejected with a warning and excluded from the check.
The mitre field is an object that maps MITRE ATT&CK categories to arrays of identifier strings. The following keys are supported:
tactic, technique, subtechnique, mitigation
Conditions define how rule results are aggregated:
all: Pass if all rules passany: Pass if at least one rule passesnone: Pass if no rule passes| Condition | Passed | Failed | Not applicable | Result |
|---|---|---|---|---|
| all | yes | no | no | Passed |
| all | * | no | yes | Not applicable |
| all | * | yes | * | Failed |
| any | yes | * | * | Passed |
| any | no | yes | no | Failed |
| any | no | * | yes | Not applicable |
| none | yes | * | * | Failed |
| none | no | * | yes | Not applicable |
| none | no | yes | no | Passed |
* does not affect the final result.
Rules define existence or content checks.
| Type | Character |
|---|---|
| File | f |
| Directory | d |
| Process | p |
| Command | c |
| Registry | r |
RULE_TYPE:target
Examples:
f:/etc/sshd_configd:/etcnot p:sshdr:HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\LsaRULE_TYPE:target -> OPERATOR:value
Examples:
f:/etc/ssh_config -> !r:PermitRootLogin
f:/etc/ssh_config -> !r:^# && r:Protocol && r:2
c:systemctl is-enabled cups -> r:^enabled
Notes
- Content checks operate at line level
- Spaces around
->,&&, andcompareare mandatory
f:/path/to/filef:/path/to/file -> r:REGEXf:/path/to/file -> n:REGEX(\d+) compare <= 4d:/path/to/directoryd:/path/to/directory -> file_namep:process_namenot p:process_namec:command -> r:REGEXc:command -> n:REGEX(\d+) compare >= numberr:path/to/keyr:path/to/key -> value -> contentf:/etc/ssh/sshd_config -> !r:^# && r:Port\.+22not f:/etc/ssh/sshd_config -> !r:^# && r:Port\.+22f:/proc/sys/net/ipv4/ip_forward -> 1p:avahi-daemond:/etc/mysqlc:sshd -T -> !r:^\s*maxauthtries\s+4\s*$f:/etc/passwd -> !r:^# && !r:^root: && r:^\w+:\w+:0: