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
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 <Send webhook with proper headers
if [ -n "$API_KEY" ]; then
curl -X POST "$WEBHOOK_URL" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $API_KEY" \
-d "$PAYLOAD" \
--max-time 5 \
--silent \
--output /dev/null
else
curl -X POST "$WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d "$PAYLOAD" \
--max-time 5 \
--silent \
--output /dev/null
fi
Log the notification attempt
echo "[$(date)] Webhook sent for IP: $REMOTE_ADDR, URI: $REQUEST_URI, Score: $ANOMALY_SCORE" >> /var/log/modsecurity/webhook.log
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 integration service
sudo systemctl daemon-reload
sudo systemctl enable modsecurity-soar
sudo systemctl start modsecurity-soar
Check service status
sudo systemctl status modsecurity-soar
sudo systemctl status nginx
Configure SOAR platform webhook endpoints
Set up SOAR platform webhook receiver
Configure your SOAR platform to receive and process ModSecurity security events. This example shows configuration for a generic SOAR platform.
# Example webhook endpoint configuration for SOAR platforms
Endpoint: POST /api/webhook/modsecurity
Required headers:
Content-Type: application/json
Authorization: Bearer YOUR_API_KEY (optional)
Expected payload structure:
{
"alert_type": "modsecurity_waf|modsecurity_high_severity",
"severity": "low|medium|high|critical",
"timestamp": "2024-01-15T10:30:00Z",
"source": "ModSecurity WAF",
"event_id": "unique_event_identifier",
"indicators": {
"ip_address": "203.0.113.10",
"user_agent": "Mozilla/5.0...",
"host": "example.com",
"request_uri": "/vulnerable-endpoint"
},
"details": {
"method": "POST",
"response_code": 403,
"threat_score": 8,
"matched_rules": [
{
"rule_id": "942100",
"message": "SQL Injection Attack Detected",
"severity": "CRITICAL",
"data": "SELECT * FROM users"
}
]
}
}
Configure automated response workflows
Set up automated incident response workflows in your SOAR platform based on ModSecurity event data.
# Example SOAR workflow configuration
Trigger: ModSecurity webhook with severity >= "high"
Workflow steps:
- Parse incoming ModSecurity event
- Enrich with threat intelligence data
- Check IP reputation (VirusTotal, AbuseIPDB)
- Create incident ticket
- If threat_score > 8:
- Add IP to firewall blocklist
- Send alert to security team
- Create SIEM correlation rule
- If repeated attacks from same IP:
- Implement rate limiting
- Escalate to senior analyst
- Update threat intelligence database
- Generate incident response report
Auto-remediation rules:
- SQL Injection attempts: Block IP for 24 hours
- XSS attempts: Rate limit and monitor
- Path traversal: Block immediately
- Anomaly score > 10: Immediate escalation
Testing and validation
Test SQL injection detection
Verify that ModSecurity detects SQL injection attempts and sends alerts to your SOAR platform.
# Test SQL injection detection
curl -X POST "http://example.com/search" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "query='; DROP TABLE users; --"
Test XSS detection
curl "http://example.com/search?q="
Test path traversal
curl "http://example.com/file?path=../../../etc/passwd"
Check ModSecurity audit log
sudo tail -f /var/log/modsecurity/audit.log
Check webhook notifications
sudo tail -f /var/log/modsecurity/webhook.log
Check SOAR integration service logs
sudo journalctl -u modsecurity-soar -f
Verify your setup
# Check ModSecurity module is loaded
nginx -V 2>&1 | grep -o with-http_modsecurity_module
Verify SOAR integration service
sudo systemctl status modsecurity-soar
Check log files are being created
ls -la /var/log/modsecurity/
Test webhook connectivity
curl -X POST "$MODSEC_SOAR_WEBHOOK" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MODSEC_SOAR_API_KEY" \
-d '{"test": "connectivity"}'
Verify OWASP rules are active
sudo grep -r "Include.*coreruleset" /etc/nginx/
Check for recent security events
sudo tail -20 /var/log/modsecurity/audit.log | grep -o '"msg":"[^"]*"'
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Nginx fails to start with ModSecurity module | Module path incorrect or missing dependencies | Check /etc/nginx/modules/ and run ldd ngx_http_modsecurity_module.so |
| SOAR webhooks not being sent | Network connectivity or API key issues | Test webhook URL manually with curl and verify API key |
| High false positive rate | OWASP rules too strict for application | Tune rules in /opt/coreruleset/crs-setup.conf and whitelist legitimate traffic |
| ModSecurity logs not in JSON format | Audit log format not set correctly | Verify SecAuditLogFormat JSON in modsecurity.conf |
| SOAR integration service crashes | Python dependencies or file permissions | Check service logs with journalctl -u modsecurity-soar and fix file ownership |
| Performance impact on web server | ModSecurity processing overhead | Tune SecRequestBodyLimit and disable unnecessary rule sets |
Performance optimization and fine-tuning
Optimize ModSecurity performance
Configure ModSecurity for high-performance environments with reduced latency and resource usage.
# Performance optimization settings
SecRequestBodyLimit 1048576
SecRequestBodyInMemoryLimit 131072
SecResponseBodyLimit 524288
Reduce logging overhead for high-traffic sites
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditEngine RelevantOnly
Optimize rule processing
SecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess Off
Cache compiled rules
SecDataDir /opt/modsecurity/var/cache
SecTmpDir /tmp/modsecurity
Sampling for high-volume sites (log 1 in 100 requests)
SecRule REQUEST_HEADERS:User-Agent "@rx .*" \
"id:9001,phase:1,pass,nolog,skipAfter:END_SAMPLING,ctl:auditEngine=Off"
SecRule TX:SAMPLING_RND "@lt 1" \
"id:9002,phase:1,pass,nolog,ctl:auditEngine=On"
SecMarker "END_SAMPLING"
Next steps
- Set up ELK Stack for centralized ModSecurity log analysis and monitoring
- Implement network security policies with iptables and firewalld for enterprise infrastructure protection
- Configure NGINX rate limiting and DDoS protection with advanced security rules
- Set up centralized security monitoring with ClamAV 1.4 and Elasticsearch 8
- Implement advanced ModSecurity rules for application-specific threats
- Configure SOAR platform integration with multiple security tools
Running this in production?
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# ModSecurity 3 with SOAR Integration Install Script
# Production-ready installation script for multiple Linux distributions
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Configuration variables
NGINX_CONFIG_DIR=""
NGINX_USER=""
WEBHOOK_URL="${1:-}"
# Print colored output
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Usage message
usage() {
echo "Usage: $0 [webhook_url]"
echo " webhook_url: Optional SOAR platform webhook URL for notifications"
exit 1
}
# Cleanup function for rollback
cleanup() {
print_error "Installation failed. Cleaning up..."
rm -rf /opt/ModSecurity /opt/ModSecurity-nginx /opt/coreruleset 2>/dev/null || true
systemctl stop nginx 2>/dev/null || true
}
# Set trap for cleanup on error
trap cleanup ERR
# Check if running as root or with sudo
if [[ $EUID -eq 0 ]] && [[ -z "${SUDO_USER:-}" ]]; then
print_warning "Running as root. Consider using sudo instead."
elif [[ $EUID -ne 0 ]] && [[ -z "${SUDO_USER:-}" ]]; then
print_error "This script requires root privileges. Please run with sudo."
exit 1
fi
# Auto-detect distribution and set package manager
echo "[1/12] Detecting distribution and setting up package manager..."
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_UPDATE="apt update"
PKG_INSTALL="apt install -y"
NGINX_CONFIG_DIR="/etc/nginx"
NGINX_USER="www-data"
;;
almalinux|rocky|centos|rhel|ol)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
NGINX_CONFIG_DIR="/etc/nginx"
NGINX_USER="nginx"
if ! command -v dnf &> /dev/null; then
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
fi
;;
fedora)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
NGINX_CONFIG_DIR="/etc/nginx"
NGINX_USER="nginx"
;;
amzn)
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
NGINX_CONFIG_DIR="/etc/nginx"
NGINX_USER="nginx"
;;
*)
print_error "Unsupported distribution: $ID"
exit 1
;;
esac
else
print_error "Cannot detect distribution. /etc/os-release not found."
exit 1
fi
print_status "Detected $ID, using $PKG_MGR package manager"
# Update system packages
echo "[2/12] Updating system packages..."
$PKG_UPDATE
# Install dependencies based on distribution
echo "[3/12] Installing build dependencies..."
if [[ "$PKG_MGR" == "apt" ]]; then
$PKG_INSTALL build-essential libcurl4-openssl-dev liblua5.3-dev libfuzzy-dev ssdeep gettext pkg-config libpcre3-dev libxml2-dev yajl-tools libyajl-dev doxygen nginx git autoconf automake libtool libgeoip-dev
else
$PKG_INSTALL "@Development Tools" libcurl-devel lua-devel ssdeep-devel gettext-devel pkgconfig pcre-devel libxml2-devel yajl-devel doxygen nginx git autoconf automake libtool GeoIP-devel
if [[ "$ID" == "fedora" ]] || [[ "$ID" == "almalinux" ]] || [[ "$ID" == "rocky" ]]; then
$PKG_INSTALL libfuzzy-devel
fi
fi
# Create necessary directories with proper permissions
echo "[4/12] Creating directories and setting permissions..."
mkdir -p /var/log/modsecurity /opt
chown root:root /opt
chmod 755 /opt
chown $NGINX_USER:$NGINX_USER /var/log/modsecurity
chmod 755 /var/log/modsecurity
# Download and compile ModSecurity 3
echo "[5/12] Downloading and compiling ModSecurity 3..."
cd /opt
git clone --depth 1 -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity.git
chown -R root:root ModSecurity
cd ModSecurity
git submodule init
git submodule update
./build.sh
./configure --enable-standalone-module
make -j$(nproc)
make install
ldconfig
# Get nginx version for module compilation
echo "[6/12] Preparing nginx module compilation..."
NGINX_VERSION=$(nginx -v 2>&1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1)
print_status "Detected nginx version: $NGINX_VERSION"
# Download and compile ModSecurity-nginx connector
echo "[7/12] Compiling ModSecurity-nginx connector..."
cd /opt
git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git
chown -R root:root ModSecurity-nginx
# Download nginx source
wget -q "http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz"
tar -xzf "nginx-${NGINX_VERSION}.tar.gz"
cd "nginx-${NGINX_VERSION}"
# Configure and build the dynamic module
./configure --with-compat --add-dynamic-module=../ModSecurity-nginx
make modules
# Install the module with proper permissions
mkdir -p "${NGINX_CONFIG_DIR}/modules"
cp objs/ngx_http_modsecurity_module.so "${NGINX_CONFIG_DIR}/modules/"
chown root:root "${NGINX_CONFIG_DIR}/modules/ngx_http_modsecurity_module.so"
chmod 644 "${NGINX_CONFIG_DIR}/modules/ngx_http_modsecurity_module.so"
# Download OWASP Core Rule Set
echo "[8/12] Installing OWASP Core Rule Set..."
cd /opt
wget -q https://github.com/coreruleset/coreruleset/archive/v4.0.0.tar.gz
tar -xzf v4.0.0.tar.gz
mv coreruleset-4.0.0 coreruleset
chown -R root:root coreruleset
chmod -R 644 coreruleset/*
find coreruleset -type d -exec chmod 755 {} \;
cp coreruleset/crs-setup.conf.example coreruleset/crs-setup.conf
# Create ModSecurity main configuration
echo "[9/12] Creating ModSecurity configuration..."
cat > /opt/modsecurity.conf << 'EOF'
SecRuleEngine On
SecRequestBodyAccess On
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072
SecRequestBodyInMemoryLimit 131072
SecRequestBodyLimitAction Reject
SecResponseBodyAccess On
SecResponseBodyMimeType text/plain text/html text/xml application/json
SecResponseBodyLimit 524288
SecResponseBodyLimitAction ProcessPartial
SecTmpDir /tmp/
SecDataDir /tmp/
# JSON Logging for SOAR Integration
SecAuditEngine On
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABIJDEFHZ
SecAuditLogType Serial
SecAuditLog /var/log/modsecurity/audit.log
SecAuditLogFormat JSON
SecAuditLogStorageDir /var/log/modsecurity/
# Enhanced security rules
SecRule REQUEST_HEADERS:Content-Type "(?:text|application)/xml" "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
SecRule RESPONSE_STATUS "@streq 404" "id:'200001',phase:5,pass,nolog,setvar:tx.allowed_request_content_type=|application/x-www-form-urlencoded| |multipart/form-data| |text/xml| |application/xml| |application/soap+xml| |application/x-amf| |application/json| |application/octet-stream| |text/plain|"
# Include OWASP CRS
Include /opt/coreruleset/crs-setup.conf
Include /opt/coreruleset/rules/*.conf
EOF
chown root:root /opt/modsecurity.conf
chmod 644 /opt/modsecurity.conf
# Configure nginx with ModSecurity
echo "[10/12] Configuring nginx with ModSecurity..."
# Load the module
sed -i '1i load_module modules/ngx_http_modsecurity_module.so;' "${NGINX_CONFIG_DIR}/nginx.conf"
# Create ModSecurity nginx configuration
mkdir -p "${NGINX_CONFIG_DIR}/conf.d"
cat > "${NGINX_CONFIG_DIR}/conf.d/modsecurity.conf" << 'EOF'
modsecurity on;
modsecurity_rules_file /opt/modsecurity.conf;
# Log format for SOAR integration
log_format modsec_json escape=json
'{'
'"timestamp":"$time_iso8601",'
'"remote_addr":"$remote_addr",'
'"request_method":"$request_method",'
'"request_uri":"$request_uri",'
'"status":"$status",'
'"body_bytes_sent":"$body_bytes_sent",'
'"http_referer":"$http_referer",'
'"http_user_agent":"$http_user_agent",'
'"request_time":"$request_time"'
'}';
access_log /var/log/nginx/modsec_access.log modsec_json;
EOF
chown root:root "${NGINX_CONFIG_DIR}/conf.d/modsecurity.conf"
chmod 644 "${NGINX_CONFIG_DIR}/conf.d/modsecurity.conf"
# Create webhook notification script if URL provided
echo "[11/12] Setting up SOAR integration..."
if [[ -n "$WEBHOOK_URL" ]]; then
cat > /usr/local/bin/modsec_webhook.sh << EOF
#!/bin/bash
WEBHOOK_URL="$WEBHOOK_URL"
tail -F /var/log/modsecurity/audit.log | while read line; do
if echo "\$line" | grep -q '"messages":\['; then
curl -X POST -H "Content-Type: application/json" -d "\$line" "\$WEBHOOK_URL" &
fi
done
EOF
chmod 755 /usr/local/bin/modsec_webhook.sh
chown root:root /usr/local/bin/modsec_webhook.sh
# Create systemd service for webhook
cat > /etc/systemd/system/modsec-webhook.service << EOF
[Unit]
Description=ModSecurity SOAR Webhook Service
After=network.target
[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/modsec_webhook.sh
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable modsec-webhook.service
print_status "SOAR webhook integration configured"
fi
# Start and enable services
echo "[12/12] Starting services and performing verification..."
systemctl enable nginx
systemctl restart nginx
if [[ -n "$WEBHOOK_URL" ]]; then
systemctl start modsec-webhook.service
fi
# Verification checks
print_status "Performing verification checks..."
# Check if nginx is running
if systemctl is-active --quiet nginx; then
print_status "✓ Nginx is running"
else
print_error "✗ Nginx is not running"
exit 1
fi
# Check if ModSecurity module is loaded
if nginx -t 2>&1 | grep -q "successful"; then
print_status "✓ Nginx configuration is valid"
else
print_error "✗ Nginx configuration has errors"
exit 1
fi
# Check log files
if [[ -f /var/log/modsecurity/audit.log ]]; then
print_status "✓ ModSecurity audit log is created"
else
print_warning "ModSecurity audit log not yet created (will be created on first request)"
fi
# Clean up build artifacts
rm -rf /opt/nginx-* /opt/v4.0.0.tar.gz
print_status "ModSecurity 3 with SOAR integration installed successfully!"
print_status "Configuration files:"
print_status " - ModSecurity config: /opt/modsecurity.conf"
print_status " - Nginx config: ${NGINX_CONFIG_DIR}/conf.d/modsecurity.conf"
print_status " - Audit logs: /var/log/modsecurity/audit.log"
if [[ -n "$WEBHOOK_URL" ]]; then
print_status " - SOAR webhook service: modsec-webhook.service"
fi
print_warning "Remember to configure your server blocks to include ModSecurity directives"
print_warning "Test the installation by triggering a security rule and checking the logs"
Review the script before running. Execute with: bash install.sh