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

ParameterDefaultDescription
disablednoEnable or disable the module (yes/no)
tag-Descriptive name for identifying the command in logs
command-Path to the command or script with arguments
interval2sInterval between executions (s/m/h/d/M)
run_on_startyesExecute on service startup (yes/no)
timeout0Maximum execution time in seconds (0 for unlimited)
ignore_outputnoSuppress output logging (yes/no)
verify_md5-MD5 hash for executable verification
verify_sha1-SHA1 hash for verification
verify_sha256-SHA256 hash for verification
skip_verificationnoExecute 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>
ParameterDescription
timeExecution time in hh:mm format
wdayDay of week (sunday - saturday)
dayDay 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>&amp;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=1

This 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 to no
  • Check /var/ossec/logs/ossec.log for module errors
  • For remote commands, ensure wazuh_command.remote_commands=1 is enabled

Output Does Not Appear in Alerts

  • Verify <ignore_output> is not set to yes
  • 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

Last updated on