fix(waf): GET-Requests ohne Body wurden von allen Phase-2-Regeln nie geprüft — v1.3.18

Schwerwiegende WAF-Lücke: der SPOE-Agent rief tx.ProcessRequestBody() nur bei
len(body)>0 auf. In Coraza wird die GESAMTE Phase 2 (SQLi 942xxx, XSS 941xxx,
LFI/RCE — alle prüfen ARGS aus dem Query-String) aber erst von
ProcessRequestBody() ausgewertet. Damit lief jeder GET-Request ohne Body
komplett ungeprüft an den Injection-Regeln vorbei — der häufigste
Web-Angriffsvektor (?id=1' OR 1=1, ?x=<script>) war blind. Nur Requests MIT
Body (POST/PUT/PROPFIND-XML) wurden inspiziert.

Fix: ProcessRequestBody() läuft jetzt IMMER (mit/ohne Body). Regressionstest
TestPhase2RequiresProcessRequestBody nagelt die Semantik fest.

Alle 9 aktiven WAF-Domains sind in Detection-Modus → der Fix erzeugt nur mehr
(echte) Alerts, blockt nichts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Debian
2026-08-04 10:00:17 +02:00
parent 5c268425c1
commit de153dc13a
3 changed files with 67 additions and 9 deletions

View File

@@ -131,14 +131,22 @@ func (a *SPOEAgent) handle(ctx context.Context, w *encoding.ActionWriter, m *enc
// liefert den Body via `option http-buffer-request` (bis tune.bufsize) —
// größere Bodies werden zur Prüfung gekappt. Content-Type kam bereits
// über die Header, sodass Coraza urlencoded/multipart/json korrekt parst.
if interruption == nil && len(body) > 0 {
if it, _, err := tx.WriteRequestBody(body); err != nil {
slog.Warn("waf: WriteRequestBody", "error", err)
} else if it != nil {
interruption = it
} else {
it, err := tx.ProcessRequestBody()
if err != nil {
if interruption == nil {
if len(body) > 0 {
if it, _, err := tx.WriteRequestBody(body); err != nil {
slog.Warn("waf: WriteRequestBody", "error", err)
} else if it != nil {
interruption = it
}
}
// ProcessRequestBody MUSS immer laufen — auch ohne Body. In Coraza wird
// die GESAMTE Phase 2 (SQLi 942xxx, XSS 941xxx, die den Query-String/ARGS
// prüfen) erst hier ausgewertet. Wurde das an len(body)>0 gekoppelt,
// blieben GET-Requests ohne Body von allen Phase-2-Regeln ungeprüft →
// Query-String-Angriffe (?id=1' OR 1=1, ?x=<script>) liefen komplett
// durch. Der häufigste Web-Angriffsvektor war damit blind.
if interruption == nil {
if it, err := tx.ProcessRequestBody(); err != nil {
slog.Warn("waf: ProcessRequestBody", "error", err)
} else if it != nil {
interruption = it