ModSecurity WAF

Web Application Firewall integration with bundled CoreRuleSet

API-Fence includes integrated ModSecurity WAF support with bundled OWASP CoreRuleSet (CRS) v4.0.0 rules, providing zero-configuration protection against common web attacks.

Overview

ModSecurity integration provides:

  • SQL Injection (SQLi) detection (CRS rule 942)
  • Cross-Site Scripting (XSS) detection (CRS rule 941)
  • Remote Code Execution (RCE) detection (CRS rule 932)
  • Local/Remote File Inclusion (LFI/RFI) detection (CRS rules 930, 931)
  • Protocol Enforcement (CRS rules 920, 921)
  • JSON-aware scanning with optimized string extraction
  • Dual ruleset support for seamless CRS version migration

Quick Start

Enable WAF scanning with bundled CRS rules:

{
  "api_name": "my_api",
  "openapi_spec_path": "/etc/envoy/openapi.yaml",
  "modsecurity": {
    "scan_request": true,
    "primary_ruleset": {
      "name": "crs",
      "use_bundled_crs": true
    }
  }
}

This enables request body scanning with all bundled CRS rules using default settings.

Configuration

Basic Options

{
  "modsecurity": {
    "scan_request": true,
    "scan_response": false,
    "scan_response_as_request": false,
    "request_action": "block",
    "response_action": "alert"
  }
}
OptionTypeDefaultDescription
scan_requestbooleanfalseEnable WAF scanning of request bodies
scan_responsebooleanfalseEnable WAF scanning of response bodies
scan_response_as_requestbooleanfalseUse request-oriented rules for response scanning (more thorough)
request_actionstring"block"Action when request matches: "block" or "alert"
response_actionstring"alert"Action when response matches: "block" or "alert"

Actions

  • block: Reject the request/response with an error (403 Forbidden)
  • alert: Log the match and set metadata, but allow through

Use alert mode initially to assess rule matches before enforcing with block.

Ruleset Configuration

Bundled CRS

API-Fence bundles OWASP CoreRuleSet v4.0.0 rules. Enable with:

{
  "primary_ruleset": {
    "name": "crs",
    "use_bundled_crs": true,
    "bundled_crs_profile": "full"
  }
}

CRS Profiles

Choose a profile based on your performance and security requirements:

ProfileRules IncludedUse Case
fullAll bundled CRS rules (request + response)Maximum protection, higher latency
requestRequest rules only (SQLi, XSS, RCE, LFI)Balanced protection, no response scanning overhead
minimalSQLi (942), XSS (941), RCE (932) onlyFastest, protects against most critical attacks
{
  "primary_ruleset": {
    "name": "crs_minimal",
    "use_bundled_crs": true,
    "bundled_crs_profile": "minimal"
  }
}

Custom Rules

File-based Rules

Load rules from files (supports glob patterns):

{
  "primary_ruleset": {
    "name": "custom",
    "rules_path": [
      "/etc/modsecurity/crs/*.conf",
      "/etc/modsecurity/custom-rules.conf"
    ]
  }
}

Inline Rules

Define rules directly in configuration:

{
  "primary_ruleset": {
    "name": "inline",
    "rules_inline": "SecRule REQUEST_URI \"@contains /admin\" \"id:1000,phase:1,deny,status:403,msg:'Admin access blocked'\""
  }
}

Remote Rules

Fetch rules from a URL:

{
  "primary_ruleset": {
    "name": "remote",
    "rules_remote": {
      "url": "https://rules.example.com/modsec-rules.conf",
      "key": "api-key-for-auth"
    }
  }
}

Combining Rule Sources

You can combine bundled CRS with custom rules:

{
  "primary_ruleset": {
    "name": "combined",
    "use_bundled_crs": true,
    "bundled_crs_profile": "minimal",
    "rules_inline": "SecRule REQUEST_HEADERS:X-Custom-Header \"@rx dangerous\" \"id:10001,phase:1,deny\""
  }
}

Dual Ruleset Migration

When upgrading CRS versions, use dual rulesets to test new rules alongside existing ones:

{
  "modsecurity": {
    "scan_request": true,
    "primary_ruleset": {
      "name": "crs_3.3",
      "rules_path": ["/etc/modsecurity/crs-3.3/*.conf"]
    },
    "secondary_ruleset": {
      "name": "crs_4.0",
      "use_bundled_crs": true,
      "bundled_crs_profile": "full"
    }
  }
}

Behavior:

  • Both rulesets are evaluated for every request
  • If both match, the secondary (new) result is used for enforcement
  • Metrics track matches for both rulesets separately
  • Allows gradual migration with full visibility

Scanner Pool Configuration

Configure the scanner thread pool:

{
  "modsecurity": {
    "scan_request": true,
    "pool": {
      "timeout_ms": 100,
      "timeout_action": "allow",
      "queue_capacity": 1000
    },
    "primary_ruleset": {
      "name": "crs",
      "use_bundled_crs": true
    }
  }
}
OptionTypeDefaultDescription
timeout_msinteger100Maximum scan time (milliseconds)
timeout_actionstring"allow"Action on timeout: "allow" (fail open) or "block" (fail closed)
queue_capacityinteger1000Maximum pending scan jobs

Note: The global thread count is controlled by the API_FENCE_MODSEC_THREADS environment variable (defaults to number of CPUs).

String Extraction Configuration

For JSON request bodies, API-Fence extracts string values for efficient scanning:

{
  "modsecurity": {
    "string_extraction": {
      "max_unique_strings": 1000,
      "min_string_length": 1,
      "max_string_length": 10000,
      "skip_base64": true
    }
  }
}
OptionTypeDefaultDescription
max_unique_stringsinteger1000Maximum unique strings to extract
min_string_lengthinteger1Minimum string length to include
max_string_lengthinteger10000Maximum string length to include
skip_base64booleantrueSkip base64-encoded strings (reduces false positives)

Complete Example

{
  "api_name": "secure_api",
  "openapi_spec_path": "/etc/envoy/openapi.yaml",
  "validation": {
    "validate_request": true,
    "fail_on_request_error": true
  },
  "modsecurity": {
    "scan_request": true,
    "scan_response": false,
    "request_action": "block",
    "pool": {
      "timeout_ms": 150,
      "timeout_action": "allow",
      "queue_capacity": 2000
    },
    "string_extraction": {
      "max_unique_strings": 500,
      "skip_base64": true
    },
    "primary_ruleset": {
      "name": "crs",
      "use_bundled_crs": true,
      "bundled_crs_profile": "request"
    }
  }
}

Deployment Recommendations

Start with Alert Mode

Begin with request_action: "alert" to monitor rule matches without blocking:

{
  "modsecurity": {
    "scan_request": true,
    "request_action": "alert",
    "primary_ruleset": {
      "name": "crs",
      "use_bundled_crs": true
    }
  }
}

Review logs and tune rules before switching to block.

Profile Selection

ScenarioRecommended Profile
High-security APIfull
Public-facing APIrequest
Internal microserviceminimal
Latency-sensitiveminimal

Timeout Configuration

  • Low latency APIs: Use timeout_ms: 50 with timeout_action: "allow"
  • High security APIs: Use timeout_ms: 200 with timeout_action: "block"

Troubleshooting

High Latency

If ModSecurity scanning adds too much latency:

  1. Switch to minimal profile
  2. Reduce max_unique_strings in string extraction
  3. Ensure adequate thread pool size via API_FENCE_MODSEC_THREADS

False Positives

If legitimate requests are blocked:

  1. Start with alert mode to identify patterns
  2. Add rule exclusions via inline rules
  3. Consider minimal profile which has fewer false positives

Memory Usage

The scanner thread pool and rule compilation use memory. Monitor:

  • Reduce queue_capacity if memory is constrained
  • Use minimal profile to reduce rule memory footprint