endpoint security

Configuring Host-Based Intrusion Detection

Configures host-based intrusion detection systems (HIDS) to monitor endpoint file integrity, system calls, and configuration changes for security violations. Use when deploying OSSEC, Wazuh, or AIDE for endpoint monitoring, building file integrity monitoring (FIM) policies, or meeting compliance requirements for change detection. Activates for requests involving HIDS configuration, file integrity monitoring, OSSEC/Wazuh deployment, or host-based detection.

endpointfile-integrity-monitoringhidsintrusion-detectionossecwazuh
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

When to Use

Use this skill when:

  • Deploying HIDS agents (Wazuh, OSSEC, AIDE) across Windows and Linux endpoints
  • Configuring file integrity monitoring (FIM) for compliance (PCI DSS 11.5, NIST SI-7)
  • Monitoring system configuration changes, rootkit detection, and security policy violations
  • Integrating HIDS alerts with SIEM platforms for centralized monitoring

Do not use this skill for network-based IDS (Suricata, Snort) or for EDR deployment.

Prerequisites

  • Wazuh server (manager) deployed and accessible from endpoints
  • Administrative access to target endpoints
  • Network connectivity: agents to Wazuh manager on port 1514 (TCP/UDP) and 1515 (TCP enrollment)
  • Wazuh dashboard (OpenSearch Dashboards) for alert visualization
  • Understanding of critical files/directories to monitor per OS

Workflow

Step 1: Install Wazuh Agent

Windows:

# Download and install Wazuh agent
Invoke-WebRequest -Uri "https://packages.wazuh.com/4.x/windows/wazuh-agent-4.9.0-1.msi" `
  -OutFile "wazuh-agent.msi"
msiexec /i wazuh-agent.msi /q WAZUH_MANAGER="wazuh-manager.corp.com" `
  WAZUH_REGISTRATION_SERVER="wazuh-manager.corp.com" WAZUH_AGENT_GROUP="windows-workstations"
net start WazuhSvc

Linux (Debian/Ubuntu):

curl -s https://packages.wazuh.com/key/GPG-KEY-WAZUH | gpg --dearmor -o /usr/share/keyrings/wazuh.gpg
echo "deb [signed-by=/usr/share/keyrings/wazuh.gpg] https://packages.wazuh.com/4.x/apt/ stable main" \
  > /etc/apt/sources.list.d/wazuh.list
apt-get update && apt-get install wazuh-agent -y
sed -i 's/MANAGER_IP/wazuh-manager.corp.com/' /var/ossec/etc/ossec.conf
systemctl daemon-reload && systemctl enable --now wazuh-agent

Step 2: Configure File Integrity Monitoring (FIM)

Edit agent configuration (/var/ossec/etc/ossec.conf or C:\Program Files (x86)\ossec-agent\ossec.conf):

<syscheck>
  <!-- Scan frequency: every 12 hours -->
  <frequency>43200</frequency>
  <scan_on_start>yes</scan_on_start>
  <alert_new_files>yes</alert_new_files>
 
  <!-- Linux critical directories -->
  <directories check_all="yes" realtime="yes">/etc</directories>
  <directories check_all="yes" realtime="yes">/usr/bin</directories>
  <directories check_all="yes" realtime="yes">/usr/sbin</directories>
  <directories check_all="yes" realtime="yes">/bin</directories>
  <directories check_all="yes" realtime="yes">/sbin</directories>
  <directories check_all="yes">/boot</directories>
 
  <!-- Windows critical directories -->
  <directories check_all="yes" realtime="yes">C:\Windows\System32</directories>
  <directories check_all="yes" realtime="yes">C:\Windows\SysWOW64</directories>
  <directories check_all="yes" realtime="yes">%PROGRAMFILES%</directories>
 
  <!-- Windows registry monitoring -->
  <windows_registry>HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run</windows_registry>
  <windows_registry>HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce</windows_registry>
  <windows_registry>HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services</windows_registry>
 
  <!-- Ignore frequently changing files -->
  <ignore>/etc/mtab</ignore>
  <ignore>/etc/resolv.conf</ignore>
  <ignore type="sregex">.log$</ignore>
</syscheck>

Step 3: Configure Rootkit Detection

<rootcheck>
  <disabled>no</disabled>
  <frequency>43200</frequency>
  <rootkit_files>/var/ossec/etc/shared/rootkit_files.txt</rootkit_files>
  <rootkit_trojans>/var/ossec/etc/shared/rootkit_trojans.txt</rootkit_trojans>
  <system_audit>/var/ossec/etc/shared/system_audit_rcl.txt</system_audit>
  <check_dev>yes</check_dev>
  <check_files>yes</check_files>
  <check_if>yes</check_if>
  <check_pids>yes</check_pids>
  <check_ports>yes</check_ports>
  <check_sys>yes</check_sys>
  <check_trojans>yes</check_trojans>
  <check_unixaudit>yes</check_unixaudit>
</rootcheck>

Step 4: Configure Log Analysis Rules

<!-- Custom rules in /var/ossec/etc/rules/local_rules.xml -->
<group name="local,syscheck,">
  <!-- Alert on critical binary modifications -->
  <rule id="100001" level="12">
    <if_sid>550</if_sid>
    <match>/usr/bin/|/usr/sbin/|/bin/|/sbin/</match>
    <description>Critical system binary modified: $(file)</description>
    <group>syscheck,pci_dss_11.5,</group>
  </rule>
 
  <!-- Alert on new executable in temp directories -->
  <rule id="100002" level="10">
    <if_sid>554</if_sid>
    <match>/tmp/|/var/tmp/</match>
    <description>New file created in temp directory: $(file)</description>
    <group>syscheck,malware,</group>
  </rule>
 
  <!-- Alert on SSH configuration changes -->
  <rule id="100003" level="10">
    <if_sid>550</if_sid>
    <match>/etc/ssh/sshd_config</match>
    <description>SSH configuration modified</description>
    <group>syscheck,authentication,</group>
  </rule>
</group>

Step 5: Configure Active Response

<!-- Auto-block IP after repeated authentication failures -->
<active-response>
  <command>firewall-drop</command>
  <location>local</location>
  <rules_id>5712</rules_id>
  <timeout>600</timeout>
</active-response>
 
<!-- Disable account after brute force detection -->
<active-response>
  <disabled>no</disabled>
  <command>disable-account</command>
  <location>local</location>
  <rules_id>100100</rules_id>
  <timeout>3600</timeout>
</active-response>

Step 6: Integrate with SIEM

# Wazuh to Splunk via Filebeat
# Edit /etc/filebeat/filebeat.yml:
filebeat.inputs:
  - type: log
    paths:
      - /var/ossec/logs/alerts/alerts.json
    json.keys_under_root: true
output.elasticsearch:
  hosts: ["https://splunk-hec:8088"]
 
# Wazuh to Elastic via direct integration
# Wazuh indexer feeds directly into OpenSearch/Elasticsearch
# Dashboard: https://wazuh-dashboard:5601

Key Concepts

Term Definition
HIDS Host-based Intrusion Detection System; monitors individual endpoints for malicious activity
FIM File Integrity Monitoring; detects unauthorized changes to files by comparing cryptographic hashes
Syscheck Wazuh/OSSEC module for file integrity monitoring and registry monitoring
Rootcheck Wazuh/OSSEC module for rootkit and malware detection
Active Response Automated defensive action triggered by HIDS alert (IP block, account disable)
CDB List Constant Database list used for custom lookups in Wazuh rules

Tools & Systems

  • Wazuh: Open-source HIDS platform (fork of OSSEC) with manager, agent, and dashboard
  • OSSEC: Original open-source HIDS (predecessor to Wazuh)
  • AIDE (Advanced Intrusion Detection Environment): Standalone file integrity checker for Linux
  • Tripwire: Commercial file integrity monitoring solution
  • Samhain: Open-source HIDS focused on file integrity and log monitoring

Common Pitfalls

  • Monitoring too many directories: FIM on entire filesystems generates excessive alerts. Focus on critical system binaries, configuration files, and web roots.
  • Not excluding noisy files: Frequently changing files (logs, temp, caches) generate false positive FIM alerts. Maintain exclusion lists.
  • Ignoring baseline establishment: First FIM scan creates a baseline. Changes detected before baseline stabilization are noise, not threats. Allow 48 hours for baseline.
  • Active response without testing: Auto-blocking IPs or disabling accounts can cause outages. Test active response rules in a non-production environment first.
  • Agent enrollment failures: Agents must successfully enroll with the manager before monitoring begins. Verify firewall rules allow port 1514 and 1515 traffic.
Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 3

api-reference.md1.5 KB

Host-Based Intrusion Detection — API Reference

Libraries

Library Install Purpose
requests pip install requests Wazuh REST API client
osquery Binary install SQL-based host inspection
hashlib stdlib File integrity hash computation

Wazuh API Endpoints

Method Endpoint Description
POST /security/user/authenticate Obtain JWT token
GET /agents List managed agents
GET /agents/{id} Agent details
GET /sca/{agent_id} Security Configuration Assessment results
GET /rootcheck/{agent_id} Rootkit check results
GET /alerts Query security alerts
GET /rules List detection rules

Key osquery Tables

Table Description
processes Running processes with user, path, cmdline
listening_ports Open network ports and bound processes
users System user accounts
file File metadata and hashes
suid_bin SUID/SGID binaries
crontab Scheduled cron jobs

OSSEC Rule IDs

Rule ID Range Category
500-599 File integrity monitoring
5700-5799 SSH authentication
18100-18199 Linux audit events
31100-31199 Web attack detection

External References

standards.md1.5 KB

Standards & References - Configuring Host-Based Intrusion Detection

Primary Standards

NIST SP 800-94 Rev 1 - Guide to Intrusion Detection and Prevention Systems

  • Publisher: NIST
  • Scope: Architecture, deployment, and management of IDPS including host-based systems

PCI DSS 4.0 Requirement 11.5 - File Integrity Monitoring

  • Publisher: PCI SSC
  • Requirement: Deploy FIM to alert on unauthorized modification of critical files
  • Scope: System files, configuration files, content files on in-scope systems

CIS Control 3 - Data Protection (v8)

  • Publisher: CIS
  • Relevance: Sub-control 3.14 requires monitoring for unauthorized changes to sensitive data

Compliance Mappings

Framework Requirement HIDS Coverage
PCI DSS 4.0 11.5.2 - FIM mechanism deployed Wazuh syscheck module
NIST 800-53 SI-7 Software, Firmware, and Information Integrity File integrity monitoring
NIST 800-53 SI-4 System Monitoring HIDS log analysis and alerting
HIPAA 164.312(b) - Audit controls File access and change monitoring
ISO 27001 A.12.4.1 - Event logging HIDS event collection and analysis

Supporting References

workflows.md1.3 KB

Workflows - Configuring Host-Based Intrusion Detection

Workflow 1: Wazuh HIDS Deployment

[Deploy Wazuh Manager]


[Configure FIM, rootcheck, and log analysis modules]


[Deploy agents to pilot endpoints]


[Establish baseline (48 hours)]


[Tune rules: suppress false positives, add exclusions]


[Deploy agents to production fleet]


[Integrate with SIEM]


[Create dashboards and alert workflows]

Workflow 2: FIM Alert Investigation

[FIM alert: File modified]


[Check file path and change details]

    ├── Known system update ──► [Correlate with patch window, close alert]
    ├── Authorized config change ──► [Verify change ticket, close alert]
    └── Unauthorized change ──► [Investigate]

                                     ├── Determine who/what changed the file
                                     ├── Review process tree and timeline

                                     ├── Malicious ──► [Escalate to IR]
                                     └── Operational ──► [Update change process]

Scripts 2

agent.py5.3 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Host-based intrusion detection agent using OSSEC/Wazuh API and osquery."""

import json
import os
import sys
import argparse
import subprocess
from datetime import datetime

try:
    import requests
    requests.packages.urllib3.disable_warnings()
except ImportError:
    print("Install: pip install requests")
    sys.exit(1)


class WazuhClient:
    """Wazuh API client for HIDS management."""

    def __init__(self, base_url, username, password):
        self.url = base_url.rstrip("/")
        self.token = self._authenticate(username, password)

    def _authenticate(self, username, password):
        resp = requests.post(f"{self.url}/security/user/authenticate",
                             auth=(username, password),
                             verify=not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true", timeout=30)  # Set SKIP_TLS_VERIFY=true for self-signed certs in lab environments
        resp.raise_for_status()
        return resp.json()["data"]["token"]

    def _get(self, endpoint, params=None):
        resp = requests.get(f"{self.url}/{endpoint}",
                            headers={"Authorization": f"Bearer {self.token}"},
                            params=params,
                            verify=not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true", timeout=30)  # Set SKIP_TLS_VERIFY=true for self-signed certs in lab environments
        resp.raise_for_status()
        return resp.json()

    def list_agents(self, status=None):
        params = {}
        if status:
            params["status"] = status
        return self._get("agents", params)

    def get_agent_alerts(self, agent_id, limit=20):
        return self._get(f"alerts", {"agent.id": agent_id, "limit": limit})

    def get_sca_results(self, agent_id):
        return self._get(f"sca/{agent_id}")

    def get_rootcheck(self, agent_id):
        return self._get(f"rootcheck/{agent_id}")


def run_osquery_check(query):
    """Execute osquery for host inspection."""
    cmd = ["osqueryi", "--json", query]
    try:
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
        return json.loads(result.stdout) if result.stdout.strip() else []
    except (FileNotFoundError, json.JSONDecodeError):
        return [{"error": "osquery not available"}]


def check_file_integrity(paths):
    """Check file integrity for key system files."""
    checks = []
    import hashlib, os
    for path in paths:
        if os.path.exists(path):
            with open(path, "rb") as f:
                sha256 = hashlib.sha256(f.read()).hexdigest()
            stat = os.stat(path)
            checks.append({
                "path": path,
                "sha256": sha256,
                "size": stat.st_size,
                "modified": datetime.fromtimestamp(stat.st_mtime).isoformat(),
                "status": "present",
            })
        else:
            checks.append({"path": path, "status": "missing", "severity": "HIGH"})
    return checks


def run_audit(wazuh_url=None, username=None, password=None, agent_id=None):
    """Execute HIDS audit."""
    print(f"\n{'='*60}")
    print(f"  HOST-BASED INTRUSION DETECTION AUDIT")
    print(f"  Generated: {datetime.utcnow().isoformat()} UTC")
    print(f"{'='*60}\n")

    if wazuh_url and username and password:
        client = WazuhClient(wazuh_url, username, password)
        agents = client.list_agents()
        data = agents.get("data", {})
        items = data.get("affected_items", [])
        print(f"--- WAZUH AGENTS ({data.get('total_affected_items', 0)}) ---")
        for a in items[:10]:
            print(f"  {a.get('name', 'N/A')} ({a.get('id', '')}): {a.get('status', '')}")

        if agent_id:
            sca = client.get_sca_results(agent_id)
            sca_data = sca.get("data", {}).get("affected_items", [])
            print(f"\n--- SCA RESULTS (agent {agent_id}) ---")
            for s in sca_data[:5]:
                print(f"  {s.get('name', '')}: pass={s.get('pass', 0)} fail={s.get('fail', 0)}")

    system_files = ["/etc/passwd", "/etc/shadow", "/etc/sudoers", "/etc/ssh/sshd_config"]
    integrity = check_file_integrity(system_files)
    print(f"\n--- FILE INTEGRITY CHECK ---")
    for f in integrity:
        print(f"  {f['path']}: {f['status']}")

    processes = run_osquery_check("SELECT name, pid, uid FROM processes WHERE uid = 0")
    print(f"\n--- ROOT PROCESSES ({len(processes)}) ---")
    for p in processes[:10]:
        if "error" not in p:
            print(f"  PID {p.get('pid', '')}: {p.get('name', '')}")

    return {"integrity": integrity, "processes": processes}


def main():
    parser = argparse.ArgumentParser(description="HIDS Audit Agent")
    parser.add_argument("--wazuh-url", help="Wazuh API URL (https://host:55000)")
    parser.add_argument("--username", help="Wazuh API username")
    parser.add_argument("--password", help="Wazuh API password")
    parser.add_argument("--agent-id", help="Specific agent ID to audit")
    parser.add_argument("--output", help="Save report to JSON file")
    args = parser.parse_args()

    report = run_audit(args.wazuh_url, args.username, args.password, args.agent_id)
    if args.output:
        with open(args.output, "w") as f:
            json.dump(report, f, indent=2, default=str)
        print(f"\n[+] Report saved to {args.output}")


if __name__ == "__main__":
    main()
process.py5.5 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""
HIDS Alert Analyzer

Parses Wazuh/OSSEC alerts JSON and generates summary reports for
file integrity monitoring and intrusion detection events.
"""

import json
import sys
import os
from collections import defaultdict, Counter
from datetime import datetime


def parse_wazuh_alerts(json_path: str) -> list:
    """Parse Wazuh alerts JSON file (one JSON object per line)."""
    alerts = []

    with open(json_path, "r", encoding="utf-8") as f:
        for line in f:
            line = line.strip()
            if not line:
                continue
            try:
                alert = json.loads(line)
                alerts.append({
                    "timestamp": alert.get("timestamp", ""),
                    "rule_id": alert.get("rule", {}).get("id", ""),
                    "rule_description": alert.get("rule", {}).get("description", ""),
                    "rule_level": alert.get("rule", {}).get("level", 0),
                    "rule_groups": alert.get("rule", {}).get("groups", []),
                    "agent_name": alert.get("agent", {}).get("name", ""),
                    "agent_ip": alert.get("agent", {}).get("ip", ""),
                    "syscheck_path": alert.get("syscheck", {}).get("path", ""),
                    "syscheck_event": alert.get("syscheck", {}).get("event", ""),
                    "syscheck_md5_after": alert.get("syscheck", {}).get("md5_after", ""),
                    "src_ip": alert.get("data", {}).get("srcip", ""),
                    "full_log": alert.get("full_log", "")[:300],
                })
            except json.JSONDecodeError:
                continue

    return alerts


def analyze_alerts(alerts: list) -> dict:
    """Analyze parsed alerts for patterns and summary statistics."""
    analysis = {
        "total_alerts": len(alerts),
        "by_level": Counter(),
        "by_rule": Counter(),
        "by_agent": Counter(),
        "by_group": Counter(),
        "fim_events": {
            "modified": 0,
            "added": 0,
            "deleted": 0,
            "top_modified_files": Counter(),
        },
        "high_severity": [],
        "attack_sources": Counter(),
    }

    for alert in alerts:
        level = alert["rule_level"]
        analysis["by_level"][level] += 1
        analysis["by_rule"][f"{alert['rule_id']}: {alert['rule_description']}"] += 1
        analysis["by_agent"][alert["agent_name"]] += 1

        for group in alert["rule_groups"]:
            analysis["by_group"][group] += 1

        if "syscheck" in alert["rule_groups"] or alert["syscheck_path"]:
            event = alert["syscheck_event"]
            if event == "modified":
                analysis["fim_events"]["modified"] += 1
                analysis["fim_events"]["top_modified_files"][alert["syscheck_path"]] += 1
            elif event == "added":
                analysis["fim_events"]["added"] += 1
            elif event == "deleted":
                analysis["fim_events"]["deleted"] += 1

        if level >= 10:
            analysis["high_severity"].append({
                "timestamp": alert["timestamp"],
                "agent": alert["agent_name"],
                "rule": alert["rule_description"],
                "level": level,
                "detail": alert["full_log"],
            })

        if alert["src_ip"]:
            analysis["attack_sources"][alert["src_ip"]] += 1

    return analysis


def generate_report(analysis: dict, output_path: str) -> None:
    """Generate HIDS alert analysis report."""
    report = {
        "report_generated": datetime.utcnow().isoformat() + "Z",
        "total_alerts": analysis["total_alerts"],
        "severity_distribution": dict(analysis["by_level"]),
        "top_rules": dict(analysis["by_rule"].most_common(20)),
        "top_agents": dict(analysis["by_agent"].most_common(20)),
        "alert_groups": dict(analysis["by_group"].most_common(15)),
        "file_integrity": {
            "files_modified": analysis["fim_events"]["modified"],
            "files_added": analysis["fim_events"]["added"],
            "files_deleted": analysis["fim_events"]["deleted"],
            "top_modified": dict(analysis["fim_events"]["top_modified_files"].most_common(20)),
        },
        "high_severity_alerts": analysis["high_severity"][:50],
        "top_attack_sources": dict(analysis["attack_sources"].most_common(20)),
    }

    with open(output_path, "w", encoding="utf-8") as f:
        json.dump(report, f, indent=2)


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python process.py <wazuh_alerts.json>")
        print()
        print("Analyzes Wazuh/OSSEC alerts JSON for HIDS event patterns.")
        sys.exit(1)

    json_path = sys.argv[1]
    if not os.path.exists(json_path):
        print(f"Error: File not found: {json_path}")
        sys.exit(1)

    print("Parsing Wazuh alerts...")
    alerts = parse_wazuh_alerts(json_path)
    print(f"Parsed {len(alerts)} alerts")

    print("Analyzing alert patterns...")
    analysis = analyze_alerts(alerts)

    base = os.path.splitext(os.path.basename(json_path))[0]
    out_dir = os.path.dirname(json_path) or "."
    report_path = os.path.join(out_dir, f"{base}_analysis.json")
    generate_report(analysis, report_path)
    print(f"Analysis report: {report_path}")

    print(f"\n--- HIDS Alert Summary ---")
    print(f"Total alerts: {analysis['total_alerts']}")
    print(f"High severity (level >= 10): {len(analysis['high_severity'])}")
    print(f"FIM: {analysis['fim_events']['modified']} modified, "
          f"{analysis['fim_events']['added']} added, "
          f"{analysis['fim_events']['deleted']} deleted")

Assets 1

template.mdtext/markdown · 1.0 KB
Keep exploring