Skip to content

Commit

Permalink
minor waf fixes (#2693)
Browse files Browse the repository at this point in the history
  • Loading branch information
buixor authored Jan 3, 2024
1 parent a504113 commit 1c03fbe
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 12 deletions.
2 changes: 1 addition & 1 deletion pkg/acquisition/modules/appsec/appsec.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ func (w *AppsecSource) appsecHandler(rw http.ResponseWriter, r *http.Request) {
}

// parse the request only once
parsedRequest, err := appsec.NewParsedRequestFromRequest(r)
parsedRequest, err := appsec.NewParsedRequestFromRequest(r, w.logger)
if err != nil {
w.logger.Errorf("%s", err)
rw.WriteHeader(http.StatusInternalServerError)
Expand Down
4 changes: 3 additions & 1 deletion pkg/appsec/appsec_rule/appsec_rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ rules:
type match struct {
Type string `yaml:"type"`
Value string `yaml:"value"`
Not bool `yaml:"not,omitempty"`
}

type CustomRule struct {
Expand All @@ -40,7 +41,8 @@ type CustomRule struct {
Transform []string `yaml:"transform"` //t:lowercase, t:uppercase, etc
And []CustomRule `yaml:"and,omitempty"`
Or []CustomRule `yaml:"or,omitempty"`
BodyType string `yaml:"body_type,omitempty"`

BodyType string `yaml:"body_type,omitempty"`
}

func (v *CustomRule) Convert(ruleType string, appsecRuleName string) (string, []uint32, error) {
Expand Down
16 changes: 16 additions & 0 deletions pkg/appsec/appsec_rule/modsec_rule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,22 @@ func TestVPatchRuleString(t *testing.T) {
},
expected: `SecRule ARGS_GET:foo "@rx [^a-zA-Z]" "id:2203944045,phase:2,deny,log,msg:'Base Rule',tag:'crowdsec-Base Rule',t:lowercase"`,
},
{
name: "Base Rule #2",
rule: CustomRule{
Zones: []string{"METHOD"},
Match: match{Type: "startsWith", Value: "toto"},
},
expected: `SecRule REQUEST_METHOD "@beginsWith toto" "id:2759779019,phase:2,deny,log,msg:'Base Rule #2',tag:'crowdsec-Base Rule #2'"`,
},
{
name: "Base Negative Rule",
rule: CustomRule{
Zones: []string{"METHOD"},
Match: match{Type: "startsWith", Value: "toto", Not: true},
},
expected: `SecRule REQUEST_METHOD "!@beginsWith toto" "id:3966251995,phase:2,deny,log,msg:'Base Negative Rule',tag:'crowdsec-Base Negative Rule'"`,
},
{
name: "Multiple Zones",
rule: CustomRule{
Expand Down
7 changes: 6 additions & 1 deletion pkg/appsec/appsec_rule/modsecurity.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ var matchMap map[string]string = map[string]string{
"lt": "@lt",
"gte": "@ge",
"lte": "@le",
"eq": "@eq",
}

var bodyTypeMatch map[string]string = map[string]string{
Expand Down Expand Up @@ -141,7 +142,11 @@ func (m *ModsecurityRule) buildRules(rule *CustomRule, appsecRuleName string, an

if rule.Match.Type != "" {
if match, ok := matchMap[rule.Match.Type]; ok {
r.WriteString(fmt.Sprintf(`"%s %s"`, match, rule.Match.Value))
prefix := ""
if rule.Match.Not {
prefix = "!"
}
r.WriteString(fmt.Sprintf(`"%s%s %s"`, prefix, match, rule.Match.Value))
} else {
return nil, fmt.Errorf("unknown match type '%s'", rule.Match.Type)
}
Expand Down
16 changes: 7 additions & 9 deletions pkg/appsec/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"regexp"

"github.com/google/uuid"
"github.com/sirupsen/logrus"
log "github.com/sirupsen/logrus"
)

Expand Down Expand Up @@ -267,7 +268,7 @@ func (r *ReqDumpFilter) ToJSON() error {
}

// Generate a ParsedRequest from a http.Request. ParsedRequest can be consumed by the App security Engine
func NewParsedRequestFromRequest(r *http.Request) (ParsedRequest, error) {
func NewParsedRequestFromRequest(r *http.Request, logger *logrus.Entry) (ParsedRequest, error) {
var err error
contentLength := r.ContentLength
if contentLength < 0 {
Expand All @@ -282,26 +283,23 @@ func NewParsedRequestFromRequest(r *http.Request) (ParsedRequest, error) {
}
}

// the real source of the request is set in 'x-client-ip'
clientIP := r.Header.Get(IPHeaderName)
if clientIP == "" {
return ParsedRequest{}, fmt.Errorf("missing '%s' header", IPHeaderName)
}
// the real target Host of the request is set in 'x-client-host'
clientHost := r.Header.Get(HostHeaderName)
if clientHost == "" {
return ParsedRequest{}, fmt.Errorf("missing '%s' header", HostHeaderName)
}
// the real URI of the request is set in 'x-client-uri'

clientURI := r.Header.Get(URIHeaderName)
if clientURI == "" {
return ParsedRequest{}, fmt.Errorf("missing '%s' header", URIHeaderName)
}
// the real VERB of the request is set in 'x-client-uri'
clientMethod := r.Header.Get(VerbHeaderName)
if clientMethod == "" {
return ParsedRequest{}, fmt.Errorf("missing '%s' header", VerbHeaderName)
}
clientHost := r.Header.Get(HostHeaderName)
if clientHost == "" { //this might be empty
logger.Debugf("missing '%s' header", HostHeaderName)
}

// delete those headers before coraza process the request
delete(r.Header, IPHeaderName)
Expand Down

0 comments on commit 1c03fbe

Please sign in to comment.