Built-in attack detection engine, signature rules, and firewall defense
1. Running Threat Detection (--detect)
Enable the security detection engine using the --detect / -d flag:
caddy-analyze --detect /var/log/caddy/access.log
Per-IP Suspicious Request Details
The security report shows the actual suspicious requests per offending IP, including detection type, description, HTTP method, and path:
- 192.168.1.100 15 malicious requests
[sql_injection] SQL injection attempt GET /search?id=1' OR '1'='1
[scanner] Scanner / automated tool detected GET /admin
This information is available in all output formats (table, JSON, CSV, HTML).
2. URL Unescaping & Evasion Prevention
Before evaluating detection rules, caddy-analyze automatically unescapes URL percent-encodings (e.g., converting %2e%2e%2f to ../ and %3Cscript%3E to <script>) to prevent attackers from bypassing security rules using URL encoding tricks. Additionally, a second pass matches against the raw (non-unescaped) URI to catch multibyte-encoded traversal sequences (%c0%ae%c0%ae%c0%af, %252e%252e%252f) and internal host probe attempts that would be lost after unescaping.
Memory Bounding
The detection engine bounds memory usage on huge logs via two mechanisms:
LRU IP eviction โ at most 100,000 distinct client IPs are tracked (configurable via Detector.SetIPCap). When the cap is reached, the least recently used IP is evicted. Actively-used IPs are never dropped, preserving detection accuracy for real attackers.
Per-IP path cap โ at most 1,000 distinct paths per IP are tracked for beaconing/object-enumeration detection, preventing an attacker with many endpoints from exhausting memory.
3. Threat Rule Specification (26 Categories)
Every detection carries a confidence score (1โ10) based on pattern specificity, and MITRE ATT&CK technique IDs for SOC mapping. The engine ships 171 signature patterns across the 26 categories below. The patterns listed under each card are representative examples โ each card also shows the real number of signatures it contains (e.g. SQL injection matches 19 distinct rule families, from UNION SELECT and comment-bypass to time-based blind and out-of-band exfiltration).
๐SQL Injection
UNION SELECT, OR 1=1, pg_sleep, INTO OUTFILE, @@version, etc.
19 signatures
T1190conf 6โ10
๐NoSQL Injection
$ne, $gt, $regex, $where, $nin, %24ne, etc.
3 signatures
T1190conf 7โ8
๐XSS
<script, onerror=, onfocus=, alert(, document.cookie, data:text/html, etc.
18 signatures
T1059.007T1189conf 2โ9
๐งฉSSTI
__class__, __mro__, freemarker, nunjucks, {{7*7}}, os.popen, <#assign, <%=, __${...}__, etc.
6 signatures
T1190conf 8โ9
๐SSRF
169.254.169.254, 0x7f000001, gopher://, dict://, redis://, etc.
11 signatures
T1190conf 6โ10
โกRCE
/bin/sh, whoami, /dev/tcp/, powershell, certutil, eval(), rO0AB, _$$ND_FUNC$$_, etc.
23 signatures
T1059T1190conf 7โ10
๐Path Traversal / LFI
../, ..%00, /etc/passwd, /proc/self/*, php://input, etc.
10 signatures
T1083conf 6โ9
๐GraphQL Introspection
__schema, __type, IntrospectionQuery, etc.
3 signatures
T1595.002conf 6โ8
โLog4j / JNDI
${jndi:ldap://, ${env:, ${lower:jndi, ${::-j}, etc.
4 signatures
T1190T1059conf 5โ10
๐XXE / XInclude
<!ENTITY, SYSTEM, PUBLIC, xi:include, xpointer, etc.
6 signatures
T1190conf 8โ9
โช๏ธOpen Redirect
?url=http://, ?redirect=//, //evil.com, ?url=/\, etc.
5 signatures
T1566.002conf 7
๐LDAP Injection
(&(, (|(, )(|(, URL-encoded operators, etc.
2 signatures
T1190conf 7โ8
๐งญXPath Injection
]|//*, .//*, etc.
2 signatures
T1190conf 7
โฉ๏ธCRLF / Log Injection
%0d%0aSet-Cookie:, %0d%0aLocation:, literal CRLF, %E5%98%8A%E5%98%8D, etc.
4 signatures
T1190T1059conf 5โ8
๐งฌPrototype Pollution
__proto__, constructor.prototype, JSON payloads, etc.
2 signatures
T1190T1059.007conf 7โ8
๐กSSI Injection
<!--#exec cmd=, #include virtual=, #echo var=, etc.
Use --audit-log <path> to record every block and unblock action as a JSON-lines file. Each entry includes timestamp, action, IP, reason, ban duration, and the user who ran the command. The file is created with 0600 permissions. Available on guard, block, and unban subcommands.
sudo caddy-analyze guard --audit-log /var/log/caddy-analyzer/audit.jsonl docker://my-caddy
# Example entry:
{"ts":"2025-01-15T14:29:01Z","action":"block","ip":"203.0.113.5","reason":"12 malicious request(s)","duration":"24h0m0s","user":"root"}
# Other reasons you may see: " auth failures", " not found", " requests",
# " requests from (distributed scan)", "cred_stuffing", "threat_intel: score= (...)"
State Persistence
Use --state-file <path> to persist blocked-IP state across guard restarts. When the guard daemon restarts, it reloads previously blocked IPs, cleans up expired bans, and resumes enforcement. Without this flag, all bans are lost on restart. The block and unban commands also accept --state-file to sync manual blocks/unbans with the guard's persisted state.
Use --never-block to specify IPs/CIDRs that should never be banned, protecting trusted gateways, proxies, or health-check IPs from false-positive blocks. Use --never-block-file to load a larger allowlist from a file (one IP/CIDR per line, # comments supported). The two flags can be combined โ entries are merged.
Besides rate and status thresholds, guard also blocks IPs whose requests match security patterns (SQLi, XSS, RCE, etc.). Use --detect-confidence <1-10> to set the minimum confidence score required to trigger a block (default 8); detections below the threshold are reported in the audit log but not blocked. Pass 0 to disable pattern-based blocking entirely:
โ Danger
Setting --detect-confidence 0disables all pattern-based blocking. Only rate and status thresholds will trigger blocks. SQLi, XSS, RCE, and Log4j attacks will pass through unblocked if they don't exceed rate limits.
Every detection is assigned a confidence score from 1 (low) to 10 (high) based on the specificity and reliability of the matched pattern. High-confidence patterns (e.g. UNION SELECT, ${jndi:ldap://) score 9โ10, while broad or ambiguous patterns (e.g. onerror= which can appear in legitimate payloads) score 3โ5. This allows downstream consumers to filter noise and prioritize high-signal detections.
5. MITRE ATT&CK Tags
Every detection carries MITRE ATT&CK technique IDs (e.g. T1190 for Exploit Public-Facing Application, T1595 for Active Scanning). This lets SOC analysts build ATT&CK Navigator coverage layers from caddy-analyzer output and map detections to adversary techniques. Tags are included in JSON output and Sigma rules.
6. Sigma Rule Export
Export 23 detection categories as Sigma YAML rules for SIEM import (Splunk, Elastic, Sigma-compatible SIEMs). Rules include MITRE ATT&CK tags, deterministic UUIDs, and dynamically-constructed detection conditions. Validate with sigma check.
โน Note
The 3 behavioral detections (ua_rotation, object_enumeration, beaconing) are not pattern-based and are not exported as Sigma rules. They require temporal analysis across multiple requests and cannot be expressed as static patterns.
Use --defang to defang IPs and URLs in all output formats for safe sharing of reports containing IOCs. IPs are defanged (192.168.1.1 โ 192[.]168[.]1[.]1) and URL schemes are defanged (http:// โ hxxp://, https:// โ hxxps://). Works across all commands: report, detect, top, tail, diff, and log listing mode.
caddy-analyze --detect --defang access.log
caddy-analyze top ip --defang access.log
caddy-analyze tail --defang access.log