Advanced Signals
Behavioural analysis, scoring and escalation-aware decay
Vulnerability Pattern Detection (vulnerability_rules.lua)
Responsible for direct pattern matching against URI requests to identify known vulnerability patterns or exploit kit signatures. Uses lua_pattern_utils.escape_pattern for safe pattern matching. The core function detect_vulnerability_pattern(uri, args, wcpay_checkout_user_header) analyzes request URIs to flag potential vulnerabilities.
Threat Alert Processing (suricata_rules.lua)
Turns eve.json alerts into per-IP reputation scores and reason strings, which feed routing stage
6 ("IP reputation"). Its functions are listed on Suricata Network
IDS; its decay is the shared policy below.
Behavioural & Sophistication Signals
Beyond matching a single request, sophistication_analyzer.lua classifies a whole session as
scripted, ai_assisted, manual or unknown using an inspectable
weighted rule set. Every contributing signal is returned in a signals list, and the confidence is
simply the winning class's share of the total weight — so the classification is auditable, not a black box.
| Signal | What it reads | Leans toward |
|---|---|---|
| Timing | Mean and standard deviation of inter-request gaps across the session. | Very regular, fast cadence → scripted; human-like variance → manual; in between → ai_assisted. |
| User-agent | Known scanner fragments, SDK/agent markers, or a normal browser string. | Scanner UA → scripted (+35); agent/SDK marker → ai_assisted (+35); browser UA → manual. |
| Headers | Presence of browser-like headers such as Accept-Language. | Present → manual (+20); absent → split evenly between scripted and ai_assisted (the UA/timing signals disambiguate). |
| Precision | How noisy vs targeted the matched patterns are. | Broad, noisy "spray" → scripted (+20); few precise high-value matches → ai_assisted / manual. |
Two further high-confidence signals feed the same picture:
- Honeytokens — a later request carrying one of the five injected fake credentials (API key, DB creds, admin password, S3 URL, JWT secret) confirms compromise. See Detection Capabilities.
- Device signature — the consent-gated, one-way GDPR signature re-recognises a returning adversary after a cookie and storage wipe, so a reset session does not launder prior risk.
AbuseIPDB Reporting Logic (abuseipdb_rules.lua)
Governs the deterministic decision-making process for reporting detected IP addresses to the AbuseIPDB service. Acts as a whitelist for reportability.
- Category Mapping: Maintains
_M.REASON_CATEGORIESmapping routing reasons to AbuseIPDB category IDs. - Reportability Check:
_M.is_reportable_reason(reason)checks if a reason is in the whitelist. - Comment Generation: Constructs detailed report comment, including associated CVEs.
Risk Scoring Model
Per-signal score deltas are listed once, by analyser stage, in
Detection → Detection Stages. Static assets are always skipped (0), the
accumulated score is capped at 100, and a session is diverted at the honeypot threshold of 80
(honeypot_threshold; see the Configuration Reference).
Escalation-Aware Decay (decay_policy.lua)
Shared by two risk-score decay paths: router_rules.decayed_score() (per-session) and suricata_rules.decayed_score() (per-IP reputation).
- The half-life multiplier grows linearly with offenses:
1 + decay_offense_slowdown × offenses, so repeat offenders fade progressively more slowly. - Past
permaflag_offensesoffenses, OR once the stored peak has ever reachedpermaflag_score, decay stops entirely (permaflag). - Default:
decay_offense_slowdown = 0.75,permaflag_offenses = 5,permaflag_score = 100.
The core of decay_policy.lua:
function _M.half_life_multiplier(offenses, slowdown)
offenses = tonumber(offenses) or 0
slowdown = tonumber(slowdown) or 0
if offenses <= 0 or slowdown <= 0 then return 1 end
return 1 + slowdown * offenses
end
-- in decay(), after the peak <= 0, no-elapsed-time and permaflag early returns:
local eff_half_life = base_half_life * _M.half_life_multiplier(offenses, cfg.decay_offense_slowdown)
return peak * (0.5 ^ (elapsed / eff_half_life))
With the defaults, a session with two prior offenses decays with a 2.5× longer half-life (750 s instead of 300 s).
The configured half-life is 300 s, but a recorded exploit test-scenario run measured the effective half-life at 529 s (95% CI 475–596 s, exponential fit R² = 0.99) — well outside the configured value. That is the escalation-aware slowdown working as designed: each prior offense adds linearly to the half-life multiplier, so a session that has already misbehaved fades more slowly than the base constant suggests. The decay the router applies is the curve the measurement tracks, not the raw 300 s.
Relevance: Ensures that only high-confidence, logic-driven signals (combining CVEs, Suricata alerts, and IP reputation hits) lead to external reporting.