Configuring File Integrity Monitoring on Linux with AIDE: Detect System Tampering Early

Security tutorial - IT technology blog
Security tutorial - IT technology blog

The Silent Intrusion Problem

Picture this: you log into your monitoring dashboard on a Monday morning and notice steady 15 Mbps outbound traffic from an internal database server. Authentication logs show zero failed SSH attempts.

Your perimeter firewalls report nothing out of the ordinary. Yet after half a day of forensics, the ugly truth emerges. An attacker leveraged an unpatched Redis instance three weeks ago, swapped /usr/sbin/sshd with a 1.2 MB trojanized binary, and added a single stealthy line to /etc/pam.d/common-auth to harvest cleartext passwords into /var/tmp/.pam_cache.

Perimeter defenses stop outside noise, but once an intruder establishes a foothold, persistence is step one. Attackers modify system binaries, slip jobs into /etc/cron.d/, plant kernel modules, or edit daemon configs. Standard monitoring tools tracking CPU spikes, disk fill rates, and listening ports will miss these subtle filesystem edits entirely. You need a dedicated guard that answers one blunt question: has any critical file changed since the last known good state?

Core Concepts: How AIDE Tracks File Integrity

File Integrity Monitoring (FIM) validates system and application files against an authoritative cryptographic snapshot. While modern EDR agents run heavy userland hooks, AIDE (Advanced Intrusion Detection Environment) remains the battle-tested, lightweight standard for Unix host integrity. It runs cleanly, leaves a tiny footprint, and requires no persistent background daemon.

AIDE relies on a straightforward snapshot-and-compare model:

  • Baseline Generation: During setup, AIDE indexes directories defined in its configuration. It records file sizes, POSIX permissions, ownership (UID/GID), inode numbers, modification timestamps (mtime), change timestamps (ctime), and cryptographic hashes (SHA-256 and SHA-512). It then writes these records to a fresh baseline file: aide.db.new (or aide.db.new.gz).
  • Database Activation: You promote this snapshot to the active database (aide.db). This file becomes your single source of truth.
  • Integrity Verification: In check mode (aide --check), AIDE rescans your filesystem, recalculates attributes on the fly, and flags any deviation against the trusted database. The resulting report pinpoints exactly what changed—whether an attacker dropped a new library, removed an audit log, or modified a hash.

Hands-on Practice: Deploying and Configuring AIDE

Step 1: Installing AIDE

AIDE lives in the standard repositories of every major distribution.

On Debian 12 and Ubuntu 22.04/24.04:

sudo apt update
sudo apt install -y aide aide-common

On RHEL 9, Rocky Linux, or AlmaLinux:

sudo dnf install -y aide

Step 2: Defining Inspection Rules in aide.conf

The primary configuration file lives at /etc/aide/aide.conf on Debian-based distros, or /etc/aide.conf on RHEL. Debian systems can also assemble rules from snippets in /etc/aide/aide.conf.d/, but the core syntax is identical across all platforms.

Before locking down file paths, ensure your management credentials are solid. When provisioning cloud instances or setting root passwords, using a client-side utility like the password generator at toolcraft.app/en/tools/security/password-generator prevents credentials from traveling over the wire. Once root credentials and SSH keys are settled, FIM becomes your next security baseline.

Open your configuration file:

sudo nano /etc/aide/aide.conf

Define custom rule macros near the top of the file. Replace legacy, collision-prone MD5 rules with modern SHA-256 and SHA-512 checks:

# Custom Rule Macros
# Track permissions, inodes, links, user, group, size, block counts, mtime, ctime, and dual SHA hashes
STRICT_SYSTEM = p+i+n+u+g+s+b+m+c+sha256+sha512
CONFIG_FILES  = p+i+n+u+g+s+m+c+sha256
STATIC_DIR    = p+i+u+g

# Critical Binaries and Shared Libraries
/bin            STRICT_SYSTEM
/sbin           STRICT_SYSTEM
/usr/bin        STRICT_SYSTEM
/usr/sbin       STRICT_SYSTEM
/lib            STRICT_SYSTEM
/lib64          STRICT_SYSTEM

# System Configuration
/etc            CONFIG_FILES

# Kernel Images and Boot Configuration
/boot           STRICT_SYSTEM

# Dynamic Files and Mount Exclusions (Prevents noise)
!/etc/mtab
!/etc/resolv.conf
!/var/log
!/var/spool
!/var/cache
!/tmp
!/proc
!/sys
!/dev

The exclamation mark (!) marks exclusions. Skipping dynamic virtual filesystems like /proc and /sys is mandatory. If you forget to prune these, routine kernel state changes and system logs will swamp your daily reports with thousands of false positives.

Step 3: Building and Activating the Baseline Database

With rules in place, initialize the reference catalog. Debian and Ubuntu ship a convenient helper script called aideinit:

sudo aideinit

On RHEL and clone distributions, invoke upstream AIDE directly:

sudo aide --init

On an SSD-backed instance with roughly 50,000 files, initialization finishes in about 20 to 45 seconds. On slower mechanical storage or systems holding millions of files, plan for 3 to 5 minutes. AIDE writes the output to /var/lib/aide/aide.db.new.gz (or an uncompressed aide.db.new on older RHEL setups).

Activate the baseline by renaming it to the production target path:

sudo cp /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz
# If your environment uses uncompressed databases:
# sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db

Step 4: Testing Tamper Detection

Never trust a security control you have not watched fail. Stage a controlled modification to confirm AIDE catches out-of-band edits.

Append a fake host record to /etc/hosts:

echo "# Malicious entry simulation" | sudo tee -a /etc/hosts

Execute an immediate verification pass:

sudo aide --check

Within seconds, AIDE flags the anomaly:

AIDE 0.17.4 found differences between database and filesystem!!

Summary:
  Total number of entries:      48215
  Added entries:                0
  Removed entries:              0
  Changed entries:              1

---------------------------------------------------
Changed entries:
---------------------------------------------------

changed: /etc/hosts

---------------------------------------------------
Detailed information about changes:
---------------------------------------------------

File: /etc/hosts
  Size     : 221                              , 252
  Mtime    : 2026-11-04 09:12:04              , 2026-11-04 10:25:31
  Ctime    : 2026-11-04 09:12:04              , 2026-11-04 10:25:31
  SHA256   : a1b2c3d4e5f6...                  , e5f6a7b8c9d0...

Notice how AIDE caught the file growth, timestamp changes, and hash mismatch. Clean up your test entry before moving forward:

sudo sed -i '/# Malicious entry simulation/d' /etc/hosts

Step 5: Automating Checks and Dispatching Alerts

Manual security audits fail the moment operations get busy. Automate your scans and route unexpected diffs straight to your operations inbox.

AIDE uses specific exit codes: 0 indicates no changes, while non-zero values signal file discrepancies or processing errors. We can leverage that in a simple monitoring wrapper.

Create a script at /usr/local/bin/aide-check.sh:

sudo nano /usr/local/bin/aide-check.sh

Paste the following logic:

#!/usr/bin/env bash
set -uo pipefail

REPORT_FILE="/tmp/aide-report.txt"
RECIPIENT="[email protected]"
HOSTNAME=$(hostname -f)

# Run AIDE check and capture output
/usr/bin/aide --check > "$REPORT_FILE" 2>&1
EXIT_CODE=$?

if [ "$EXIT_CODE" -eq 0 ]; then
    # Filesystem matches baseline
    rm -f "$REPORT_FILE"
    exit 0
else
    # Drift or tampering detected
    mail -s "ALERT: File Integrity Anomaly on ${HOSTNAME} (Code: ${EXIT_CODE})" "$RECIPIENT" < "$REPORT_FILE"
    rm -f "$REPORT_FILE"
    exit "$EXIT_CODE"
fi

Make the script executable:

sudo chmod 750 /usr/local/bin/aide-check.sh

Schedule it to trigger every morning at 03:00 UTC via cron:

echo "0 3 * * * root /usr/local/bin/aide-check.sh" | sudo tee /etc/cron.d/aide-daily

Step 6: Updating the Baseline After Maintenance

Patching packages via apt upgrade or dnf update rewrites hundreds of binaries and libraries. Running an audit right after OS patching will dump massive diffs into your mailbox.

Make baseline re-indexing an explicit final step in your deployment runbook:

# 1. Apply system updates
sudo apt upgrade -y

# 2. Rebuild the baseline against new files
sudo aide --update

# 3. Swap the updated catalog into production
sudo cp /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz

Always run aide --check before updating the baseline. Skipping this verification risks approving an undetected breach as legitimate system architecture.

Conclusion

Host-based File Integrity Monitoring turns opaque filesystem changes into hard forensic data. AIDE delivers strong visibility without high memory overhead or background CPU drain. Store an offline or read-only copy of aide.db.gz—such as in an S3 bucket with Object Lock enabled—so an attacker with root access cannot overwrite your baseline undetected. Couple that with disciplined post-patch updates, and you will know the moment an unauthorized byte lands on your disks.

Share: