-
Notifications
You must be signed in to change notification settings - Fork 195
Description
Note: This bug was identified and fixed by Claude Code (Opus 4.5) during a debugging session.
Bug Report: ModSecurity Parser Fails to Match Apache Error Logs
Summary
The crowdsecurity/modsecurity parser (v1.3) fails to parse valid Apache ModSecurity log entries due to a space handling bug in the grok patterns APACHEERRORPREFIX2 and MODSECPREFIX2.
Environment
- CrowdSec version: 1.6.x
- Parser version: crowdsecurity/modsecurity v1.3
- OS: Debian 13 (Trixie)
- Apache version: 2.4.x with mod_security2
- ModSecurity CRS: 3.3.7
Symptoms
- ModSecurity logs are read from
/var/log/apache2/error.logbut never parsed cscli explain --type modsecurityshows parser failurecscli metrics show parsersshows 0 hits forcrowdsecurity/modsecurity- Attackers triggering ModSecurity rules are never banned
Root Cause Analysis
The bug is in the space handling between two patterns:
Pattern 1: APACHEERRORPREFIX2
\\[%{APACHEERRORTIME:timestamp}\\] \\[%{NOTSPACE:apacheseverity}\\] (\\[pid %{INT}(:tid %{INT})?\\] )?\\[(client|remote) %{IPORHOST:sourcehost}(:%{INT:source_port})?\\] (\\[client %{IPORHOST}\\])?Note the ending: \\] (\\[client %{IPORHOST}\\])?
There is a space before the optional [client IP] group.
Pattern 2: MODSECPREFIX2
%{APACHEERRORPREFIX2} ModSecurity: ...Note: There is a space after %{APACHEERRORPREFIX2}.
The Problem
For a log line like:
[Mon Dec 15 05:34:22 2025] [security2:error] [pid 123:tid 456] [client 192.168.1.1:12345] ModSecurity: Warning...
APACHEERRORPREFIX2matches up to[client 192.168.1.1:12345]- After the closing
], there's a space in the log - The pattern
] (\\[client ...)consumes that space while trying to match the optional group - The optional group
(\\[client %{IPORHOST}\\])?fails (next chars areModSecurity, not[client) - Since it's optional, the group is skipped, but the space was already consumed
MODSECPREFIX2then expects another space beforeModSecurity:- But the space was already consumed, so the match fails
Fix
Move the space inside the optional group, so it's only consumed when the group actually matches:
Before (broken)
APACHEERRORPREFIX2: "...\\] (\\[client %{IPORHOST}\\])?"
MODSECPREFIX2: "%{APACHEERRORPREFIX2} ModSecurity: ..."After (fixed)
APACHEERRORPREFIX2: "...\\] (\\[client %{IPORHOST}\\] )?"
MODSECPREFIX2: "%{APACHEERRORPREFIX2}ModSecurity: ..."Changes:
- Add space inside optional group:
(\\[client %{IPORHOST}\\])?→(\\[client %{IPORHOST}\\] )? - Remove space after prefix:
%{APACHEERRORPREFIX2} ModSecurity:→%{APACHEERRORPREFIX2}ModSecurity:
Verification
Before fix
$ echo '[Mon Dec 15 05:34:22 2025] [security2:error] [pid 123:tid 456] [client 192.168.1.1:12345] ModSecurity: Warning. test. [file "/test.conf"] [line "1"] [id "123"] [msg "test"] [severity "CRITICAL"] [hostname "test"] [uri "/"] [unique_id "abc"]' | cscli explain --type modsecurity -f -
├ s01-parse
| └ 🔴 crowdsecurity/modsecurity
└-------- parser failure 🔴After fix
$ echo '[Mon Dec 15 05:34:22 2025] [security2:error] [pid 123:tid 456] [client 192.168.1.1:12345] ModSecurity: Warning. test. [file "/test.conf"] [line "1"] [id "123"] [msg "test"] [severity "CRITICAL"] [hostname "test"] [uri "/"] [unique_id "abc"]' | cscli explain --type modsecurity -f -
├ s01-parse
| └ 🟢 crowdsecurity/modsecurity (+36 ~2)
├-------- parser success 🟢
├ Scenarios
└ 🟢 crowdsecurity/modsecurityPatch
Apply this patch to /etc/crowdsec/parsers/s01-parse/modsecurity.yaml:
# Fix 1: Move space inside optional [client IP] group
sed -i 's/(\\[client %{IPORHOST}\\])?/(\\[client %{IPORHOST}\\] )?/g' /etc/crowdsec/parsers/s01-parse/modsecurity.yaml
# Fix 2: Remove extra space between APACHEERRORPREFIX2 and ModSecurity
sed -i 's/%{APACHEERRORPREFIX2} ModSecurity:/%{APACHEERRORPREFIX2}ModSecurity:/g' /etc/crowdsec/parsers/s01-parse/modsecurity.yaml
# Reload CrowdSec
systemctl reload crowdsecAdditional Notes
Apache ErrorLogFormat
For CrowdSec compatibility, Apache's error log format should not include microseconds. The default Debian 13 format includes microseconds which the %{TIME} grok pattern cannot parse.
Recommended Apache configuration (/etc/apache2/conf-available/error-log-format.conf):
# CrowdSec compatibility: no microseconds
ErrorLogFormat "[%{%a %b %d %H:%M:%S %Y}t] [%-m:%l] [pid %P:tid %T] [client %{c}a] %M"Enable with:
a2enconf error-log-format
systemctl reload apache2Affected Versions
- crowdsecurity/modsecurity v1.3 (current as of December 2025)