Skip to content

Commit

Permalink
fix: headers leaked during interruptions at phase 3/4 (port) (#166)
Browse files Browse the repository at this point in the history
* fix: headers leaked during interruptions at phase 3/4 (port)

* enrich example
  • Loading branch information
M4tteoP committed Aug 5, 2024
1 parent b66be2f commit 0bf0455
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 12 deletions.
23 changes: 14 additions & 9 deletions example/Caddyfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
auto_https off
order coraza_waf first
log {
output stdout
format console
level info
level debug
include "http.handlers.waf"
}
}

Expand All @@ -15,25 +17,28 @@
Include @coraza.conf-recommended
Include @crs-setup.conf.example
Include @owasp_crs/*.conf
SecDefaultAction "phase:3,log,auditlog,pass"
SecDefaultAction "phase:4,log,auditlog,pass"
SecDefaultAction "phase:5,log,auditlog,pass"
SecRuleEngine On
SecDebugLog /dev/stdout
SecDebugLogLevel 9
SecRule REQUEST_URI "@streq /admin" "id:101,phase:1,t:lowercase,deny,status:403"
SecRule REQUEST_BODY "@rx maliciouspayload" "id:102,phase:2,t:lowercase,deny,status:403"
SecRule RESPONSE_HEADERS::status "@rx 406" "id:103,phase:3,t:lowercase,deny,status:403"
SecRule RESPONSE_STATUS "@rx 406" "id:103,phase:3,t:lowercase,deny,status:403"
SecResponseBodyAccess On
SecResponseBodyMimeType application/json
SecRule RESPONSE_BODY "@contains responsebodycode" "id:104,phase:4,t:lowercase,deny,status:403"
`
}

handle_errors 403 {
header X-Blocked "true"
root * /etc/caddy/custom-pages
rewrite * /{err.status_code}.html
file_server
templates
}
handle_errors 403 {
header X-Blocked "true"
root * /etc/caddy/custom-pages
rewrite * /{err.status_code}.html
file_server
templates
}

reverse_proxy {$HTTPBIN_HOST:localhost}:8081
}
16 changes: 13 additions & 3 deletions interceptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func (i *rwInterceptor) WriteHeader(statusCode int) {
i.statusCode = statusCode

if it := i.tx.ProcessResponseHeaders(statusCode, i.proto); it != nil {
i.w.Header().Del("Content-Length")
i.cleanHeaders()
i.statusCode = obtainStatusCodeFromInterruptionOrDefault(it, i.statusCode)
i.flushWriteHeader()
return
Expand All @@ -64,6 +64,13 @@ func (i *rwInterceptor) flushWriteHeader() {
}
}

// cleanHeaders removes all headers from the response
func (i *rwInterceptor) cleanHeaders() {
for k := range i.w.Header() {
i.w.Header().Del(k)
}
}

// Write buffers the response body until the request body limit is reach or an
// interruption is triggered, this buffer is later used to analyse the body in
// the response processor.
Expand Down Expand Up @@ -91,7 +98,9 @@ func (i *rwInterceptor) Write(b []byte) (int, error) {
// to it, otherwise we just send it to the response writer.
it, n, err := i.tx.WriteResponseBody(b)
if it != nil {
i.overrideWriteHeader(it.Status)
// if there is an interruption we must clean the headers and override the status code
i.cleanHeaders()
i.overrideWriteHeader(obtainStatusCodeFromInterruptionOrDefault(it, i.statusCode))
// We only flush the status code after an interruption.
i.flushWriteHeader()

Expand Down Expand Up @@ -164,9 +173,10 @@ func wrap(w http.ResponseWriter, r *http.Request, tx types.Transaction) (
Err: err,
}
} else if it != nil {
// if there is an interruption we must clean the headers and override the status code
i.cleanHeaders()
code := obtainStatusCodeFromInterruptionOrDefault(it, i.statusCode)
i.overrideWriteHeader(code)
i.w.Header().Del("Content-Length")
i.flushWriteHeader()

return caddyhttp.HandlerError{
Expand Down

0 comments on commit 0bf0455

Please sign in to comment.