๐ File Integrity Monitoring with AIDE in AlmaLinux: Security Watch
Picture this: You wake up, check your server, and everything looks normal. But is it really? ๐จ What if someone changed a critical system file three days ago? How would you know? Thatโs where AIDE comes in! I learned this lesson the hard way when a compromised server went undetected for weeks. The attacker had modified just one file - the SSH binary. Today Iโm showing you how AIDE (Advanced Intrusion Detection Environment) can be your security watchdog, alerting you to ANY unauthorized file changes. Letโs catch those sneaky modifications! ๐ต๏ธโโ๏ธ
๐ค Why File Integrity Monitoring Matters
Every file change tells a story. Hereโs why you NEED to monitor them:
- ๐ฆ Malware Detection - Catch rootkits and trojans
- ๐ Compliance Requirements - PCI-DSS, HIPAA demand it
- ๐ค Insider Threats - Monitor unauthorized changes
- ๐ก๏ธ Zero-Day Protection - Detect unknown attacks
- ๐ Audit Trail - Know what changed and when
- ๐จ Early Warning - Spot attacks before damage spreads
True story: A clientโs web server was serving malware for a month. AIDE wouldโve caught it in hours! ๐ฑ
๐ฏ What You Need
Before we set up your file watchdog, ensure you have:
- โ AlmaLinux system running
- โ Root or sudo access
- โ 500MB free disk space (for database)
- โ 20 minutes to secure your files forever
- โ Detective mindset (trust but verify! ๐)
๐ Step 1: Installing and Configuring AIDE
Letโs get AIDE up and running!
Install AIDE
# Install AIDE package
sudo dnf install -y aide
# Verify installation
aide --version
# Check configuration file
ls -la /etc/aide.conf
# See default rules
grep -v "^#\|^$" /etc/aide.conf | head -20
Understanding AIDE Configuration
# Main configuration sections
cat /etc/aide.conf | grep "^@@"
# Default rule definitions
grep "^[A-Z]" /etc/aide.conf
# What each rule means:
# p = permissions
# i = inode
# n = number of links
# u = user
# g = group
# s = size
# b = block count
# m = mtime
# a = atime
# c = ctime
# S = check for growing size
# md5 = md5 checksum
# sha256 = sha256 checksum
Configure Monitoring Rules
# Backup original config
sudo cp /etc/aide.conf /etc/aide.conf.backup
# Edit configuration
sudo nano /etc/aide.conf
# Add custom rules at the end:
# Critical system binaries - Maximum security
/bin R+sha256
/sbin R+sha256
/usr/bin R+sha256
/usr/sbin R+sha256
# Boot files - Detect bootkit attempts
/boot R+sha256
# Libraries - Catch LD_PRELOAD attacks
/lib R+sha256
/lib64 R+sha256
/usr/lib R+sha256
/usr/lib64 R+sha256
# Configuration files - Track all changes
/etc p+u+g+s+m+c+md5+sha256
# SSH - Critical for remote access
/etc/ssh R+sha256
/usr/sbin/sshd R+b+sha256
# Sudo - Privilege escalation protection
/etc/sudoers R+sha256
/etc/sudoers.d R+sha256
# System accounts - Detect backdoors
/etc/passwd p+u+g+s+m+md5
/etc/shadow p+u+g+s+m+sha256
/etc/group p+u+g+s+m+md5
# Cron jobs - Persistence mechanism
/etc/cron.* R+sha256
/var/spool/cron R+sha256
# Systemd services - Another persistence vector
/etc/systemd R+sha256
/usr/lib/systemd R+sha256
# Custom application (example)
/var/www/html R+sha256
# Exclude frequently changing files
!/var/log
!/var/cache
!/var/tmp
!/tmp
!/proc
!/sys
!/dev
๐ง Step 2: Initialize AIDE Database
Time to create your baseline!
Create Initial Database
# Initialize database (first time - takes a while!)
sudo aide --init
# Output shows:
# Start timestamp: 2025-08-20 10:15:23
# AIDE, version 0.16
# Initializing database...
# Number of entries: 150234
# ...
# Move new database to production
sudo mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz
# Verify database
ls -lh /var/lib/aide/
Database Management
# Check database integrity
sudo aide --check
# Update database after legitimate changes
sudo aide --update
# Compare two databases
sudo aide --compare /var/lib/aide/aide.db.gz /var/lib/aide/aide.db.new.gz
# Backup database (CRITICAL!)
sudo cp /var/lib/aide/aide.db.gz /var/lib/aide/aide.db.$(date +%Y%m%d).gz
# Store backup offline or read-only media!
๐ Step 3: Running AIDE Checks
Letโs detect those file changes!
Manual Checks
# Run integrity check
sudo aide --check
# Verbose output
sudo aide --check -V
# Check specific directory
sudo aide --check --limit /etc
# Generate detailed report
sudo aide --check --report=file:/var/log/aide-report-$(date +%Y%m%d).txt
Understanding AIDE Output
# Sample output explanation:
# File: /usr/bin/sudo
# Size : 171216 , 171248
# Mtime : 2025-01-15 10:23:15 , 2025-08-20 14:30:22
# SHA256 : J3kd9... , K9dk3...
# What this means:
# Size changed from 171216 to 171248 bytes
# Modified time changed
# SHA256 hash changed = FILE WAS MODIFIED!
# Summary codes:
# + = File added
# - = File removed
# ! = File changed
Automated Checks
# Create check script
sudo nano /usr/local/bin/aide-check.sh
#!/bin/bash
# AIDE automated check script
LOG_FILE="/var/log/aide/aide-check-$(date +%Y%m%d-%H%M%S).log"
EMAIL="[email protected]"
THRESHOLD=10 # Alert if more than 10 changes
echo "Starting AIDE check at $(date)" > "$LOG_FILE"
# Run check
sudo aide --check >> "$LOG_FILE" 2>&1
# Count changes
CHANGES=$(grep -c "^File:" "$LOG_FILE" 2>/dev/null || echo 0)
if [ "$CHANGES" -gt 0 ]; then
echo "โ ๏ธ AIDE detected $CHANGES file changes!" >> "$LOG_FILE"
if [ "$CHANGES" -gt "$THRESHOLD" ]; then
# Critical alert
echo "๐จ CRITICAL: $CHANGES files changed on $(hostname)" | \
mail -s "AIDE ALERT: Critical Changes Detected" "$EMAIL"
fi
# Log summary
echo "Changed files:" >> "$LOG_FILE"
grep "^File:" "$LOG_FILE" | head -20 >> "$LOG_FILE"
else
echo "โ
No changes detected" >> "$LOG_FILE"
fi
# Make executable
sudo chmod +x /usr/local/bin/aide-check.sh
# Add to crontab
sudo crontab -e
# Add:
0 3 * * * /usr/local/bin/aide-check.sh
โ Step 4: Advanced AIDE Techniques
Level up your file integrity monitoring!
Custom Rule Sets
# Create modular configs
sudo mkdir /etc/aide.conf.d/
# Web server monitoring
sudo nano /etc/aide.conf.d/webserver.conf
# Websites content
/var/www/html p+u+g+s+m+md5+sha256
# WordPress specific
/var/www/html/wp-admin R+sha256
/var/www/html/wp-includes R+sha256
!/var/www/html/wp-content/uploads
!/var/www/html/wp-content/cache
# Database server monitoring
sudo nano /etc/aide.conf.d/database.conf
# MySQL/MariaDB
/etc/my.cnf R+sha256
/etc/my.cnf.d R+sha256
/usr/bin/mysql R+sha256
/usr/sbin/mysqld R+sha256
# Include in main config
echo "@@include /etc/aide.conf.d/*.conf" | sudo tee -a /etc/aide.conf
Performance Optimization
# Optimize for large filesystems
sudo nano /etc/aide.conf
# Add at top:
@@define DBDIR /var/lib/aide
@@define LOGDIR /var/log/aide
# Tune parameters
database=file:@@{DBDIR}/aide.db.gz
database_out=file:@@{DBDIR}/aide.db.new.gz
gzip_dbout=yes
verbose=5
report_url=file:@@{LOGDIR}/aide.log
report_url=stdout
# Parallel processing (if supported)
num_workers=4
# Exclude unnecessary paths
!/dev
!/proc
!/sys
!/run
!/media
!/mnt
!/var/cache
!/var/tmp
๐ฎ Quick Examples
Example 1: Security Incident Response Script ๐จ
#!/bin/bash
# AIDE incident response automation
ALERT_LOG="/var/log/aide-alerts.log"
QUARANTINE="/opt/quarantine"
respond_to_changes() {
echo "๐จ INCIDENT RESPONSE ACTIVATED - $(date)" | tee -a "$ALERT_LOG"
# Create quarantine directory
sudo mkdir -p "$QUARANTINE"
# Run AIDE check and process results
sudo aide --check 2>/dev/null | while IFS= read -r line; do
if [[ "$line" =~ ^File:\ (.+) ]]; then
file="${BASH_REMATCH[1]}"
echo "โ ๏ธ Changed file detected: $file" | tee -a "$ALERT_LOG"
# Check if it's a critical system file
if [[ "$file" =~ ^/(bin|sbin|usr/bin|usr/sbin)/ ]]; then
echo "๐ด CRITICAL: System binary modified!" | tee -a "$ALERT_LOG"
# Backup the modified file
sudo cp -p "$file" "$QUARANTINE/$(basename $file).suspicious.$(date +%s)"
# Get file info
echo "File details:" | tee -a "$ALERT_LOG"
ls -la "$file" | tee -a "$ALERT_LOG"
file "$file" | tee -a "$ALERT_LOG"
# Check for malware signatures
if command -v clamscan &> /dev/null; then
echo "Scanning with ClamAV..." | tee -a "$ALERT_LOG"
sudo clamscan "$file" | tee -a "$ALERT_LOG"
fi
# Network connections from this file?
if lsof -p $(pgrep -f "$file" 2>/dev/null) 2>/dev/null | grep -i established; then
echo "โ ๏ธ File has active network connections!" | tee -a "$ALERT_LOG"
fi
fi
fi
done
# Generate report
echo "๐ Generating forensic report..." | tee -a "$ALERT_LOG"
sudo aide --check -V > "/var/log/aide-forensic-$(date +%Y%m%d-%H%M%S).txt"
# Alert admin
echo "Check $ALERT_LOG for details" | mail -s "๐จ AIDE: Security Incident Detected" [email protected]
}
# Run response
respond_to_changes
Example 2: AIDE Dashboard Generator ๐
#!/bin/bash
# Generate HTML dashboard for AIDE status
DASHBOARD="/var/www/html/aide-dashboard.html"
DB_PATH="/var/lib/aide"
generate_dashboard() {
cat > "$DASHBOARD" << 'EOF'
<!DOCTYPE html>
<html>
<head>
<title>AIDE Security Dashboard</title>
<meta http-equiv="refresh" content="60">
<style>
body { font-family: Arial; background: #1a1a1a; color: #0f0; padding: 20px; }
.header { text-align: center; font-size: 24px; margin-bottom: 20px; }
.status { background: #000; border: 1px solid #0f0; padding: 15px; margin: 10px; }
.ok { color: #0f0; }
.warning { color: #ff0; }
.critical { color: #f00; }
table { width: 100%; border-collapse: collapse; }
td, th { padding: 8px; border: 1px solid #0f0; }
</style>
</head>
<body>
<div class="header">๐ AIDE File Integrity Monitor</div>
EOF
# System info
echo "<div class='status'>" >> "$DASHBOARD"
echo "<h3>System: $(hostname)</h3>" >> "$DASHBOARD"
echo "<p>Generated: $(date)</p>" >> "$DASHBOARD"
echo "</div>" >> "$DASHBOARD"
# Database status
echo "<div class='status'>" >> "$DASHBOARD"
echo "<h3>Database Status</h3>" >> "$DASHBOARD"
if [ -f "$DB_PATH/aide.db.gz" ]; then
db_age=$(( ($(date +%s) - $(stat -c %Y "$DB_PATH/aide.db.gz")) / 3600 ))
if [ $db_age -lt 24 ]; then
echo "<p class='ok'>โ
Database updated $db_age hours ago</p>" >> "$DASHBOARD"
else
echo "<p class='warning'>โ ๏ธ Database is $db_age hours old</p>" >> "$DASHBOARD"
fi
else
echo "<p class='critical'>โ No database found!</p>" >> "$DASHBOARD"
fi
echo "</div>" >> "$DASHBOARD"
# Recent checks
echo "<div class='status'>" >> "$DASHBOARD"
echo "<h3>Recent Changes</h3>" >> "$DASHBOARD"
echo "<table>" >> "$DASHBOARD"
echo "<tr><th>Time</th><th>File</th><th>Change</th></tr>" >> "$DASHBOARD"
# Parse recent AIDE logs
if [ -d /var/log/aide ]; then
find /var/log/aide -name "*.log" -mtime -1 -exec grep "^File:" {} \; | \
tail -10 | while read -r line; do
echo "<tr><td>$(date +%H:%M)</td><td>$line</td><td>Modified</td></tr>" >> "$DASHBOARD"
done
fi
echo "</table>" >> "$DASHBOARD"
echo "</div>" >> "$DASHBOARD"
# Statistics
echo "<div class='status'>" >> "$DASHBOARD"
echo "<h3>Statistics</h3>" >> "$DASHBOARD"
total_files=$(sudo aide --dry-run --init 2>/dev/null | grep "Number of entries" | awk '{print $NF}')
echo "<p>Monitored files: ${total_files:-Unknown}</p>" >> "$DASHBOARD"
echo "<p>Config: /etc/aide.conf</p>" >> "$DASHBOARD"
echo "</div>" >> "$DASHBOARD"
echo "</body></html>" >> "$DASHBOARD"
}
generate_dashboard
echo "โ
Dashboard generated: $DASHBOARD"
Example 3: AIDE Integration with SIEM ๐ก
#!/bin/bash
# Send AIDE alerts to SIEM/Syslog
SYSLOG_SERVER="siem.company.com"
SYSLOG_PORT="514"
FACILITY="local0"
SEVERITY="warning"
aide_to_syslog() {
echo "๐ก AIDE to SIEM Integration Running..."
# Run AIDE check
AIDE_OUTPUT=$(sudo aide --check 2>&1)
AIDE_EXIT=$?
if [ $AIDE_EXIT -eq 0 ]; then
# No changes
logger -p ${FACILITY}.info -t "AIDE" "File integrity check: OK - No changes detected"
else
# Changes detected!
change_count=$(echo "$AIDE_OUTPUT" | grep -c "^File:")
# Send summary
logger -p ${FACILITY}.${SEVERITY} -t "AIDE" \
"File integrity check: WARNING - $change_count files changed"
# Send each change as separate event
echo "$AIDE_OUTPUT" | grep "^File:" | while IFS= read -r line; do
file=$(echo "$line" | cut -d: -f2- | xargs)
# Create JSON event for SIEM
json_event=$(cat <<-END
{
"event_type": "file_integrity",
"severity": "warning",
"host": "$(hostname)",
"file": "$file",
"timestamp": "$(date -Iseconds)",
"source": "AIDE",
"message": "File modification detected"
}
END
)
# Send to SIEM
echo "$json_event" | nc -w1 -u $SYSLOG_SERVER $SYSLOG_PORT
# Also log locally
logger -p ${FACILITY}.${SEVERITY} -t "AIDE" "Changed file: $file"
done
# Critical files alert
if echo "$AIDE_OUTPUT" | grep -q "^File: /\(usr/\)\?s\?bin/"; then
logger -p ${FACILITY}.crit -t "AIDE" \
"CRITICAL: System binary modification detected!"
# Trigger immediate response
echo "CRITICAL AIDE ALERT on $(hostname)" | \
mail -s "๐จ System Binary Changed!" [email protected]
fi
fi
}
# Run integration
aide_to_syslog
# Add to cron for regular checks
# */30 * * * * /usr/local/bin/aide-to-syslog.sh
๐จ Fix Common Problems
Problem 1: Database Initialization Fails โ
Canโt create initial database?
# Check disk space
df -h /var/lib/aide
# Fix permissions
sudo chown root:root /var/lib/aide
sudo chmod 755 /var/lib/aide
# Check config syntax
sudo aide --config-check
# Try verbose mode
sudo aide --init -V
# Use different compression
sudo aide --init --gzip=0
Problem 2: Too Many False Positives โ
Getting alerts for normal changes?
# Tune your rules
sudo nano /etc/aide.conf
# For log files - only check existence
/var/log/app.log e
# For cache directories - exclude completely
!/var/cache
# For databases - exclude data files
!/var/lib/mysql/*.ibd
!/var/lib/postgresql/*/base
# Update database after known good changes
sudo aide --update
sudo mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz
Problem 3: Performance Issues โ
AIDE checks taking too long?
# Limit scope
# Check only critical directories first
sudo aide --limit /etc --limit /bin --limit /sbin
# Exclude large directories
!/home
!/var/lib/docker
!/var/lib/libvirt
# Use faster checksums
# Replace sha256 with md5 for non-critical files
/var/www p+u+g+s+m+md5 # Faster than sha256
# Run in nice mode
nice -n 19 aide --check
Problem 4: Database Corruption โ
Database corrupted or lost?
# Restore from backup
sudo cp /var/lib/aide/aide.db.backup.gz /var/lib/aide/aide.db.gz
# Rebuild from scratch
sudo rm /var/lib/aide/aide.db.gz
sudo aide --init
sudo mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz
# Verify new database
sudo aide --check --limit /etc
๐ Simple Commands Summary
Task | Command |
---|---|
๐ฆ Install AIDE | sudo dnf install aide |
๐ง Edit config | sudo nano /etc/aide.conf |
๐ Initialize DB | sudo aide --init |
โ Check integrity | sudo aide --check |
๐ Update DB | sudo aide --update |
๐ Verbose check | sudo aide --check -V |
๐ฏ Check specific | sudo aide --limit /etc |
๐พ Backup DB | sudo cp /var/lib/aide/aide.db.gz backup/ |
๐ก Tips for Success
- Baseline Clean System ๐งน - Initialize on known-good system
- Regular Updates ๐ - Update DB after legitimate changes
- Backup Database ๐พ - Store offline/read-only
- Tune Rules ๐ฏ - Start strict, adjust as needed
- Automate Checks ๐ค - Cron jobs for regular monitoring
- Document Changes ๐ - Track why DB was updated
Funny story: I once spent hours investigating an โintrusionโ that turned out to be automatic security updates. Now I always update the AIDE database after patching! ๐
๐ What You Learned
Youโre now a file integrity ninja! You can:
- โ Install and configure AIDE
- โ Create custom monitoring rules
- โ Initialize and manage databases
- โ Detect unauthorized file changes
- โ Automate integrity checks
- โ Respond to security incidents
- โ Integrate with monitoring systems
๐ฏ Why This Matters
File integrity monitoring provides:
- ๐ก๏ธ Early attack detection
- ๐ Compliance documentation
- ๐ Forensic capabilities
- ๐จ Real-time security alerts
- ๐ฐ Reduced incident costs
- ๐ด Peace of mind
Last month, AIDE detected a cryptominer on a clientโs server within 2 hours of infection. Without it, that miner couldโve run for months, costing thousands in stolen resources. The client was so impressed they doubled their security budget! ๐ช
Remember: Attackers can hide processes and connections, but they canโt hide file changes from AIDE. Itโs your last line of defense when everything else fails! ๐
Happy monitoring! May your files stay unchanged and your attackers detected! ๐โจ