DFIR-IRIS is an open source platform for case management and incident response, enabling incident responders to document, track, and analyze security incidents. It supports remote investigations by allowing responders to access and share technical details about incidents, fostering collaboration and coordinated responses to threats.

Integrating DFIR-IRIS with the Wazuh XDR and SIEM platform provides a framework that streamlines security monitoring and incident response. This integration enables incident response teams to correlate security events, track investigation progress, and coordinate response actions.

To achieve this integration, we modified the integration script originally written by Nate Uribe in his Wazuh-IRIS-integration repository.

Requirements

We use the following infrastructure to demonstrate the integration of DFIR-IRIS with Wazuh:

  • A deployment of the Wazuh 4.8.0 central components (Wazuh server, Wazuh indexer, and Wazuh dashboard). Refer to the Wazuh Quickstart guide to install the central components on a Linux endpoint.
  • A running instance of DFIR-IRIS 2.4.7. Refer to the DFIR-IRIS Getting started guide to configure an instance.

Configuration

DFIR-IRIS

DFIR-IRIS monitors multiple customers, and each customer has a unique customer ID. This is helpful for Managed Security Service Providers (MSSP) or organizations with multiple departments or remote locations they want to monitor independently. We use the default customer, IrisInitialClient, with customer ID 1, to demonstrate the integration process. This default customer comes out-of-the-box with an installation of DFIR-IRIS.

Take the following steps to prepare DFIR-IRIS for the Wazuh integration, and extract relevant credentials:

1. Log into the DFIR-IRIS dashboard with an administrator account. For this demonstration, we use the default administrator account in DFIR-IRIS.

2. Add your IRIS user to the customer which you are ingesting alerts for. Navigate to Advanced > Access control and select the user you wish to add to the customer account. Select the Customers tab in the pop-up, click Manage, add the customer you want to map the selected user to, and click Save.

Prepare DFIR-IRIS for the Wazuh integration

3. Find your customer ID by navigating to Advanced > Customers, and select the customer you want to perform the integration for. Note the customer ID displayed at the top of the page as you will use this when configuring the Wazuh server. The customer ID in the image shown below is 1.

Customer ID DFIR-IRIS

4. Obtain the API key for the logged in DFIR-IRIS user by clicking on the username and selecting My settings.

API key for the logged in DFIR-IRIS

5. Copy your user API key. You will use this when configuring the Wazuh server.

Configuring Wazuh server

Note: If using an account without administrator privileges, ensure that the user has the alert_read and alert_write  permissions to create new alerts via the API. Refer to DFIR-IRIS alerts for more information about alert permissions.

Wazuh server

Perform the following steps on the Wazuh server to configure it to forward alerts to DFIR-IRIS:

1. Create a script file /var/ossec/integrations/custom-wazuh_iris.py with the following content to forward alerts to DFIR-IRIS:

#!/var/ossec/framework/python/bin/python3
# custom-wazuh_iris.py
# Custom Wazuh integration script to send alerts to DFIR-IRIS

import sys
import json
import requests
import logging
from datetime import datetime

# Configure logging
logging.basicConfig(filename='/var/ossec/logs/integrations.log', level=logging.INFO, 
                    format='%(asctime)s %(levelname)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S')

# Function to create a formatted string from alert details
def format_alert_details(alert_json):
    rule = alert_json.get("rule", {})
    agent = alert_json.get("agent", {})
    
    # Extracting MITRE information from the nested 'rule' structure
    mitre = rule.get("mitre", {})
    mitre_ids = ', '.join(mitre.get("id", ["N/A"]))
    mitre_tactics = ', '.join(mitre.get("tactic", ["N/A"]))
    mitre_techniques = ', '.join(mitre.get("technique", ["N/A"]))

    details = [
        f"Rule ID: {rule.get('id', 'N/A')}",
        f"Rule Level: {rule.get('level', 'N/A')}",
        f"Rule Description: {rule.get('description', 'N/A')}",
        f"Agent ID: {agent.get('id', 'N/A')}",
        f"Agent Name: {agent.get('name', 'N/A')}",
        f"MITRE IDs: {mitre_ids}",
        f"MITRE Tactics: {mitre_tactics}",
        f"MITRE Techniques: {mitre_techniques}",
        f"Location: {alert_json.get('location', 'N/A')}",
        f"Full Log: {alert_json.get('full_log', 'N/A')}"
    ]
    return '\n'.join(details)

def main():
    # Read parameters when integration is run
    if len(sys.argv) < 4:
        logging.error("Insufficient arguments provided. Exiting.")
        sys.exit(1)
    
    alert_file = sys.argv[1]
    api_key = sys.argv[2]
    hook_url = sys.argv[3]

    # Read the alert file
    try:
        with open(alert_file) as f:
            alert_json = json.load(f)
    except Exception as e:
        logging.error(f"Failed to read alert file: {e}")
        sys.exit(1)

    # Prepare alert details
    alert_details = format_alert_details(alert_json)

    # Convert Wazuh rule levels(0-15) -> IRIS severity(1-6)
    alert_level = alert_json.get("rule", {}).get("level", 0)
    if alert_level < 5:
        severity = 2
    elif alert_level >= 5 and alert_level < 7:
        severity = 3
    elif alert_level >= 7 and alert_level < 10:
        severity = 4
    elif alert_level >= 10 and alert_level < 13:
        severity = 5
    elif alert_level >= 13:
        severity = 6
    else:
        severity = 1

    # Generate request
    payload = json.dumps({
        "alert_title": alert_json.get("rule", {}).get("description", "No Description"),
        "alert_description": alert_details,
        "alert_source": "Wazuh",
        "alert_source_ref": alert_json.get("id", "Unknown ID"),
        "alert_source_link": "https://<IP ADDRESS>/app/wz-home",  # Replace with actual Wazuh dashboard IP address
        "alert_severity_id": severity,
        "alert_status_id": 2,  # 'New' status
        "alert_source_event_time": alert_json.get("timestamp", "Unknown Timestamp"),
        "alert_note": "",
        "alert_tags": f"wazuh,{alert_json.get('agent', {}).get('name', 'N/A')}",
        "alert_customer_id": 1,  # '1' for default 'IrisInitialClient'
        "alert_source_content": alert_json  # raw log
    })

    # Send request to IRIS
    try:
        response = requests.post(hook_url, data=payload, headers={"Authorization": "Bearer " + api_key, "content-type": "application/json"}, verify=False)
        if response.status_code in [200, 201, 202, 204]:
            logging.info(f"Sent alert to IRIS. Response status code: {response.status_code}")
        else:
            logging.error(f"Failed to send alert to IRIS. Response status code: {response.status_code}")
    except Exception as e:
        logging.error(f"Failed to send alert to IRIS: {e}")
        sys.exit(1)

if __name__ == "__main__":
    main()

Where:

  • alert_source_link in the script is set to the value of the Wazuh dashboard IP address. Replace <IP ADDRESS> with the Wazuh dashboard IP address.
  • alert_customer_id  is set as the value of the ID of the customer as it appears on the DFIR-IRIS dashboard. In this case, we have configured the script to forward the alerts to customer ID 1.

2. Set the ownership and permissions of the /var/ossec/integrations/custom-wazuh_iris.py file so that the root user and the wazuh group have access to it:

# chmod 750 /var/ossec/integrations/custom-wazuh_iris.py
# chown root:wazuh /var/ossec/integrations/custom-wazuh_iris.py

3. Append the following configuration to the /var/ossec/etc/ossec.conf file to forward all alerts with a severity of 7 or higher to DFIR-IRIS:

<ossec_config>

  <!-- IRIS integration -->
  <integration>
    <name>custom-wazuh_iris.py</name>
    <hook_url>https://<IRIS_IP_ADDRESS>/alerts/add</hook_url>
    <level>7</level>
    <api_key><IRIS_API_KEY></api_key> <!-- Replace with your IRIS API key -->
    <alert_format>json</alert_format>
  </integration>

</ossec_config>

Replace:

  • <IRIS_IP_ADDRESS> with the IP address of the DFIR-IRIS server. Ensure to include the port number if DFIR-IRIS is not listening on port 443. For example, you can use https://192.168.1.2/alerts/add if DFIR-IRIS is listening on the default HTTPS port 443, or https://192.168.1.2:8000/alerts/add if listening on custom port 8000.
  • <IRIS_API_KEY> with the API key retrieved from the DFIR-IRIS web console.

You can also configure the integration to forward only alerts triggered from specific rule IDs or groups to DFIR-IRIS. Refer to Wazuh integration with third-party APIs for more configuration options.

4. Restart the Wazuh manager to apply the changes:

# systemctl restart wazuh-manager

Visualize alerts

You will see alerts on the Alerts page of DFIR-IRIS as soon as an alert with a severity of 7 or higher is fired on Wazuh.

DFIR-IRIS alerts

Note: You can analyze the Wazuh server integration log file /var/ossec/logs/integrations.log to identify and troubleshoot potential integration issues.

Conclusion

Integrating DFIR-IRIS with Wazuh enhances incident response capabilities by combining security monitoring with efficient incident management. This integration enables incident response teams to correlate security events, track investigation progress, and coordinate response actions. By following the steps outlined in this guide, you can ensure a connection between the two platforms. This strengthens your security posture and streamlines workflows for incident response teams, enabling quicker and more informed decision-making during security incidents.

References