diff --git a/pkg/appsec/request.go b/pkg/appsec/request.go index c82529acc..11fe68b37 100644 --- a/pkg/appsec/request.go +++ b/pkg/appsec/request.go @@ -1,6 +1,7 @@ package appsec import ( + "bytes" "encoding/json" "fmt" "io" @@ -43,6 +44,7 @@ type ParsedRequest struct { IsOutBand bool `json:"-"` AppsecEngine string `json:"appsec_engine,omitempty"` RemoteAddrNormalized string `json:"normalized_remote_addr,omitempty"` + HTTPRequest *http.Request `json:"-"` } type ReqDumpFilter struct { @@ -274,13 +276,16 @@ func NewParsedRequestFromRequest(r *http.Request, logger *logrus.Entry) (ParsedR if contentLength < 0 { contentLength = 0 } - body := make([]byte, contentLength) + body := make([]byte, contentLength) if r.Body != nil { _, err = io.ReadFull(r.Body, body) if err != nil { return ParsedRequest{}, fmt.Errorf("unable to read body: %s", err) } + r.Body.Close() + // reset the original body back as it's been read, i'm not sure its needed? + r.Body = io.NopCloser(bytes.NewBuffer(body)) } clientIP := r.Header.Get(IPHeaderName) @@ -292,10 +297,12 @@ func NewParsedRequestFromRequest(r *http.Request, logger *logrus.Entry) (ParsedR if clientURI == "" { return ParsedRequest{}, fmt.Errorf("missing '%s' header", URIHeaderName) } + 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) @@ -307,6 +314,13 @@ func NewParsedRequestFromRequest(r *http.Request, logger *logrus.Entry) (ParsedR delete(r.Header, URIHeaderName) delete(r.Header, VerbHeaderName) + originalHTTPRequest := r.Clone(r.Context()) + originalHTTPRequest.Body = io.NopCloser(bytes.NewBuffer(body)) + originalHTTPRequest.RemoteAddr = clientIP + originalHTTPRequest.RequestURI = clientURI + originalHTTPRequest.Method = clientMethod + originalHTTPRequest.Host = clientHost + parsedURL, err := url.Parse(clientURI) if err != nil { return ParsedRequest{}, fmt.Errorf("unable to parse url '%s': %s", clientURI, err) @@ -343,5 +357,6 @@ func NewParsedRequestFromRequest(r *http.Request, logger *logrus.Entry) (ParsedR TransferEncoding: r.TransferEncoding, ResponseChannel: make(chan AppsecTempResponse), RemoteAddrNormalized: remoteAddrNormalized, + HTTPRequest: originalHTTPRequest, }, nil } diff --git a/pkg/appsec/waf_helpers.go b/pkg/appsec/waf_helpers.go index 605d42ccb..3d9a96a0d 100644 --- a/pkg/appsec/waf_helpers.go +++ b/pkg/appsec/waf_helpers.go @@ -22,6 +22,7 @@ func GetPreEvalEnv(w *AppsecRuntimeConfig, request *ParsedRequest) map[string]in return map[string]interface{}{ "IsInBand": request.IsInBand, "IsOutBand": request.IsOutBand, + "req": request.HTTPRequest, "RemoveInBandRuleByID": w.RemoveInbandRuleByID, "RemoveInBandRuleByName": w.RemoveInbandRuleByName, "RemoveInBandRuleByTag": w.RemoveInbandRuleByTag, @@ -39,13 +40,14 @@ func GetPostEvalEnv(w *AppsecRuntimeConfig, request *ParsedRequest) map[string]i "IsInBand": request.IsInBand, "IsOutBand": request.IsOutBand, "DumpRequest": request.DumpRequest, + "req": request.HTTPRequest, } } func GetOnMatchEnv(w *AppsecRuntimeConfig, request *ParsedRequest, evt types.Event) map[string]interface{} { return map[string]interface{}{ "evt": evt, - "req": request, + "req": request.HTTPRequest, "IsInBand": request.IsInBand, "IsOutBand": request.IsOutBand, "SetRemediation": w.SetAction,