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:
- 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.
- 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 -> IndexerConfiguring 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_levelis 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
auditddaemon must be installed and running - The
auditctlutility 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:
| Attribute | Description |
|---|---|
check_md5sum | MD5 hash verification |
check_sha1sum | SHA-1 hash verification |
check_sha256sum | SHA-256 hash verification |
check_size | File size check |
check_owner | File owner check |
check_group | Group owner check |
check_perm | Permission check |
check_mtime | Modification time check |
check_inode | Inode 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
| Attribute | Description |
|---|---|
arch | Registry architecture: 32bit, 64bit, or both |
check_all | All attribute checks |
check_sum | Hash verification for values |
report_changes | Report value changes |
restrict_key | Key name filter (sregex) |
restrict_value | Value name filter (sregex) |
check_type | Track value type changes |
recursion_level | Key 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_changesenabled - 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>| Parameter | Description | Default |
|---|---|---|
interval | Synchronization interval | 5m |
max_interval | Maximum interval when no changes occur | 1h |
response_timeout | Response wait timeout | 30s |
queue_size | Synchronization queue size | 16384 |
max_eps | Maximum events per second | 10 |
Comparison with Alternative Solutions
| Feature | Wazuh FIM | OSSEC FIM | Tripwire | AIDE |
|---|---|---|---|---|
| Real-time monitoring | Yes (inotify, whodata) | Yes (inotify) | Yes (commercial edition) | No (scheduled only) |
| Who-data (process audit) | Yes | No | Yes (commercial) | No |
| Windows Registry monitoring | Yes | Yes (basic) | Yes | No (Linux only) |
| Change reporting (diff) | Yes | No | Yes | Yes |
| Centralized management | Yes (agent.conf) | Limited | Yes (commercial) | No |
| SIEM integration | Built-in | Requires setup | Requires export | Requires export |
| License | Open Source (GPLv2) | Open Source (GPLv2) | Commercial / OSS | Open Source (GPLv2) |
| Scalability | Up to 100,000+ agents | Up to 10,000 agents | License-dependent | Local 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
- Verify that the syscheck module is not disabled:
<syscheck>
<disabled>no</disabled>
</syscheck>- Confirm that the target directory is listed in the configuration:
grep -A5 '<directories' /var/ossec/etc/ossec.conf- Check the last scan status:
/var/ossec/bin/agent_control -i 001 | grep syscheck- Trigger a manual scan:
/var/ossec/bin/agent_control -r -u 001- Review the agent logs:
tail -100 /var/ossec/logs/ossec.log | grep syscheckToo Many Alerts
- Use
<ignore>to exclude frequently changing files:
<ignore>/var/log/lastlog</ignore>
<ignore type="sregex">\.tmp$</ignore>- Enable
auto_ignorefor automatic suppression:
<auto_ignore frequency="10" timeframe="3600">yes</auto_ignore>Files changing more than 10 times within 3600 seconds will be excluded automatically.
- Increase the scan interval:
<frequency>86400</frequency>Performance Impact
- Limit recursion depth:
<directories recursion_level="3" check_all="yes">/var</directories>- Restrict the number of monitored files:
<file_limit>
<enabled>yes</enabled>
<entries>50000</entries>
</file_limit>- Configure
max_epsto throttle the event stream:
<synchronization>
<max_eps>5</max_eps>
</synchronization>- Use
scan_timeto schedule scans during off-peak hours:
<scan_time>03:00</scan_time>Whodata Not Working on Linux
- Check that auditd is installed and running:
systemctl status auditd- Verify that audit rules are in place:
auditctl -l | grep wazuh- Check the audit backlog size:
auditctl -s | grep backlogIf whodata cannot initialize, the module automatically falls back to realtime mode.
Related Sections
- Malware Detection - using FIM together with YARA and VirusTotal for malware identification
- Security Configuration Assessment - verifying system settings against security standards
- Wazuh Architecture - how FIM data flows from agent to indexer