Security Configuration Assessment
This section attempts to introduce how this module can help us to secure our systems.
The configuration assessment scope
One of the most certain ways to avoid hosts being compromised is to secure them by reducing their surface of vulnerabilities. That process is commonly known as hardening, and the configuration assessment is the most effective way to determine where the hosts may have their hardening improved.
The SCA will perform scans using policy files as templates to discover the exposures or misconfiguration of the monitored hosts. For example it will determine if it is necessary to change default passwords, remove unnecessary software, unnecessary usernames or logins, and disable or remove of unnecessary services. The target of those policies can be an Operating System such as Debian or Windows, or a particular software like the SSH server.
Security compliance
Each policy check can contain an optional compliance field that is used to specify how the check is relevant to different Compliance Standards specifications. Many of the default policies available with Wazuh, especially CIS policies, already have the CIS and PCI-DSS controls mapped. Here we can see an example:
id: 6512
title: "Ensure noexec option set on removable media partitions"
description: "The noexec mount option specifies that the filesystem cannot contain executable binaries."
rationale: "Setting this option on a file system prevents users from executing programs from the removable media. This deters users from being able to introduce potentially malicious software on the system."
remediation: "Edit the /etc/fstab file and add noexec to the fourth field (mounting options) of all removable media partitions. Look for entries that have mount points that contain words such as floppy or cdrom."
compliance:
- cis: "1.1.20"
- cis_csc: "8"
- pci_dss: "2.2.4"
condition: any
rules:
- 'f:/etc/fstab -> NIN !r:^# && r:/media && r:noexec;'
SCA scan results
SCA scan results appear as alerts when a check has changed its status between scans. Only the events that are necessary to keep the global status of the scan updated are sent by agents, avoiding the flooding of unnecessary events in each scan.
An alert example can be seen here:
** Alert 1556643969.400529: - sca,gdpr_IV_35.7.d
2019 Apr 30 10:06:09 (centos) 192.168.0.97->sca
Rule: 19008 (level 3) -> 'CIS Benchmark for Red Hat Enterprise Linux 7: Ensure address space layout randomization (ASLR) is enabled'
{"type":"check","id":645241598,"policy":"CIS Benchmark for Red Hat Enterprise Linux 7","policy_id":"cis_rhel7","check":{"id":6523,"title":"Ensure address space layout randomization (ASLR) is enabled","description":"Address space layout randomization (ASLR) is an exploit mitigation technique which randomly arranges the address space of key data areas of a process.","rationale":"Randomly placing virtual memory regions will make it difficult to write memory page exploits as the memory placement will be consistently shifting.","remediation":"Set the following parameter in /etc/sysctl.conf or a /etc/sysctl.d/* file: kernel.randomize_va_space = 2 and set the active kernel parameter","compliance":{"cis":"1.5.3","cis_csc":"8.4"},"rules":["f:/proc/sys/kernel/randomize_va_space -> !r:^2$;"],"file":"/proc/sys/kernel/randomize_va_space","result":"passed"}}
sca.type: check
sca.scan_id: 645241598
sca.policy: CIS Benchmark for Red Hat Enterprise Linux 7
sca.check.id: 6523
sca.check.title: Ensure address space layout randomization (ASLR) is enabled
sca.check.description: Address space layout randomization (ASLR) is an exploit mitigation technique which randomly arranges the address space of key data areas of a process.
sca.check.rationale: Randomly placing virtual memory regions will make it difficult to write memory page exploits as the memory placement will be consistently shifting.
sca.check.remediation: Set the following parameter in /etc/sysctl.conf or a /etc/sysctl.d/* file: kernel.randomize_va_space = 2 and set the active kernel parameter
sca.check.compliance.cis: 1.5.3
sca.check.compliance.cis_csc: 8.4
sca.check.file: ["/proc/sys/kernel/randomize_va_space"]
sca.check.result: passed
On the Wazuh App, within the SCA tab we can see the result for each check of the scanned policies. In addition, each check can be expanded to view more detailed information about it.

Scanned policies overview
Every scanned policy should contain a header to provide its overview information. Here we can see a header example:
policy:
id: "system_audit_ssh"
file: "system_audit_ssh.yml"
name: "System audit for SSH hardening"
description: "Guidance for establishing a secure configuration for SSH service vulnerabilities."
references:
- https://www.ssh.com/ssh/
Fields like id are mandatory to identify and classify policies.
The following screenshot of the SCA tab shows an overview of scanned policies for an agent:

Available policies
Policies for the SCA module are written using the YAML format, which was chosen due to its focus on human readability, which allows the user to quickly understand and write their own policy files or extend the existing ones.
Many of the available default policies are based on CIS benchmarks, enriched with valuable information for every check.
Available policies list
When a Wazuh agent is installed, the system will only include the policy files supported by that particular Operating System. The following list shows all the default policy files available for the Operating Systems officially supported by Wazuh. These policies are all included with the Wazuh manager installation so they may be included in agent groups easily.
Policy |
Name |
Requirement |
acsc_office2016_rcl |
System audit for Office 2016 vulnerabilities |
Microsoft Office 2016 |
cis_apache2224_rcl |
CIS Apache HTTP Server 2.2/2.4 Benchmark |
Apache configuration files |
cis_win2012r2_domainL1_rcl |
CIS benchmark for Windows 2012 R2 Domain Controller L1 |
Windows Server 2012 R2 |
cis_win2012r2_domainL2_rcl |
CIS benchmark for Windows 2012 R2 Domain Controller L2 |
Windows Server 2012 R2 |
cis_win2012r2_memberL1_rcl |
CIS benchmark for Windows 2012 R2 Member Server L1 |
Windows Server 2012 R2 |
cis_win2012r2_memberL2_rcl |
CIS benchmark for Windows 2012 R2 Member Server L2 |
Windows Server 2012 R2 |
cis_rhel5_linux_rcl |
CIS Benchmark for Red Hat Enterprise Linux 5 |
Red Hat Systems |
cis_rhel6_linux_rcl |
CIS Benchmark for Red Hat Enterprise Linux 6 |
Red Hat Systems |
cis_rhel7_linux_rcl |
CIS Benchmark for Red Hat Enterprise Linux 7 |
Red Hat Systems |
cis_apple_macOS_10.11 |
CIS Apple OSX 10.11 Benchmark |
MAC OS X 10.11 (El Capitan) |
cis_apple_macOS_10.12 |
CIS Apple macOS 10.12 Benchmark |
MAC OS X 10.12 (Sierra) |
cis_apple_macOS_10.13 |
CIS Apple macOS 10.13 Benchmark |
MAC OS X 10.13 (High Sierra) |
cis_debianlinux7-8_L1_rcl |
CIS benchmark for Debian/Linux 7 and 8 L1 |
Debian 7 and 8 |
cis_debianlinux7-8_L2_rcl |
CIS benchmark for Debian/Linux 7 and 8 L2 |
Debian 7 and 8 |
cis_debian_linux_rcl |
CIS benchmark for Debian/Linux |
Debian systems |
cis_sles11_linux_rcl |
CIS SUSE Linux Enterprise 11 Benchmark |
SUSE 11 |
cis_sles12_linux_rcl |
CIS SUSE Linux Enterprise 12 Benchmark |
SUSE 12 |
cis_solaris11_rcl |
CIS benchmark for Oracle Solaris 11 |
Solaris 11 |
system_audit_pw |
System audit for password-related vulnerabilities |
Password files |
system_audit_rcl_mac |
System audit for web-related vulnerabilities |
N/A |
system_audit_rcl |
System audit for web-related vulnerabilities |
N/A |
system_audit_ssh |
System audit for SSH hardening |
SSH configuration files |
win_audit_rcl |
Benchmark for Windows audit |
Windows |
cis_win10_enterprise_L1_rcl |
CIS benchmark for Windows 10 Enterprise (Release 1709) |
Windows 10 |
cis_win10_enterprise_L2_rcl |
CIS benchmark for Windows 10 Enterprise (Release 1709) |
Windows 10 |
cis_mysql5-6_community_rcl |
CIS benchmark for Oracle MySQL Community Server 5.6 |
MySQL configuration files |
cis_mysql5-6_enterprise_rcl |
CIS benchmark for Oracle MySQL Enterprise 5.6 |
MySQL configuration files |
Policy files location
On Linux platforms, the default policy files are located under the default installation directory at
/var/ossec/ruleset/sca
.On Windows platformss, the policy files are located under the default installation directory at
C:\\Program files (x86)\\ossec-agent\\ruleset\\sca
.
Creating custom SCA policies
As mentioned previously, the policy files have a YAML format. In order to illustrate shown below is a section of the policy file for SSH hardening:
policy:
id: "system_audit_ssh"
file: "system_audit_ssh.yml"
name: "System audit for SSH hardening"
description: "Guidance for establishing a secure configuration for SSH service vulnerabilities."
references:
- https://www.ssh.com/ssh/
requirements:
title: "Check that the SSH service is installed on the system"
description: "Requirements for running the SCA scan against the SSH policy."
condition: "all required"
rules:
- 'f:/etc/ssh/sshd_config;'
variables:
$sshd_file: /etc/ssh/sshd_config;
checks:
- id: 1500
title: "SSH Hardening - 1: Port 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, an attacker or bot doing port-scanning can quickly identify your SSH port."
remediation: "Change the Port option value in the sshd_config file."
compliance:
- pci_dss: "2.2.4"
condition: any
rules:
- 'f:$sshd_file -> IN !r:^# && r:Port\.+22;'
As shown in this example, there are four sections, not all of them are required for a policy file:
Section |
Required |
policy |
Yes |
requirements |
No |
variables |
No |
checks |
Yes |
Note
If the requirements aren't satisfied for a specific policy file, the scan for that file won't start.
Each section has their own fields that can be mandatory as described below:
Policy section
Field |
Mandatory |
Type |
Allowed values |
id |
Yes |
String |
Any string |
file |
Yes |
String |
Any string |
name |
Yes |
String |
Any string |
description |
Yes |
String |
Any string |
references |
No |
Array of strings |
Any string |
Requirements section
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 |
Variables section
Field |
Mandatory |
Type |
Allowed values |
variable_name |
Yes |
String |
Any string |
Checks section
Field |
Mandatory |
Type |
Allowed values |
id |
Yes |
Numeric |
Any integer number |
title |
Yes |
String |
Any string |
description |
No |
String |
Any string |
rationale |
No |
String |
Any string |
remediation |
No |
String |
Any string |
compliance |
No |
Array of strings |
Any string |
references |
No |
Array of strings |
Any string |
condition |
Yes |
String |
all, any, any required, all required |
rules |
Yes |
Array of strings |
Any string |
It is recommended that new policy files be placed under the ruleset/sca directory.
Note
Remember that the value of the policy and check id fields must be unique, not existing in other policy files.
Information about variables
When setting variables in the variables section:
Make sure they start with
$
characterMake sure they end with
;
character
Example: $sshd_file: /etc/ssh/sshd_config;
Information about rules
General rule syntax
The rules field is where SCA
dictates if a check is marked as passed or failed.
There are five main types of rules as described below:
Type |
Character |
File |
f |
Directory |
d |
Process |
p |
Commands |
c |
Registry (Windows Only) |
r |
In order to better understand the syntax of the rules, it is important to note that:
The type of a rule references the location where the rule will look for the content of the check. Every rule has to start with a location.
The location is commonly followed by the content to look for. It is accepted a literal string or a regular expression preceded by
r:
(the supported Regex syntax can be found here).As explained before, the most common rules have the format
type:location -> r:REGEX;
. However, there are exceptions, for example, for Windows registries, we would have to add the registry key in the middle of the rule.Each rule must end with the semicolon
;
character.
The following examples illustrate this logic:
Rule syntax for files
Checking that a file exists -
'f:/path/to/file;'
Checking file content (whole line match) -
'f:/path/to/file -> content;'
Checking file content with regex -
'f:/path/to/file -> r:REGEX;'
Rule syntax for directories
Checking that a directory exists -
'd:/path/to/directory;'
Checking that a directory contains a file -
'd:/path/to/directory -> file;'
Checking that a directory contains files with regex -
'd:/path/to/directory -> r:^files;'
Checking that a directory contains files and its content -
'd:/path/to/directory -> file -> content;'
Rule syntax for processes
Checking that a process is running -
'p:process_name;'
Rule syntax for commands
Checking the output of a command -
'c:command -> output;'
Checking the output of a command with regex -
'c:command -> r:REGEX;'
Rule syntax for registries (Windows only).
Checking that a registry exists -
'r:path/to/registry ;'
Checking that a registry key exists -
'r:path/to/registry -> key;'
Checking a registry key content -
'r:path/to/registry -> key -> content;'
Global operators for composed rules
When more than one term is necessary, two logical operators can be used to determine the accumulated result of a check (terms are separated by &&
inside a rule).
IN (included): This operator means that both the terms should be matched.
NIN (not included): The opposite operator, it means the rule is triggered if both terms are not matched.
Use cases
Composed rules:
Alert when there is a line that does not begin with
#
and containsPort 22
-'f:/etc/ssh/sshd_config -> IN !r:^# && r:Port\.+22;'
Alert when there is no line that does not begin with
#
and containsPort 2222
-'f:/etc/ssh/sshd_config -> NIN !r:^# && r:Port\.+2222;'
Other examples:
Looking at the value inside a file:
'f:/proc/sys/net/ipv4/ip_forward -> 1;'
Checking if a file exists:
'f:/proc/sys/net/ipv4/ip_forward;'
Checking if a process is running:
'p:avahi-daemon;'
Looking at the value of a registry:
'r:HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Netlogon\Parameters -> MaximumPasswordAge -> 0;'
Looking if a directory contains files:
'd:/home/* -> ^.mysql_history$;'
Checking if a directory exists:
'd:/etc/mysql;
Check the running configuration of ssh to check the maximum authentication tries:
'c:sshd -T -> !r:^\s*maxauthtries\s+4\s*$;'
Check if root is the only UID 0 account
'f:/etc/passwd -> IN !r:^# && !r:^root: && r:^\w+:\w+:0:;'