Skip to content

Commit 968dc71

Browse files
authored
fix: Disables implicit Cookies url decoding (#928)
* Cookie not urldecoded * adds test * chore: adds comment * makes const private * QueryUnescape minor refactor * private doParseQuery avoiding public booleans * removes also comment, makes QueryUnescape private * go mod tidy * adds a couple of QueryUnescape test cases * godoc format * untrack go.work.sum, drops constants * fix comment
1 parent c0b5f7a commit 968dc71

File tree

11 files changed

+109
-185
lines changed

11 files changed

+109
-185
lines changed

Diff for: .gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@ coraza-waf
1818
__debug_bin
1919

2020
build/
21+
22+
go.work.sum

Diff for: go.sum

-4
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
3232
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
3333
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
3434
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
35-
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
36-
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
3735
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
3836
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
3937
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -49,8 +47,6 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
4947
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
5048
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
5149
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
52-
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
53-
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
5450
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
5551
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
5652
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

Diff for: go.work.sum

-130
This file was deleted.

Diff for: http/middleware_test.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,7 @@ SecRule &REQUEST_HEADERS:Transfer-Encoding "!@eq 0" "id:1,phase:1,deny"
101101
}
102102
if it == nil {
103103
t.Fatal("Expected interruption")
104-
}
105-
if it.RuleID != 1 {
104+
} else if it.RuleID != 1 {
106105
t.Fatalf("Expected rule 1 to be triggered, got rule %d", it.RuleID)
107106
}
108107
if err := tx.Close(); err != nil {

Diff for: internal/bodyprocessors/urlencoded.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010

1111
"github.com/corazawaf/coraza/v3/experimental/plugins/plugintypes"
1212
"github.com/corazawaf/coraza/v3/internal/collections"
13-
"github.com/corazawaf/coraza/v3/internal/url"
13+
urlutil "github.com/corazawaf/coraza/v3/internal/url"
1414
)
1515

1616
type urlencodedBodyProcessor struct {
@@ -23,7 +23,7 @@ func (*urlencodedBodyProcessor) ProcessRequest(reader io.Reader, v plugintypes.T
2323
}
2424

2525
b := buf.String()
26-
values := url.ParseQuery(b, '&')
26+
values := urlutil.ParseQuery(b, '&')
2727
argsCol := v.ArgsPost()
2828
for k, vs := range values {
2929
argsCol.Set(k, vs)

Diff for: internal/corazawaf/transaction.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,8 @@ func (tx *Transaction) AddRequestHeader(key string, value string) {
321321
}
322322
case "cookie":
323323
// Cookies use the same syntax as GET params but with semicolon (;) separator
324-
values := urlutil.ParseQuery(value, ';')
324+
// WithoutUnescape is used to avoid implicitly performing an URL decode on the cookies
325+
values := urlutil.ParseQueryWithoutUnescape(value, ';')
325326
for k, vr := range values {
326327
for _, v := range vr {
327328
tx.variables.requestCookies.Add(k, v)
@@ -535,7 +536,7 @@ func (tx *Transaction) GetStopWatch() string {
535536
}
536537

537538
// GetField Retrieve data from collections applying exceptions
538-
// In future releases we may remove de exceptions slice and
539+
// In future releases we may remove the exceptions slice and
539540
// make it easier to use
540541
func (tx *Transaction) GetField(rv ruleVariableParams) []types.MatchData {
541542
col := tx.Collection(rv.Variable)

Diff for: internal/corazawaf/transaction_test.go

+29
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,35 @@ func TestHeaderSetters(t *testing.T) {
806806
}
807807
}
808808

809+
func TestCookiesNotUrldecoded(t *testing.T) {
810+
waf := NewWAF()
811+
tx := waf.NewTransaction()
812+
fullCookie := "abc=%7Bd+e+f%7D;hij=%7Bklm%7D"
813+
expectedUrlencodedAbcCookieValue := "%7Bd+e+f%7D"
814+
unexpectedUrldencodedAbcCookieValue := "{d e f}"
815+
tx.AddRequestHeader("cookie", fullCookie)
816+
c := tx.variables.requestCookies.Get("abc")[0]
817+
if c != expectedUrlencodedAbcCookieValue {
818+
if c == unexpectedUrldencodedAbcCookieValue {
819+
t.Errorf("failed to set cookie, unexpected urldecoding. Got: %q, expected: %q", unexpectedUrldencodedAbcCookieValue, expectedUrlencodedAbcCookieValue)
820+
} else {
821+
t.Errorf("failed to set cookie, got %q", c)
822+
}
823+
}
824+
if tx.variables.requestHeaders.Get("cookie")[0] != fullCookie {
825+
t.Errorf("failed to set request header, got: %q, expected: %q", tx.variables.requestHeaders.Get("cookie")[0], fullCookie)
826+
}
827+
if !utils.InSlice("cookie", collectionValues(t, tx.variables.requestHeadersNames)) {
828+
t.Error("failed to set header name", collectionValues(t, tx.variables.requestHeadersNames))
829+
}
830+
if !utils.InSlice("abc", collectionValues(t, tx.variables.requestCookiesNames)) {
831+
t.Error("failed to set cookie name")
832+
}
833+
if err := tx.Close(); err != nil {
834+
t.Error(err)
835+
}
836+
}
837+
809838
func collectionValues(t *testing.T, col collection.Collection) []string {
810839
t.Helper()
811840
var values []string

0 commit comments

Comments
 (0)