Wazuh Command Monitoring - System Command Auditing
The command monitoring module in Wazuh periodically executes arbitrary commands on endpoints and analyzes their output through the rule engine. Command output is processed like standard log data - it passes through decoding and rule matching stages. This mechanism extends monitoring capabilities beyond log files, enabling tracking of system state, network connections, running processes, and other parameters.
Configuration Methods
Wazuh provides two methods for command monitoring:
Wodle command
The wodle command module is the preferred method. It offers advanced scheduling, script verification, and timeout management capabilities.
<wodle name="command">
<disabled>no</disabled>
<tag>check-open-ports</tag>
<command>netstat -tulnp</command>
<interval>5m</interval>
<run_on_start>yes</run_on_start>
<timeout>30</timeout>
<ignore_output>no</ignore_output>
</wodle>Localfile with command log_format
An alternative method using the <localfile> block with command or full_command formats:
<localfile>
<log_format>full_command</log_format>
<command>netstat -tulnp</command>
<frequency>120</frequency>
</localfile>The difference between command and full_command: with command, each output line is processed as a separate event; with full_command, the entire output forms a single event.
Wodle Command Configuration
Complete XML Block Structure
<wodle name="command">
<disabled>no</disabled>
<tag>descriptive-name</tag>
<command>/path/to/script-or-command</command>
<interval>1d</interval>
<run_on_start>yes</run_on_start>
<timeout>300</timeout>
<ignore_output>no</ignore_output>
<verify_sha256>hash-value</verify_sha256>
<skip_verification>no</skip_verification>
</wodle>Configuration Parameters
| Parameter | Default | Description |
|---|---|---|
disabled | no | Enable or disable the module (yes/no) |
tag | - | Descriptive name for identifying the command in logs |
command | - | Path to the command or script with arguments |
interval | 2s | Interval between executions (s/m/h/d/M) |
run_on_start | yes | Execute on service startup (yes/no) |
timeout | 0 | Maximum execution time in seconds (0 for unlimited) |
ignore_output | no | Suppress output logging (yes/no) |
verify_md5 | - | MD5 hash for executable verification |
verify_sha1 | - | SHA1 hash for verification |
verify_sha256 | - | SHA256 hash for verification |
skip_verification | no | Execute despite hash mismatch (yes/no) |
Advanced Scheduling
Beyond interval-based execution, the wodle command supports binding to specific times:
<!-- Execute daily at 03:00 -->
<wodle name="command">
<disabled>no</disabled>
<tag>daily-audit</tag>
<command>/usr/local/bin/security-audit.sh</command>
<time>03:00</time>
<run_on_start>no</run_on_start>
</wodle>
<!-- Execute on Mondays -->
<wodle name="command">
<disabled>no</disabled>
<tag>weekly-report</tag>
<command>/usr/local/bin/weekly-report.sh</command>
<wday>monday</wday>
<time>06:00</time>
</wodle>
<!-- Execute on the 1st of each month -->
<wodle name="command">
<disabled>no</disabled>
<tag>monthly-inventory</tag>
<command>/usr/local/bin/full-inventory.sh</command>
<day>1</day>
<time>00:00</time>
</wodle>| Parameter | Description |
|---|---|
time | Execution time in hh:mm format |
wday | Day of week (sunday - saturday) |
day | Day of month (1 - 31) |
The day and wday parameters are mutually exclusive.
Monitoring Output Changes
One of the key capabilities is detecting changes in command output between consecutive executions. Wazuh compares the current output with the previous one and generates an alert when differences are found.
This uses the full_command format combined with rules that track changes:
<localfile>
<log_format>full_command</log_format>
<command>netstat -tulnp | sort</command>
<frequency>300</frequency>
<alias>listening-ports</alias>
</localfile>Detection rule for tracking new network listeners:
<rule id="100200" level="7">
<if_sid>530</if_sid>
<match>ossec: output: 'listening-ports'</match>
<check_diff/>
<description>Change detected in listening network ports</description>
<group>network_monitoring,</group>
</rule>The <check_diff/> tag instructs the rule engine to compare the current output against the stored previous result.
Practical Use Cases
Monitoring Open Ports
<wodle name="command">
<disabled>no</disabled>
<tag>open-ports</tag>
<command>ss -tulnp</command>
<interval>5m</interval>
<run_on_start>yes</run_on_start>
<timeout>15</timeout>
</wodle>Monitoring Running Processes
<wodle name="command">
<disabled>no</disabled>
<tag>running-processes</tag>
<command>ps aux --sort=-rss | head -20</command>
<interval>10m</interval>
<run_on_start>yes</run_on_start>
<timeout>10</timeout>
</wodle>Monitoring Disk Usage
<wodle name="command">
<disabled>no</disabled>
<tag>disk-usage</tag>
<command>df -Ph | grep -v tmpfs</command>
<interval>30m</interval>
<run_on_start>yes</run_on_start>
<timeout>10</timeout>
</wodle>Detection rule for high disk usage:
<rule id="100210" level="10">
<if_sid>530</if_sid>
<match>ossec: output: 'disk-usage'</match>
<regex>9[0-9]%|100%</regex>
<description>Disk usage exceeds 90 percent</description>
<group>system_monitoring,disk_alert,</group>
</rule>Monitoring User Sessions
<wodle name="command">
<disabled>no</disabled>
<tag>active-sessions</tag>
<command>who</command>
<interval>5m</interval>
<run_on_start>yes</run_on_start>
<timeout>5</timeout>
</wodle>Checking Security Updates
<wodle name="command">
<disabled>no</disabled>
<tag>security-updates</tag>
<command>/usr/lib/update-notifier/apt-check --human-readable 2>&1</command>
<interval>12h</interval>
<run_on_start>yes</run_on_start>
<timeout>60</timeout>
</wodle>Detecting USB Devices
<wodle name="command">
<disabled>no</disabled>
<tag>usb-devices</tag>
<command>lsusb</command>
<interval>1m</interval>
<run_on_start>yes</run_on_start>
<timeout>5</timeout>
</wodle>Script Verification
The wodle command supports executable integrity verification through checksums. This prevents execution of scripts tampered with by an attacker.
<wodle name="command">
<disabled>no</disabled>
<tag>verified-audit</tag>
<command>/usr/local/bin/audit-check.sh</command>
<interval>1h</interval>
<verify_sha256>292a188e498caea5c5fbfb0beca413c980e7a5edf40d47cf70e1dbc33e4f395e</verify_sha256>
<skip_verification>no</skip_verification>
</wodle>When the hash does not match, the command is not executed and an alert is generated.
Osquery Integration
Wazuh supports integration with Osquery - a tool for SQL-like queries against system state. Osquery results are fed into the Wazuh analysis engine for correlation with other security events.
Agent-side Configuration
Install Osquery on the endpoint and configure log collection:
<localfile>
<log_format>json</log_format>
<location>/var/log/osquery/osqueryd.results.log</location>
</localfile>Osquery Wodle
Wazuh also provides a built-in wodle for managing Osquery:
<wodle name="osquery">
<disabled>no</disabled>
<run_daemon>yes</run_daemon>
<bin_path>/usr/bin/osqueryd</bin_path>
<log_path>/var/log/osquery/osqueryd.results.log</log_path>
<config_path>/etc/osquery/osquery.conf</config_path>
<add_labels>yes</add_labels>
</wodle>Osquery Query Examples
Osquery configuration file (osquery.conf):
{
"schedule": {
"listening_ports": {
"query": "SELECT pid, port, protocol, address FROM listening_ports;",
"interval": 300
},
"installed_packages": {
"query": "SELECT name, version, source FROM deb_packages;",
"interval": 3600
},
"crontab_entries": {
"query": "SELECT command, path FROM crontab;",
"interval": 600
}
}
}Osquery results are automatically processed by Wazuh rules to generate alerts when anomalies are detected.
Remote Command Execution
For centralized monitoring management, commands can be configured through the Wazuh manager and applied to agents. This requires enabling remote commands in the agent configuration:
wazuh_command.remote_commands=1This setting should only be enabled for trusted agents, as it allows the manager to execute arbitrary commands on the endpoint.
More about log collection: Wazuh Log Data Collection
Troubleshooting
Command Does Not Execute
- Verify the command path is correct and the file has execute permissions
- Confirm
<disabled>is set tono - Check
/var/ossec/logs/ossec.logfor module errors - For remote commands, ensure
wazuh_command.remote_commands=1is enabled
Output Does Not Appear in Alerts
- Verify
<ignore_output>is not set toyes - Confirm rules exist that match the output format
- Check the
<tag>value - it is used for identification in rules - For
check_diff, ensure the command has executed at least twice
Execution Timeout
- Increase the
<timeout>value for long-running operations - Verify the command does not hang without a terminal (TTY)
- Add stderr redirection:
command 2>/dev/null
Hash Verification Fails
- Recalculate the file hash:
sha256sum /path/to/script - Update the
<verify_sha256>value in the configuration - Temporarily set
<skip_verification>yes</skip_verification>for debugging
More about architecture: Wazuh Architecture
More about use cases: Wazuh Use Cases