File Integrity Monitoring (FIM) in Wazuh 4.14

The File Integrity Monitoring (FIM) module in Wazuh is implemented through the syscheck component. It detects changes to files, directories, and Windows Registry entries by computing cryptographic hashes and storing file attributes, then comparing the current state against a baseline on every scan. Any deviation produces an alert containing detailed change information.

How It Works

FIM performs two core functions:

  1. Baseline scan - on the initial run, the module captures a snapshot of monitored files (hashes, sizes, permissions, owners, timestamps) and stores it in the agent’s local database.
  2. Differential analysis - on each subsequent scan or in real time, the module compares the current file state against the baseline and generates alerts when discrepancies are found.

The event processing flow:

Agent (syscheck) -> Change detected -> Sent to server ->
-> Decoding -> Rule matching -> Alert -> Indexer

Configuring syscheck in ossec.conf

The primary FIM configuration resides in the <syscheck> block of /var/ossec/etc/ossec.conf on the agent side. The module can also be configured centrally through agent.conf on the server.

Basic Configuration

<syscheck>
  <disabled>no</disabled>
  <frequency>43200</frequency>
  <scan_on_start>yes</scan_on_start>
  <alert_new_files>yes</alert_new_files>

  <!-- Directories to monitor -->
  <directories check_all="yes">/etc,/usr/bin,/usr/sbin</directories>
  <directories check_all="yes">/boot</directories>

  <!-- Exclusions -->
  <ignore>/etc/mtab</ignore>
  <ignore>/etc/hosts.deny</ignore>
  <ignore>/etc/mail/statistics</ignore>
  <ignore>/etc/random-seed</ignore>
  <ignore>/etc/adjtime</ignore>
  <ignore>/etc/httpd/logs</ignore>
  <ignore>/etc/utmpx</ignore>
  <ignore>/etc/cups/certs</ignore>
  <ignore>/etc/dumpdates</ignore>
  <ignore>/etc/svc/volatile</ignore>

  <!-- Monitored file limit -->
  <file_limit>
    <enabled>yes</enabled>
    <entries>100000</entries>
  </file_limit>
</syscheck>

The frequency Parameter

The <frequency> parameter sets the interval between scheduled scans in seconds. The default value is 43200 seconds (12 hours).

<frequency>43200</frequency>   <!-- 12 hours (default) -->
<frequency>3600</frequency>    <!-- 1 hour -->
<frequency>86400</frequency>   <!-- 24 hours -->

For critical systems, combining scheduled scans with real-time monitoring (realtime) or extended auditing (whodata) is recommended.

The directories Element Attributes

The <directories> element specifies which directories and files to monitor. Each element accepts a set of attributes that control monitoring behavior.

realtime - Real-Time Monitoring

Setting realtime="yes" enables continuous monitoring via inotify (Linux) or ReadDirectoryChangesW (Windows). Alerts are generated immediately upon detecting a change, without waiting for the next scheduled scan.

<directories realtime="yes">/etc/ssh</directories>
<directories realtime="yes">/var/www/html</directories>

Limitations:

  • On Linux, the number of inotify watches is constrained by the kernel parameter fs.inotify.max_user_watches (default: 8192).
  • Real-time monitoring applies to files in the specified directory but does not automatically cover subdirectories unless recursion_level is set.

whodata - Extended Auditing

Setting whodata="yes" enriches monitoring data with information about who made the change and which process performed it. This mode automatically enables realtime.

<directories whodata="yes">/etc</directories>
<directories whodata="yes">/usr/bin</directories>

On Linux, whodata leverages the audit subsystem (auditd). Wazuh automatically creates audit rules for monitored directories. Requirements:

  • The auditd daemon must be installed and running
  • The auditctl utility must be available
  • Sufficient audit backlog slots must be configured

On Windows, whodata relies on the Windows Security Audit Policy. Object access auditing must be enabled through Group Policy or auditpol.

check_all - Comprehensive Checks

Setting check_all="yes" activates all available checks simultaneously: hashes (MD5, SHA-1, SHA-256), size, owner, group, permissions, modification time, and inode.

<directories check_all="yes">/etc/ssh</directories>

This is equivalent to setting all of the following attributes to yes:

AttributeDescription
check_md5sumMD5 hash verification
check_sha1sumSHA-1 hash verification
check_sha256sumSHA-256 hash verification
check_sizeFile size check
check_ownerFile owner check
check_groupGroup owner check
check_permPermission check
check_mtimeModification time check
check_inodeInode check (UNIX only)

report_changes - Content Diff Reporting

Setting report_changes="yes" enables saving the diff between the previous and current versions of a file. This works with text files only.

<directories report_changes="yes" check_all="yes">/etc/ssh/sshd_config</directories>

The diff_size_limit parameter restricts the maximum file size for diff computation:

<directories report_changes="yes" diff_size_limit="5MB">/etc</directories>

Additional Attributes

<!-- Limit recursion depth -->
<directories recursion_level="3" check_all="yes">/var/log</directories>

<!-- Filter by filename pattern -->
<directories restrict="\.conf$" check_all="yes">/etc</directories>

<!-- Tag alerts -->
<directories tags="web,production" check_all="yes">/var/www</directories>

<!-- Follow symbolic links -->
<directories follow_symbolic_link="yes">/opt/app/config</directories>

Combined Example

<directories whodata="yes" report_changes="yes" check_all="yes"
             tags="critical-config" restrict="\.conf$|\.yml$"
             recursion_level="5" diff_size_limit="2MB">/etc</directories>

Monitoring Exclusions

The ignore Element

Excludes files and directories from monitoring. Supports exact path matching and regular expressions.

<!-- Exact path match -->
<ignore>/etc/mtab</ignore>
<ignore>/etc/resolv.conf</ignore>

<!-- Regular expression -->
<ignore type="sregex">^/proc</ignore>
<ignore type="sregex">\.swp$</ignore>
<ignore type="sregex">/\.git/</ignore>

The nodiff Element

Excludes file content from diff computation (when report_changes="yes" is active) while continuing to track metadata. Use this for files containing sensitive data.

<nodiff>/etc/shadow</nodiff>
<nodiff>/etc/ssl/private</nodiff>
<nodiff type="sregex">\.key$</nodiff>

Windows Registry Monitoring

FIM supports monitoring Windows Registry keys and values through the <windows_registry> element.

<windows_registry arch="both" check_all="yes">
  HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
</windows_registry>

<windows_registry arch="both" check_all="yes" report_changes="yes">
  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
</windows_registry>

<windows_registry arch="64bit" check_all="yes" whodata="yes">
  HKEY_LOCAL_MACHINE\SOFTWARE\Policies
</windows_registry>

windows_registry Attributes

AttributeDescription
archRegistry architecture: 32bit, 64bit, or both
check_allAll attribute checks
check_sumHash verification for values
report_changesReport value changes
restrict_keyKey name filter (sregex)
restrict_valueValue name filter (sregex)
check_typeTrack value type changes
recursion_levelKey nesting depth (up to 512)

Registry Exclusions

<registry_ignore>HKEY_LOCAL_MACHINE\Security\Policy\Secrets</registry_ignore>
<registry_ignore type="sregex">Enum$</registry_ignore>

Registry Entry Limit

<registry_limit>
  <enabled>yes</enabled>
  <entries>100000</entries>
</registry_limit>

FIM Alert Examples

File Modification (JSON)

{
  "timestamp": "2024-11-15T10:23:45.000+0000",
  "rule": {
    "level": 7,
    "description": "Integrity checksum changed.",
    "id": "550",
    "groups": ["ossec", "syscheck", "syscheck_entry_modified"]
  },
  "agent": {
    "id": "001",
    "name": "web-server-01"
  },
  "syscheck": {
    "path": "/etc/ssh/sshd_config",
    "event": "modified",
    "changed_attributes": ["size", "md5", "sha1", "sha256", "mtime"],
    "size_before": "3297",
    "size_after": "3342",
    "md5_before": "a1b2c3d4e5f6...",
    "md5_after": "f6e5d4c3b2a1...",
    "sha256_before": "abc123...",
    "sha256_after": "def456...",
    "mtime_before": "2024-10-01T08:00:00",
    "mtime_after": "2024-11-15T10:23:40",
    "perm_before": "rw-r--r--",
    "perm_after": "rw-r--r--"
  }
}

Whodata Alert with Audit Information

{
  "rule": {
    "level": 7,
    "description": "Integrity checksum changed.",
    "id": "550"
  },
  "syscheck": {
    "path": "/etc/passwd",
    "event": "modified",
    "changed_attributes": ["size", "md5", "sha1", "sha256"],
    "audit": {
      "user": {
        "id": "0",
        "name": "root"
      },
      "group": {
        "id": "0",
        "name": "root"
      },
      "process": {
        "id": "12345",
        "name": "/usr/sbin/useradd",
        "ppid": "11000"
      },
      "effective_user": {
        "id": "0",
        "name": "root"
      }
    }
  }
}

New File Created

{
  "rule": {
    "level": 5,
    "description": "File added to the system.",
    "id": "554",
    "groups": ["ossec", "syscheck", "syscheck_entry_added"]
  },
  "syscheck": {
    "path": "/usr/bin/suspicious_binary",
    "event": "added",
    "size_after": "45678",
    "md5_after": "abc123def456...",
    "sha256_after": "789xyz...",
    "perm_after": "rwxr-xr-x",
    "uid_after": "0",
    "gid_after": "0"
  }
}

File Deleted

{
  "rule": {
    "level": 7,
    "description": "File was deleted.",
    "id": "553",
    "groups": ["ossec", "syscheck", "syscheck_entry_deleted"]
  },
  "syscheck": {
    "path": "/etc/cron.d/backup_job",
    "event": "deleted"
  }
}

Custom FIM Rules

The built-in FIM rules (IDs 550-554) can be extended with custom rules for specific detection scenarios.

Permission Change on a Script

<rule id="100002" level="8">
  <if_sid>550</if_sid>
  <field name="file">\.sh$</field>
  <field name="changed_fields">^permission$</field>
  <description>Execute permission added to shell script.</description>
  <group>syscheck,pci_dss_11.5,</group>
</rule>

Critical File Modification

<rule id="100005" level="12">
  <if_sid>550</if_sid>
  <field name="file">/etc/shadow</field>
  <description>Critical system file /etc/shadow was modified.</description>
  <mitre>
    <id>T1003</id>
  </mitre>
  <group>syscheck,authentication_modified,</group>
</rule>

File Deleted by a Process

<rule id="100003" level="8">
  <if_sid>553</if_sid>
  <field name="audit.process.name">rm$</field>
  <description>File deleted using rm command.</description>
  <group>syscheck,file_deletion,</group>
</rule>

FIM Dashboard in Wazuh

The File Integrity Monitoring dashboard in Wazuh Dashboard provides visualization of FIM events:

  • Event overview - counts of added, modified, and deleted files over time
  • Top agents - agents with the highest number of changes
  • Top files - most frequently changed files
  • Timeline - chronological view of FIM events
  • Detailed view - diff content for files with report_changes enabled
  • Filtering - by agent, file path, event type, and time range

Access the dashboard at: Wazuh Dashboard - Modules - Integrity Monitoring.

FIM Synchronization

The <synchronization> block controls how FIM data is synchronized between agent and server.

<synchronization>
  <enabled>yes</enabled>
  <interval>5m</interval>
  <max_interval>1h</max_interval>
  <response_timeout>30</response_timeout>
  <queue_size>16384</queue_size>
  <thread_pool>1</thread_pool>
  <max_eps>10</max_eps>
</synchronization>
ParameterDescriptionDefault
intervalSynchronization interval5m
max_intervalMaximum interval when no changes occur1h
response_timeoutResponse wait timeout30s
queue_sizeSynchronization queue size16384
max_epsMaximum events per second10

Comparison with Alternative Solutions

FeatureWazuh FIMOSSEC FIMTripwireAIDE
Real-time monitoringYes (inotify, whodata)Yes (inotify)Yes (commercial edition)No (scheduled only)
Who-data (process audit)YesNoYes (commercial)No
Windows Registry monitoringYesYes (basic)YesNo (Linux only)
Change reporting (diff)YesNoYesYes
Centralized managementYes (agent.conf)LimitedYes (commercial)No
SIEM integrationBuilt-inRequires setupRequires exportRequires export
LicenseOpen Source (GPLv2)Open Source (GPLv2)Commercial / OSSOpen Source (GPLv2)
ScalabilityUp to 100,000+ agentsUp to 10,000 agentsLicense-dependentLocal per host

Wazuh FIM distinguishes itself from OSSEC through whodata support, enhanced Registry monitoring attributes, and native integration with OpenSearch for data storage and visualization.

Troubleshooting

FIM Alerts Not Generating

  1. Verify that the syscheck module is not disabled:
<syscheck>
  <disabled>no</disabled>
</syscheck>
  1. Confirm that the target directory is listed in the configuration:
grep -A5 '<directories' /var/ossec/etc/ossec.conf
  1. Check the last scan status:
/var/ossec/bin/agent_control -i 001 | grep syscheck
  1. Trigger a manual scan:
/var/ossec/bin/agent_control -r -u 001
  1. Review the agent logs:
tail -100 /var/ossec/logs/ossec.log | grep syscheck

Too Many Alerts

  1. Use <ignore> to exclude frequently changing files:
<ignore>/var/log/lastlog</ignore>
<ignore type="sregex">\.tmp$</ignore>
  1. Enable auto_ignore for automatic suppression:
<auto_ignore frequency="10" timeframe="3600">yes</auto_ignore>

Files changing more than 10 times within 3600 seconds will be excluded automatically.

  1. Increase the scan interval:
<frequency>86400</frequency>

Performance Impact

  1. Limit recursion depth:
<directories recursion_level="3" check_all="yes">/var</directories>
  1. Restrict the number of monitored files:
<file_limit>
  <enabled>yes</enabled>
  <entries>50000</entries>
</file_limit>
  1. Configure max_eps to throttle the event stream:
<synchronization>
  <max_eps>5</max_eps>
</synchronization>
  1. Use scan_time to schedule scans during off-peak hours:
<scan_time>03:00</scan_time>

Whodata Not Working on Linux

  1. Check that auditd is installed and running:
systemctl status auditd
  1. Verify that audit rules are in place:
auditctl -l | grep wazuh
  1. Check the audit backlog size:
auditctl -s | grep backlog

If whodata cannot initialize, the module automatically falls back to realtime mode.

Related Sections

Last updated on