Skip to content

Commit 50c8aa4

Browse files
authored
WAF: expose more transform options (#4140)
1 parent 5a11847 commit 50c8aa4

2 files changed

Lines changed: 50 additions & 7 deletions

File tree

pkg/appsec/appsec_rule/modsec_rule_test.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ package appsec_rule
22

33
import (
44
"testing"
5+
6+
"github.com/corazawaf/coraza/v3"
7+
"github.com/stretchr/testify/require"
58
)
69

710
func TestVPatchRuleString(t *testing.T) {
@@ -10,6 +13,7 @@ func TestVPatchRuleString(t *testing.T) {
1013
description string
1114
rule CustomRule
1215
expected string
16+
invalid bool
1317
}{
1418
{
1519
name: "Collection count",
@@ -151,6 +155,7 @@ SecRule ARGS_GET:bar "@rx [^a-zA-Z]" "id:651140804,phase:2,deny,log,msg:'test ru
151155
// leaf(foo) AND (foo OR bar) → DNF: (foo AND foo) OR (foo AND bar) → 2 groups of 2
152156
name: "OR AND mix",
153157
description: "test rule",
158+
invalid: true,
154159

155160
rule: CustomRule{
156161
And: []CustomRule{
@@ -333,6 +338,15 @@ SecRule REQUEST_METHOD "@streq POST" "id:3660599789,phase:2,deny,log,msg:'test r
333338
SecRule ARGS_GET:cmd "@rx exec" "id:713704559,phase:2,deny,log,msg:'test rule',tag:'crowdsec-Deep nesting',tag:'cs-custom-rule',chain"
334339
SecRule REQUEST_HEADERS:x-debug "@streq true" "id:625013554,phase:2,deny,log,msg:'test rule',tag:'crowdsec-Deep nesting',tag:'cs-custom-rule'"`,
335340
},
341+
{
342+
name: "all transforms",
343+
rule: CustomRule{
344+
Zones: []string{"ARGS"},
345+
Variables: []string{"foo"},
346+
Match: Match{Type: "regex", Value: "[^a-zA-Z]"},
347+
Transform: []string{"lowercase", "uppercase", "length", "trim", "trim_left", "trim_right", "htmlentitydecode", "js_decode", "css_decode", "urldecode", "hexdecode", "cmdline", "b64decode", "b64decode_lenient", "b64encode", "normalize_path", "normalize_path_win", "remove_whitespaces", "compress_whitespaces", "remove_nulls", "replace_nulls", "remove_comments", "replace_comments"},
348+
},
349+
},
336350
}
337351

338352
for _, tt := range tests {
@@ -341,9 +355,17 @@ SecRule REQUEST_HEADERS:x-debug "@streq true" "id:625013554,phase:2,deny,log,msg
341355
if err != nil {
342356
t.Errorf("Error converting rule: %s", err)
343357
}
344-
if actual != tt.expected {
358+
if tt.expected != "" && actual != tt.expected {
345359
t.Errorf("Expected:\n%s\nGot:\n%s", tt.expected, actual)
346360
}
361+
// Attempt to parse the rule to make sure we generated a valid one
362+
cfg := coraza.NewWAFConfig().WithDirectives(actual)
363+
_, err = coraza.NewWAF(cfg)
364+
if tt.invalid {
365+
require.Error(t, err)
366+
} else {
367+
require.NoError(t, err)
368+
}
347369
})
348370
}
349371
}

pkg/appsec/appsec_rule/modsecurity.go

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,36 @@ var zonesMap = map[string]string{
3737
var transformMap = map[string]string{
3838
"lowercase": "t:lowercase",
3939
"uppercase": "t:uppercase",
40-
"b64decode": "t:base64Decode",
41-
//"hexdecode": "t:hexDecode", -> not supported by coraza
42-
"length": "t:length",
40+
"length": "t:length",
41+
// trim
42+
"trim": "t:trim",
43+
"trim_left": "t:trimLeft",
44+
"trim_right": "t:trimRight",
45+
// Decoding transforms
46+
"htmlentitydecode": "t:htmlEntityDecode",
47+
"html_entity_decode": "t:htmlEntityDecode",
48+
"js_decode": "t:jsDecode",
49+
"css_decode": "t:cssDecode",
4350
"urldecode": "t:urlDecode",
44-
"trim": "t:trim",
51+
"hexdecode": "t:hexDecode",
52+
"cmdline": "t:cmdLine",
53+
// b64-related transforms
54+
"b64decode": "t:base64Decode", // strict base64 decode
55+
"b64decode_lenient": "t:base64DecodeExt", // lenient base64 decode (no padding, decode up to first invalid char, skip whitespaces and dots)
56+
"b64encode": "t:base64Encode",
57+
// Path normalization
4558
"normalize_path": "t:normalizePath",
4659
"normalizepath": "t:normalizePath",
47-
"htmlentitydecode": "t:htmlEntityDecode",
48-
"html_entity_decode": "t:htmlEntityDecode",
60+
"normalize_path_win": "t:normalizePathWin",
61+
"normalizepathwin": "t:normalizePathWin",
62+
// Whitespaces
63+
"remove_whitespaces": "t:removeWhitespace",
64+
"compress_whitespaces": "t:compressWhitespace",
65+
"remove_nulls": "t:removeNulls",
66+
"replace_nulls": "t:replaceNulls",
67+
// Comments
68+
"remove_comments": "t:removeComments",
69+
"replace_comments": "t:replaceComments",
4970
}
5071

5172
var matchMap = map[string]string{

0 commit comments

Comments
 (0)