package waf import ( "testing" "github.com/corazawaf/coraza/v3" ) // TestPhase2RequiresProcessRequestBody nagelt die Coraza-Semantik fest, die der // SPOE-Bug verletzt hatte: Phase-2-Regeln (SQLi 942xxx, XSS 941xxx — sie prüfen // ARGS aus dem Query-String) werden ERST von ProcessRequestBody() ausgewertet. // Koppelt man ProcessRequestBody an len(body)>0, bleiben GET-Requests ohne Body // von der gesamten Phase 2 ungeprüft. Dieser Test schlägt fehl, sollte jemand // den Aufruf je wieder body-abhängig machen. func TestPhase2RequiresProcessRequestBody(t *testing.T) { waf, err := coraza.NewWAF(coraza.NewWAFConfig().WithDirectives( "SecRuleEngine DetectionOnly\n" + "SecRule ARGS \"@rx attackpattern\" \"id:1234,phase:2,log,msg:'phase2-arg'\"\n")) if err != nil { t.Fatalf("NewWAF: %v", err) } tx := waf.NewTransaction() defer func() { tx.ProcessLogging(); _ = tx.Close() }() tx.ProcessConnection("1.2.3.4", 0, "", 0) tx.ProcessURI("/?x=attackpattern", "GET", "HTTP/1.1") // GET, kein Body tx.AddRequestHeader("Host", "test") tx.ProcessRequestHeaders() // Vor ProcessRequestBody darf die Phase-2-Regel noch NICHT gefeuert haben. if n := len(tx.MatchedRules()); n != 0 { t.Fatalf("vor ProcessRequestBody: %d Matches, erwarte 0", n) } if _, err := tx.ProcessRequestBody(); err != nil { t.Fatalf("ProcessRequestBody: %v", err) } // Jetzt MUSS die Phase-2-Regel gegen den Query-Arg gefeuert haben. found := false for _, mr := range tx.MatchedRules() { if mr.Rule().ID() == 1234 { found = true } } if !found { t.Fatal("Phase-2-Regel feuerte auch nach ProcessRequestBody nicht — " + "GET-Query-Args würden ungeprüft bleiben (SPOE-Bug)") } }