Skip to content

Commit

Permalink
wip: crs 4.5, albedo
Browse files Browse the repository at this point in the history
  • Loading branch information
M4tteoP committed Aug 3, 2024
1 parent 010509a commit 6929283
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 49 deletions.
16 changes: 13 additions & 3 deletions testing/coreruleset/.ftw.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
---
testoverride:
ignore:
920100-4: 'Invalid uri, Coraza not reached - 404 page not found'
920100-5: 'Invalid uri, Coraza not reached - 404 page not found'
920100-8: 'Go/http allows a colon in the path. Test expects status 400 or 403 (Apache behaviour)'
920270-4: 'Rule works, log contains 920270. Test expects status 400 (Apache behaviour)'
920272-5: 'Rule works, log contains 920272. Test expects status 400 (Apache behaviour)'
920290-1: 'Rule works, log contains 920290. Test expects status 400 (Apache behaviour)'
920290-4: 'Go/http returns 400 Bad Request: missing required Host header'
920430-8: 'Go/http does not allow HTTP/3.0 - 505 HTTP Version Not Supported'
932200-13: 'wip'
930110-7: 'CRS issue: https://github.com/coreruleset/coreruleset/issues/3736'

# TODO: investigate
932200-13: 'Failing only in multiphase evalution'
932300-10: 'Failing only in multiphase evalution'
933120-2: 'Failing only in multiphase evalution'
920274-1: ''
920280-3: ''
920430-3: ''
920430-5: ''
920430-9: ''
920610-2: ''
920620-1: ''

124 changes: 124 additions & 0 deletions testing/coreruleset/albedo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// Copyright 2024 Juan Pablo Tosso and the OWASP Coraza contributors
// SPDX-License-Identifier: Apache-2.0

// These benchmarks don't currently compile with TinyGo
//go:build !tinygo
// +build !tinygo

// Note: The following code has been extracted from https://github.com/coreruleset/albedo/blob/main/server/server.go
// TODO: Make it possible to import albedo.
package coreruleset

import (
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io"
"log"
"net/http"
"strings"
"testing"
)

type reflectionSpec struct {
Status int `json:"status"`
Headers map[string]string `json:"headers"`
Body string `json:"body"`
EncodedBody string `json:"encodedBody"`
LogMessage string `json:"logMessage"`
}

func handleReflect(t testing.TB, w http.ResponseWriter, r *http.Request) {
log.Println("Received reflection request")

body, err := io.ReadAll(r.Body)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
_, err = w.Write([]byte("Failed to parse request body"))
if err != nil {
log.Printf("Failed to write response body: %s", err.Error())
}
log.Println("Failed to parse request body")
return
}
spec := &reflectionSpec{}
if err = json.Unmarshal(body, spec); err != nil {
w.WriteHeader(http.StatusBadRequest)
_, err = w.Write([]byte("Invalid JSON in request body"))
if err != nil {
log.Printf("Failed to write response body: %s", err.Error())
}
log.Println("Invalid JSON in request body")
return
}

if spec.LogMessage != "" {
log.Println(spec.LogMessage)
}

for name, value := range spec.Headers {
log.Printf("Reflecting header '%s':'%s'", name, value)
w.Header().Add(name, value)
}

if spec.Status > 0 && spec.Status < 100 || spec.Status >= 600 {
w.WriteHeader(http.StatusBadRequest)
_, err = w.Write([]byte(fmt.Sprintf("Invalid status code: %d", spec.Status)))
if err != nil {
log.Printf("Failed to write response body: %s", err.Error())
}
log.Printf("Invalid status code: %d", spec.Status)
return
}
status := spec.Status
if status == 0 {
status = http.StatusOK
}
log.Printf("Reflecting status '%d'", status)
w.WriteHeader(status)

responseBody, err := decodeBody(t, spec)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
_, err = w.Write([]byte(err.Error()))
if err != nil {
log.Printf("Failed to write response body: %s", err.Error())
}
log.Println(err.Error())
return
}

if responseBody == "" {
return
}

responseBodyBytes := []byte(responseBody)
if len(responseBody) > 200 {
responseBody = responseBody[:min(len(responseBody), 200)] + "..."
}
log.Printf("Reflecting body '%s'", responseBody)
_, err = w.Write(responseBodyBytes)
if err != nil {
log.Printf("Failed to write response body: %s", err.Error())
}
}

func decodeBody(t testing.TB, spec *reflectionSpec) (string, error) {
t.Helper()
if spec.Body != "" {
return spec.Body, nil
}

if spec.EncodedBody == "" {
return "", nil
}

decoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(spec.EncodedBody))
bodyBytes, err := io.ReadAll(decoder)
if err != nil {
return "", errors.New("invalid base64 encoding of response body")

}
return string(bodyBytes), nil
}
41 changes: 12 additions & 29 deletions testing/coreruleset/coreruleset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,31 +221,12 @@ SecRule REQUEST_HEADERS:X-CRS-Test "@rx ^.*$" \
}

s := httptest.NewServer(txhttp.WrapHandler(waf, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Emulates https://github.com/coreruleset/albedo behavior
defer r.Body.Close()
w.Header().Set("Content-Type", "text/plain")
switch {
case r.URL.Path == "/anything", r.URL.Path == "/post":
body, err := io.ReadAll(r.Body)
// Emulated httpbin behaviour: /anything and /post endpoints act as an echo server, writing back the request body
if r.Header.Get("Content-Type") == "application/x-www-form-urlencoded" {
// Tests 954120-1 and 954120-2 are the only two calling /anything with a POST and payload is urlencoded
if err != nil {
t.Fatalf("handler can not read request body: %v", err)
}
urldecodedBody, err := url.QueryUnescape(string(body))
if err != nil {
t.Logf("[warning] handler can not unescape urlencoded request body: %v", err)
// If the body can't be unescaped, we will keep going with the received body
urldecodedBody = string(body)
}
fmt.Fprint(w, urldecodedBody)
} else {
_, err = w.Write(body)
if err != nil {
t.Fatalf("handler can not write request body: %v", err)
}
}

case r.URL.Path == "/reflect":
handleReflect(t, w, r)
case strings.HasPrefix(r.URL.Path, "/base64/"):
// Emulated httpbin behaviour: /base64 endpoint write the decoded base64 into the response body
b64Decoded, err := b64.StdEncoding.DecodeString(strings.TrimPrefix(r.URL.Path, "/base64/"))
Expand All @@ -254,8 +235,7 @@ SecRule REQUEST_HEADERS:X-CRS-Test "@rx ^.*$" \
}
fmt.Fprint(w, string(b64Decoded))
default:
// Common path "/status/200" defaults here
fmt.Fprint(w, "Hello!")
// Albedo return 200 with no body
}
})))
defer s.Close()
Expand All @@ -266,7 +246,7 @@ SecRule REQUEST_HEADERS:X-CRS-Test "@rx ^.*$" \
if err != nil {
return err
}
ftwt, err := test.GetTestFromYaml(yaml)
ftwt, err := test.GetTestFromYaml(yaml, path)
if err != nil {
return err
}
Expand All @@ -292,16 +272,19 @@ SecRule REQUEST_HEADERS:X-CRS-Test "@rx ^.*$" \
cfg.WithLogfile(errorPath)
cfg.TestOverride.Overrides.DestAddr = &host
cfg.TestOverride.Overrides.Port = &port

res, err := runner.Run(cfg, tests, runner.RunnerConfig{
ShowTime: false,
}, output.NewOutput("quiet", os.Stdout))
if err != nil {
t.Fatal(err)
}

if len(res.Stats.Failed) > 0 {
t.Errorf("failed tests: %v", res.Stats.Failed)
totalIgnored := len(res.Stats.Ignored)
if totalIgnored > 0 {
t.Logf("[info] %d ignored tests: %v", totalIgnored, res.Stats.Ignored)
}
totalFailed := len(res.Stats.Failed)
if totalFailed > 0 {
t.Errorf("[fatal] %d failed tests: %v", totalFailed, res.Stats.Failed)
}
}

Expand Down
11 changes: 6 additions & 5 deletions testing/coreruleset/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ go 1.21

require (
github.com/bmatcuk/doublestar/v4 v4.6.1
github.com/corazawaf/coraza-coreruleset/v4 v4.3.0
github.com/corazawaf/coraza-coreruleset/v4 v4.5.0
github.com/corazawaf/coraza/v3 v3.0.0-00010101000000-000000000000
github.com/coreruleset/go-ftw v0.6.4
github.com/coreruleset/go-ftw v1.0.3
github.com/rs/zerolog v1.33.0
)

Expand All @@ -15,8 +15,8 @@ require (
github.com/Masterminds/semver v1.5.0 // indirect
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
github.com/corazawaf/libinjection-go v0.2.1 // indirect
github.com/coreruleset/ftw-tests-schema v1.1.0 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/coreruleset/ftw-tests-schema/v2 v2.1.0 // indirect
github.com/fatih/color v1.17.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect
github.com/goccy/go-yaml v1.11.3 // indirect
Expand All @@ -28,7 +28,7 @@ require (
github.com/knadh/koanf/maps v0.1.1 // indirect
github.com/knadh/koanf/parsers/yaml v0.1.0 // indirect
github.com/knadh/koanf/providers/env v0.1.0 // indirect
github.com/knadh/koanf/providers/file v0.1.0 // indirect
github.com/knadh/koanf/providers/file v1.1.0 // indirect
github.com/knadh/koanf/providers/rawbytes v0.1.0 // indirect
github.com/knadh/koanf/v2 v2.1.1 // indirect
github.com/kyokomi/emoji/v2 v2.2.13 // indirect
Expand All @@ -46,6 +46,7 @@ require (
golang.org/x/net v0.27.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
rsc.io/binaryregexp v0.2.0 // indirect
Expand Down
26 changes: 14 additions & 12 deletions testing/coreruleset/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZC
github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I=
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/corazawaf/coraza-coreruleset/v4 v4.3.0 h1:izzVRUxfvVf1OXhRQXpFm1jj3g/cIlLu9SiNzXOW7XU=
github.com/corazawaf/coraza-coreruleset/v4 v4.3.0/go.mod h1:RQMGurig+irQq7v21yq7rM/9SAEf1bT6hCSplJ0ByKY=
github.com/corazawaf/coraza-coreruleset/v4 v4.5.0 h1:4BDr9/yWKSJ7Ch3h7SvSqJBASju73+EqIIF0WxjsFgQ=
github.com/corazawaf/coraza-coreruleset/v4 v4.5.0/go.mod h1:1FQt1p+JSQ6tYrafMqZrEEdDmhq6aVuIJdnk+bM9hMY=
github.com/corazawaf/libinjection-go v0.2.1 h1:vNJ7L6c4xkhRgYU6sIO0Tl54TmeCQv/yfxBma30Dy/Y=
github.com/corazawaf/libinjection-go v0.2.1/go.mod h1:OP4TM7xdJ2skyXqNX1AN1wN5nNZEmJNuWbNPOItn7aw=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/coreruleset/ftw-tests-schema v1.1.0 h1:3+NYrdLE3HVmOc3nGrisRBBvY9lGjePUrV+YkT5Ay3s=
github.com/coreruleset/ftw-tests-schema v1.1.0/go.mod h1:gRd9wBxjUI85HypWRDxJzbk1JqHC4KTxl0l/Y2p9QK4=
github.com/coreruleset/go-ftw v0.6.4 h1:EdDNld38Jv4lxqHS+csGOJuHu1/8rpp4TlrFyoijTPk=
github.com/coreruleset/go-ftw v0.6.4/go.mod h1:IayMjfOmmNNBcqTcZU92e6UZTy79/eFdmJEmRu8tLs4=
github.com/coreruleset/ftw-tests-schema/v2 v2.1.0 h1:2ilKzKRG5UzzxBcrJLXFtPalStdQ9jzzaYFuFk0OEk0=
github.com/coreruleset/ftw-tests-schema/v2 v2.1.0/go.mod h1:ZHVFX5ses4+5IxUP0ufCNg/VqRWxziH6ZuUca092Hxo=
github.com/coreruleset/go-ftw v1.0.3 h1:DVqoTvBGXtAd0knvlyxr7d/bk1xMkzq8cfSbjxeOxLI=
github.com/coreruleset/go-ftw v1.0.3/go.mod h1:NzYL8DIoAbulVVneBlnudFdlJziO3mJU3iIV2fZK46U=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
github.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7DlmewI=
github.com/foxcpp/go-mockdns v1.1.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
Expand Down Expand Up @@ -52,8 +52,8 @@ github.com/knadh/koanf/parsers/yaml v0.1.0 h1:ZZ8/iGfRLvKSaMEECEBPM1HQslrZADk8fP
github.com/knadh/koanf/parsers/yaml v0.1.0/go.mod h1:cvbUDC7AL23pImuQP0oRw/hPuccrNBS2bps8asS0CwY=
github.com/knadh/koanf/providers/env v0.1.0 h1:LqKteXqfOWyx5Ab9VfGHmjY9BvRXi+clwyZozgVRiKg=
github.com/knadh/koanf/providers/env v0.1.0/go.mod h1:RE8K9GbACJkeEnkl8L/Qcj8p4ZyPXZIQ191HJi44ZaQ=
github.com/knadh/koanf/providers/file v0.1.0 h1:fs6U7nrV58d3CFAFh8VTde8TM262ObYf3ODrc//Lp+c=
github.com/knadh/koanf/providers/file v0.1.0/go.mod h1:rjJ/nHQl64iYCtAW2QQnF0eSmDEX/YZ/eNFj5yR6BvA=
github.com/knadh/koanf/providers/file v1.1.0 h1:MTjA+gRrVl1zqgetEAIaXHqYje0XSosxSiMD4/7kz0o=
github.com/knadh/koanf/providers/file v1.1.0/go.mod h1:/faSBcv2mxPVjFrXck95qeoyoZ5myJ6uxN8OOVNJJCI=
github.com/knadh/koanf/providers/rawbytes v0.1.0 h1:dpzgu2KO6uf6oCb4aP05KDmKmAmI51k5pe8RYKQ0qME=
github.com/knadh/koanf/providers/rawbytes v0.1.0/go.mod h1:mMTB1/IcJ/yE++A2iEZbY1MLygX7vttU+C+S/YmPu9c=
github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM=
Expand Down Expand Up @@ -84,8 +84,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U=
github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
Expand All @@ -108,6 +108,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
Expand Down

0 comments on commit 6929283

Please sign in to comment.