Integrate ModSecurity 3 with SOAR platforms for automated incident response and threat detection

Advanced 45 min Apr 29, 2026 486 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Set up ModSecurity 3 with structured logging, webhook notifications, and API integrations to automatically feed security events into SOAR platforms for real-time threat detection and incident response workflows.

Prerequisites

  • Root or sudo access
  • Web server (Nginx recommended)
  • Python 3.6 or later
  • SOAR platform with webhook support
  • Basic understanding of web application security

What this solves

ModSecurity 3 web application firewall generates security events that need structured processing for automated incident response. This tutorial configures ModSecurity with JSON logging, webhook notifications, and API integrations to feed security data into SOAR (Security Orchestration, Automation, and Response) platforms like Splunk Phantom, IBM Resilient, or Demisto for automated threat detection and response workflows.

Step-by-step installation and configuration

Update system packages and install dependencies

Start by updating your system and installing required packages for ModSecurity 3 compilation and web server integration.

sudo apt update && sudo apt upgrade -y
sudo apt install -y build-essential libcurl4-openssl-dev liblua5.3-dev libfuzzy-dev ssdeep gettext pkg-config libpcre3-dev libxml2-dev libcurl4-openssl-dev libyajl-dev doxygen nginx apache2-dev git autoconf automake libtool libgeoip-dev
sudo dnf update -y
sudo dnf groupinstall -y "Development Tools"
sudo dnf install -y libcurl-devel lua-devel libfuzzy-devel ssdeep gettext-devel pkgconfig pcre-devel libxml2-devel yajl-devel doxygen nginx httpd-devel git autoconf automake libtool GeoIP-devel

Download and compile ModSecurity 3

Clone the ModSecurity 3 source code and compile it with all necessary modules for web application firewall functionality.

cd /opt
sudo git clone --depth 1 -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity.git
sudo chown -R $USER:$USER /opt/ModSecurity
cd ModSecurity
git submodule init
git submodule update
./build.sh
./configure
make
sudo make install

Install ModSecurity-nginx connector

Download and compile the ModSecurity-nginx connector to integrate ModSecurity 3 with Nginx web server.

cd /opt
sudo git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git
sudo chown -R $USER:$USER /opt/ModSecurity-nginx

# Get nginx version for dynamic module compilation
nginx -v 2>&1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+'

# Download nginx source matching your version (replace 1.24.0 with your version)
wget http://nginx.org/download/nginx-1.24.0.tar.gz
tar zxvf nginx-1.24.0.tar.gz
cd nginx-1.24.0

# Configure and build the dynamic module
./configure --with-compat --add-dynamic-module=../ModSecurity-nginx
make modules
sudo cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules/

Download OWASP Core Rule Set

Install the OWASP Core Rule Set (CRS) which provides comprehensive protection rules for common web application attacks.

cd /opt
sudo wget https://github.com/coreruleset/coreruleset/archive/v4.0.0.tar.gz
sudo tar -xzf v4.0.0.tar.gz
sudo mv coreruleset-4.0.0 /opt/coreruleset
sudo cp /opt/coreruleset/crs-setup.conf.example /opt/coreruleset/crs-setup.conf

Create ModSecurity main configuration

Configure ModSecurity 3 with JSON logging format for SOAR platform consumption and structured event data.

SecRuleEngine On
SecRequestBodyAccess On
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072
SecRequestBodyInMemoryLimit 131072
SecRequestBodyLimitAction Reject
SecRule REQUEST_HEADERS:Content-Type "text/xml" "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
SecRule REQUEST_HEADERS:Content-Type "application/xml" "id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
SecRule REQUEST_HEADERS:Content-Type "text/xml" "id:'200002',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
SecResponseBodyAccess On
SecResponseBodyMimeType text/plain text/html text/xml
SecResponseBodyLimit 524288
SecResponseBodyLimitAction ProcessPartial
SecTmpDir /tmp/
SecDataDir /tmp/

# JSON Logging Configuration for SOAR Integration
SecAuditEngine On
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABIJDEFHZ
SecAuditLogType Serial
SecAuditLog /var/log/modsecurity/audit.log
SecAuditLogFormat JSON

# Enhanced JSON logging with additional fields for SOAR
SecAuditLogStorageDir /var/log/modsecurity/
SecRule RESPONSE_STATUS "@streq 200" "id:999001,phase:5,pass,nolog,setvar:'tx.allowed_request=1'"
SecRule TX:ALLOWED_REQUEST "@eq 1" "id:999002,phase:5,pass,log,msg:'Legitimate request logged for baseline',logdata:'client_ip=%{REMOTE_ADDR} user_agent=%{REQUEST_HEADERS.User-Agent} method=%{REQUEST_METHOD} uri=%{REQUEST_URI}'"

# Custom action for webhook notifications
SecAction "id:999003,phase:1,pass,nolog,setvar:'tx.webhook_url=http://your-soar-platform.example.com/api/webhook/modsecurity'"

SecDebugLog /var/log/modsecurity/debug.log
SecDebugLogLevel 3
SecArgumentSeparator &
SecCookieFormat 0
SecTmpSaveUploadedFiles on
SecUploadDir /opt/modsecurity/var/upload

Create structured JSON logging script

Create a Python script to parse ModSecurity logs and format them for SOAR platform consumption with enriched metadata.

#!/usr/bin/env python3
import json
import re
import requests
import time
from datetime import datetime
import hashlib
import os
import sys

class ModSecuritySOARIntegration:
    def __init__(self, webhook_url, api_key=None):
        self.webhook_url = webhook_url
        self.api_key = api_key
        self.headers = {
            'Content-Type': 'application/json',
            'User-Agent': 'ModSecurity-SOAR-Integration/1.0'
        }
        if api_key:
            self.headers['Authorization'] = f'Bearer {api_key}'
    
    def parse_audit_log(self, log_line):
        """Parse ModSecurity audit log line and extract security event data"""
        try:
            log_data = json.loads(log_line)
            
            # Extract key security indicators
            event = {
                'timestamp': datetime.utcnow().isoformat() + 'Z',
                'source_ip': log_data.get('request', {}).get('remote_addr', ''),
                'request_method': log_data.get('request', {}).get('method', ''),
                'request_uri': log_data.get('request', {}).get('uri', ''),
                'user_agent': log_data.get('request', {}).get('headers', {}).get('User-Agent', ''),
                'host': log_data.get('request', {}).get('headers', {}).get('Host', ''),
                'response_status': log_data.get('response', {}).get('http_code', 0),
                'rules_matched': [],
                'threat_score': 0,
                'severity': 'info'
            }
            
            # Process matched rules
            messages = log_data.get('audit_data', {}).get('messages', [])
            for msg in messages:
                rule_info = {
                    'rule_id': msg.get('details', {}).get('ruleId', ''),
                    'message': msg.get('details', {}).get('msg', ''),
                    'data': msg.get('details', {}).get('data', ''),
                    'file': msg.get('details', {}).get('file', ''),
                    'line': msg.get('details', {}).get('lineNumber', ''),
                    'severity': msg.get('details', {}).get('severity', '')
                }
                event['rules_matched'].append(rule_info)
                
                # Calculate threat score based on rule severity
                severity_scores = {'EMERGENCY': 5, 'ALERT': 4, 'CRITICAL': 4, 'ERROR': 3, 'WARNING': 2, 'NOTICE': 1}
                event['threat_score'] += severity_scores.get(rule_info['severity'].upper(), 1)
            
            # Set overall severity based on threat score
            if event['threat_score'] >= 10:
                event['severity'] = 'critical'
            elif event['threat_score'] >= 5:
                event['severity'] = 'high'
            elif event['threat_score'] >= 3:
                event['severity'] = 'medium'
            else:
                event['severity'] = 'low'
            
            # Generate unique event ID
            event_string = f"{event['timestamp']}{event['source_ip']}{event['request_uri']}"
            event['event_id'] = hashlib.sha256(event_string.encode()).hexdigest()[:16]
            
            return event
            
        except (json.JSONDecodeError, KeyError) as e:
            print(f"Error parsing log line: {e}")
            return None
    
    def send_to_soar(self, event_data):
        """Send security event to SOAR platform via webhook"""
        try:
            # Prepare SOAR-compatible payload
            soar_payload = {
                'alert_type': 'modsecurity_waf',
                'severity': event_data['severity'],
                'timestamp': event_data['timestamp'],
                'source': 'ModSecurity WAF',
                'event_id': event_data['event_id'],
                'indicators': {
                    'ip_address': event_data['source_ip'],
                    'user_agent': event_data['user_agent'],
                    'host': event_data['host'],
                    'request_uri': event_data['request_uri']
                },
                'details': {
                    'method': event_data['request_method'],
                    'response_code': event_data['response_status'],
                    'threat_score': event_data['threat_score'],
                    'matched_rules': event_data['rules_matched']
                },
                'raw_data': event_data
            }
            
            response = requests.post(
                self.webhook_url,
                headers=self.headers,
                json=soar_payload,
                timeout=10
            )
            
            if response.status_code == 200:
                print(f"Successfully sent event {event_data['event_id']} to SOAR platform")
                return True
            else:
                print(f"Failed to send event to SOAR: HTTP {response.status_code}")
                return False
                
        except requests.RequestException as e:
            print(f"Error sending to SOAR platform: {e}")
            return False

def monitor_audit_log(log_file_path, soar_integration):
    """Monitor ModSecurity audit log and send events to SOAR"""
    try:
        with open(log_file_path, 'r') as f:
            # Seek to end of file
            f.seek(0, 2)
            
            while True:
                line = f.readline()
                if line:
                    event = soar_integration.parse_audit_log(line.strip())
                    if event and event['threat_score'] > 0:
                        soar_integration.send_to_soar(event)
                else:
                    time.sleep(1)
                    
    except FileNotFoundError:
        print(f"Audit log file not found: {log_file_path}")
    except KeyboardInterrupt:
        print("Monitoring stopped")

if __name__ == "__main__":
    # Configuration - modify these values for your SOAR platform
    WEBHOOK_URL = os.getenv('MODSEC_SOAR_WEBHOOK', 'http://your-soar-platform.example.com/api/webhook/modsecurity')
    API_KEY = os.getenv('MODSEC_SOAR_API_KEY', '')
    LOG_FILE = '/var/log/modsecurity/audit.log'
    
    soar = ModSecuritySOARIntegration(WEBHOOK_URL, API_KEY)
    monitor_audit_log(LOG_FILE, soar)

Configure Nginx with ModSecurity module

Enable ModSecurity module in Nginx and configure it to use our security rules and logging settings.

# Add at the top of nginx.conf
load_module modules/ngx_http_modsecurity_module.so;

http {
    # ModSecurity configuration
    modsecurity on;
    modsecurity_rules_file /opt/ModSecurity/modsecurity.conf;
    
    # Enable detailed logging
    log_format modsec_json escape=json '{'
        '"time":"$time_iso8601",'
        '"remote_addr":"$remote_addr",'
        '"request":"$request",'
        '"status":$status,'
        '"body_bytes_sent":$body_bytes_sent,'
        '"http_referer":"$http_referer",'
        '"http_user_agent":"$http_user_agent",'
        '"request_time":$request_time,'
        '"upstream_response_time":"$upstream_response_time"'
    '}';
    
    access_log /var/log/nginx/access.log modsec_json;
    error_log /var/log/nginx/error.log warn;
    
    # Include other configurations
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Create virtual host with ModSecurity protection

Configure a virtual host that demonstrates ModSecurity protection with OWASP Core Rule Set integration.

server {
    listen 80;
    server_name example.com www.example.com;
    
    # Enable ModSecurity for this virtual host
    modsecurity on;
    modsecurity_rules_file /opt/ModSecurity/modsecurity.conf;
    
    # Include OWASP Core Rule Set
    modsecurity_rules '
        Include /opt/coreruleset/crs-setup.conf
        Include /opt/coreruleset/rules/*.conf
        
        # Custom rule for SOAR integration
        SecRule REQUEST_URI "@detectSQLi" \
            "id:2001,phase:2,block,msg:SQL Injection Attack,logdata:Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME},tag:attack-sqli,severity:CRITICAL"
        
        SecRule ARGS "@detectXSS" \
            "id:2002,phase:2,block,msg:XSS Attack,logdata:Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME},tag:attack-xss,severity:CRITICAL"
        
        # Custom action to trigger webhook on high severity events
        SecRule TX:ANOMALY_SCORE "@gt 4" \
            "id:2003,phase:5,pass,exec:/opt/modsecurity/webhook_notify.sh %{TX.ANOMALY_SCORE} %{REMOTE_ADDR} %{REQUEST_URI}"
    ';
    
    location / {
        root /var/www/html;
        index index.html index.htm;
        
        # Additional security headers
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-XSS-Protection "1; mode=block" always;
        add_header X-Content-Type-Options "nosniff" always;
    }
    
    # Specific protection for admin areas
    location /admin {
        modsecurity_rules '
            SecRuleRemoveById 920350
            SecRule REQUEST_URI "@beginsWith /admin" \
                "id:3001,phase:1,pass,log,msg:Admin area access,logdata:IP: %{REMOTE_ADDR} URI: %{REQUEST_URI}"
        ';
        
        root /var/www/html;
        index index.html;
    }
}

Create webhook notification script

Create a shell script that triggers immediate webhook notifications for high-severity security events.

#!/bin/bash

# ModSecurity Webhook Notification Script
# Arguments: $1=anomaly_score $2=remote_addr $3=request_uri

ANOMALY_SCORE=$1
REMOTE_ADDR=$2
REQUEST_URI=$3
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
WEBHOOK_URL="${MODSEC_SOAR_WEBHOOK:-http://your-soar-platform.example.com/api/webhook/modsecurity}"
API_KEY="${MODSEC_SOAR_API_KEY:-}"

# Create JSON payload for immediate notification
PAYLOAD=$(cat <

Set up log directories and permissions

Create necessary directories and set appropriate permissions for ModSecurity logging and scripts.

sudo mkdir -p /var/log/modsecurity
sudo mkdir -p /opt/modsecurity/var/upload
sudo chown -R www-data:www-data /var/log/modsecurity
sudo chown -R www-data:www-data /opt/modsecurity/var/upload
sudo chmod 755 /opt/modsecurity/webhook_notify.sh
sudo chmod 755 /opt/modsecurity/soar_integration.py

# Create logrotate configuration
sudo tee /etc/logrotate.d/modsecurity > /dev/null <

Configure environment variables for SOAR integration

Set up environment variables for SOAR platform connection details and API credentials.

# ModSecurity SOAR Integration Configuration
MODSEC_SOAR_WEBHOOK=https://your-soar-platform.example.com/api/webhook/modsecurity
MODSEC_SOAR_API_KEY=your_api_key_here
MODSEC_THREAT_THRESHOLD=3

Create systemd service for SOAR integration

Create a systemd service to run the SOAR integration script continuously and ensure it starts on boot.

[Unit]
Description=ModSecurity SOAR Integration Service
After=network.target nginx.service
Requires=nginx.service

[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/modsecurity
ExecStart=/usr/bin/python3 /opt/modsecurity/soar_integration.py
Restart=always
RestartSec=5
EnvironmentFile=/etc/environment

# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=modsecurity-soar

# Security settings
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/log/modsecurity

[Install]
WantedBy=multi-user.target

Enable and start services

Enable the Nginx virtual host, start ModSecurity protection, and activate the SOAR integration service.

# Enable the protected site
sudo ln -s /etc/nginx/sites-available/protected-site /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

# Enable and start the SOAR i

Automated install script

Run this to automate the entire setup

Vous ne voulez pas gérer cela vous-même ?

Nous gérons l'infrastructure des entreprises qui dépendent de leur disponibilité. Entièrement infogéré, avec un interlocuteur fixe qui connaît votre environnement.

Vous avez un interlocuteur fixe qui connaît votre installation

Rotterdam 07:19 · joignable par message, sans formulaire de ticket