Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-SkillsFramework mappings
MITRE ATT&CK
Overview
AIDE (Advanced Intrusion Detection Environment) is a host-based intrusion detection system that monitors file and directory integrity using cryptographic checksums. This skill covers generating AIDE configuration files, initializing baseline databases, running integrity checks, parsing change reports, and setting up automated cron-based monitoring with alerting.
When to Use
- When deploying or configuring implementing file integrity monitoring with aide capabilities in your environment
- When establishing security controls aligned to compliance requirements
- When building or improving security architecture for this domain
- When conducting security assessments that require this implementation
Prerequisites
- AIDE installed on target Linux system (apt install aide / yum install aide)
- Root or sudo access for file system scanning
- Python 3.8+ with standard library
Steps
- Generate AIDE Configuration — Create aide.conf with monitoring rules for critical directories (/etc, /bin, /sbin, /usr/bin, /boot)
- Initialize Baseline Database — Run aide --init to create the initial file integrity baseline
- Run Integrity Check — Execute aide --check to compare current state against baseline
- Parse Change Report — Extract added, removed, and changed files from AIDE output
- Configure Automated Monitoring — Generate cron job for scheduled integrity checks
- Generate Compliance Report — Produce structured report of all file changes with severity classification
Expected Output
- AIDE configuration file (aide.conf)
- Baseline database creation status
- JSON report of file changes (added/removed/changed) with severity
- Cron job configuration for automated monitoring
Source materials
References and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 1
api-reference.md2.1 KB
AIDE File Integrity Monitoring API Reference
AIDE CLI Commands
# Initialize baseline database
aide --init --config=/etc/aide/aide.conf
# Copy new database as baseline
cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db
# Run integrity check against baseline
aide --check --config=/etc/aide/aide.conf
# Update baseline with current state
aide --update --config=/etc/aide/aide.conf
# Compare two databases
aide --compare --config=/etc/aide/aide.conf
# Validate configuration syntax
aide --config-check --config=/etc/aide/aide.confConfiguration File Syntax (aide.conf)
# Database locations
database_in=file:/var/lib/aide/aide.db
database_out=file:/var/lib/aide/aide.db.new
# Report output
report_url=stdout
report_url=file:/var/log/aide/aide.log
# Gzip compression
gzip_dbout=yes
# Rule definitions
# p=permissions i=inode n=links u=user g=group s=size
# b=block_count m=mtime c=ctime sha256=SHA-256 hash
NORMAL = p+i+n+u+g+s+b+m+c+sha256
PERMS = p+i+u+g
LOG = p+u+g+i
# Monitor paths
/bin NORMAL
/sbin NORMAL
/etc PERMS
/boot NORMAL
# Exclusions (prefix with !)
!/var/log/.*
!/proc
!/sys
!/tmpAvailable Check Attributes
| Attribute | Description |
|---|---|
p |
File permissions |
i |
Inode number |
n |
Number of hard links |
u |
User ownership |
g |
Group ownership |
s |
File size |
b |
Block count |
m |
Modification time |
c |
Change time (ctime) |
sha256 |
SHA-256 hash |
sha512 |
SHA-512 hash |
md5 |
MD5 hash |
xattrs |
Extended attributes |
acl |
Access control lists |
selinux |
SELinux context |
Cron Automation
# Daily integrity check at 5 AM
0 5 * * * root /usr/bin/aide --check --config=/etc/aide/aide.conf \
| mail -s "AIDE Report" security@company.com
# Weekly baseline update
0 3 * * 0 root /usr/bin/aide --update --config=/etc/aide/aide.conf \
&& cp /var/lib/aide/aide.db.new /var/lib/aide/aide.dbInstallation
# Debian/Ubuntu
apt install aide
# RHEL/CentOS
yum install aide
# Initialize after install
aideinit # Debian wrapper
aide --init # Direct commandScripts 1
agent.py8.9 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""AIDE (Advanced Intrusion Detection Environment) configuration generator and check runner."""
import os
import json
import re
import subprocess
import argparse
from datetime import datetime
AIDE_RULE_SETS = {
"critical_binaries": {
"paths": ["/bin", "/sbin", "/usr/bin", "/usr/sbin"],
"rule": "p+i+n+u+g+s+b+m+c+sha256+xattrs",
"description": "Monitor all attributes and SHA-256 hash for system binaries",
},
"config_files": {
"paths": ["/etc"],
"rule": "p+i+u+g+sha256",
"description": "Monitor permissions, inode, ownership, and hash for config files",
},
"boot_files": {
"paths": ["/boot"],
"rule": "p+i+n+u+g+s+b+m+c+sha256",
"description": "Full attribute monitoring for boot files and kernel images",
},
"library_files": {
"paths": ["/lib", "/lib64", "/usr/lib"],
"rule": "p+i+n+u+g+s+b+sha256",
"description": "Monitor shared libraries for unauthorized modifications",
},
"log_files": {
"paths": ["/var/log"],
"rule": "p+u+g+i",
"description": "Monitor log file permissions and ownership (not content)",
},
}
AIDE_EXCLUSIONS = [
"!/var/log/.*", "!/var/spool/.*", "!/var/cache/.*",
"!/proc", "!/sys", "!/dev", "!/run", "!/tmp",
"!/var/lib/dpkg/.*", "!/var/lib/apt/.*",
]
def generate_aide_config(rule_sets=None, db_path="/var/lib/aide/aide.db",
db_new_path="/var/lib/aide/aide.db.new",
log_path="/var/log/aide/aide.log"):
"""Generate aide.conf configuration file content."""
if rule_sets is None:
rule_sets = list(AIDE_RULE_SETS.keys())
lines = [
"# AIDE Configuration - Generated by agent.py",
f"# Generated: {datetime.utcnow().isoformat()}",
"",
f"database_in=file:{db_path}",
f"database_out=file:{db_new_path}",
f"database_new=file:{db_new_path}",
"",
"# Gzip output database",
"gzip_dbout=yes",
"",
"# Report settings",
"report_url=stdout",
f"report_url=file:{log_path}",
"",
"# Rule definitions",
"NORMAL = p+i+n+u+g+s+b+m+c+sha256",
"PERMS = p+i+u+g",
"LOG = p+u+g+i",
"FULL = p+i+n+u+g+s+b+m+c+sha256+xattrs",
"",
"# Exclusions",
]
for excl in AIDE_EXCLUSIONS:
lines.append(excl)
lines.append("")
lines.append("# Monitored paths")
for rs_name in rule_sets:
rs = AIDE_RULE_SETS.get(rs_name)
if not rs:
continue
lines.append(f"# {rs['description']}")
for path in rs["paths"]:
lines.append(f"{path} {rs['rule']}")
lines.append("")
return "\n".join(lines)
def initialize_baseline():
"""Run aide --init to create the baseline database."""
result = subprocess.run(
["aide", "--init", "--config=/etc/aide/aide.conf"],
capture_output=True, text=True, timeout=600
)
if result.returncode == 0:
subprocess.run(
["cp", "/var/lib/aide/aide.db.new", "/var/lib/aide/aide.db"],
capture_output=True, text=True,
timeout=120,
)
return {"status": "success", "output": result.stdout[:500]}
return {"status": "error", "stderr": result.stderr[:500]}
def run_integrity_check():
"""Run aide --check and parse the results."""
result = subprocess.run(
["aide", "--check", "--config=/etc/aide/aide.conf"],
capture_output=True, text=True, timeout=600
)
return parse_aide_output(result.stdout, result.returncode)
def parse_aide_output(output, return_code):
"""Parse AIDE check output into structured findings."""
findings = {"added": [], "removed": [], "changed": [], "summary": {}}
section = None
for line in output.splitlines():
line = line.strip()
if "Added entries:" in line or "added:" in line.lower():
section = "added"
elif "Removed entries:" in line or "removed:" in line.lower():
section = "removed"
elif "Changed entries:" in line or "changed:" in line.lower():
section = "changed"
elif line.startswith("f") or line.startswith("d") or line.startswith("l"):
match = re.match(r"^[fdl!]\s+(.+)", line)
if match and section:
filepath = match.group(1).strip()
severity = _classify_severity(filepath, section)
findings[section].append({
"path": filepath, "severity": severity, "change_type": section,
})
elif "Number of entries" in line:
match = re.match(r"Number of entries:\s*(\d+)", line)
if match:
findings["summary"]["total_entries"] = int(match.group(1))
findings["summary"]["added_count"] = len(findings["added"])
findings["summary"]["removed_count"] = len(findings["removed"])
findings["summary"]["changed_count"] = len(findings["changed"])
findings["summary"]["return_code"] = return_code
findings["summary"]["integrity_status"] = "clean" if return_code == 0 else "changes_detected"
return findings
def _classify_severity(filepath, change_type):
"""Classify severity based on file path and change type."""
critical_paths = ["/bin/", "/sbin/", "/usr/bin/", "/usr/sbin/", "/boot/", "/etc/shadow",
"/etc/passwd", "/etc/sudoers", "/etc/ssh/"]
high_paths = ["/etc/", "/lib/", "/lib64/", "/usr/lib/"]
if change_type == "removed" and any(filepath.startswith(p) for p in critical_paths):
return "critical"
if any(filepath.startswith(p) for p in critical_paths):
return "critical" if change_type != "added" else "high"
if any(filepath.startswith(p) for p in high_paths):
return "high"
return "medium"
def generate_cron_config(schedule="0 5 * * *", email=None):
"""Generate cron job for automated AIDE integrity checks."""
cron_script = "#!/bin/bash\n"
cron_script += "# AIDE automated integrity check\n"
cron_script += "LOGFILE=/var/log/aide/aide-check-$(date +%Y%m%d).log\n"
cron_script += "aide --check --config=/etc/aide/aide.conf > $LOGFILE 2>&1\n"
cron_script += "EXIT_CODE=$?\n"
cron_script += "if [ $EXIT_CODE -ne 0 ]; then\n"
if email:
cron_script += f' mail -s "AIDE Alert: Integrity changes detected" {email} < $LOGFILE\n'
cron_script += ' logger -t aide "Integrity check found changes (exit code $EXIT_CODE)"\n'
cron_script += "fi\n"
cron_entry = f"{schedule} root /usr/local/bin/aide-check.sh"
return {"script": cron_script, "cron_entry": cron_entry, "schedule": schedule}
def generate_report(config_content, baseline_status, check_findings, cron_config):
"""Generate AIDE deployment and check report."""
return {
"report_time": datetime.utcnow().isoformat(),
"config_lines": len(config_content.splitlines()),
"monitored_rule_sets": list(AIDE_RULE_SETS.keys()),
"exclusion_count": len(AIDE_EXCLUSIONS),
"baseline_status": baseline_status,
"integrity_check": check_findings,
"cron_schedule": cron_config,
}
def main():
parser = argparse.ArgumentParser(description="AIDE File Integrity Monitoring Agent")
parser.add_argument("--action", choices=["generate", "init", "check", "full"],
default="generate", help="Action to perform")
parser.add_argument("--config-output", default="/etc/aide/aide.conf", help="Config output path")
parser.add_argument("--alert-email", help="Email for cron alert notifications")
parser.add_argument("--output", default="aide_report.json")
parser.add_argument("--rule-sets", nargs="+", default=None,
choices=list(AIDE_RULE_SETS.keys()), help="Rule sets to enable")
args = parser.parse_args()
config_content = generate_aide_config(args.rule_sets)
baseline_status = {}
check_findings = {}
if args.action in ("generate", "full"):
os.makedirs(os.path.dirname(args.config_output), exist_ok=True)
with open(args.config_output, "w") as f:
f.write(config_content)
print(f"[+] AIDE config written to {args.config_output}")
if args.action in ("init", "full"):
baseline_status = initialize_baseline()
print(f"[+] Baseline init: {baseline_status['status']}")
if args.action in ("check", "full"):
check_findings = run_integrity_check()
s = check_findings.get("summary", {})
print(f"[+] Check: added={s.get('added_count', 0)} removed={s.get('removed_count', 0)} "
f"changed={s.get('changed_count', 0)}")
cron_config = generate_cron_config(email=args.alert_email)
report = generate_report(config_content, baseline_status, check_findings, cron_config)
with open(args.output, "w") as f:
json.dump(report, f, indent=2, default=str)
print(f"[+] Report saved to {args.output}")
if __name__ == "__main__":
main()
Keep exploring