Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some malicious/spoofed preflight requests cause prohibitive load #170

Closed
jub0bs opened this issue Mar 27, 2024 · 1 comment
Closed

Some malicious/spoofed preflight requests cause prohibitive load #170

jub0bs opened this issue Mar 27, 2024 · 1 comment

Comments

@jub0bs
Copy link
Contributor

jub0bs commented Mar 27, 2024

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.

@rs
Copy link
Owner

rs commented Mar 27, 2024

Thanks, looking forward to your PR.

@jub0bs jub0bs changed the title Malicious/spoofed preflight requests cause prohibitive load Some malicious/spoofed preflight requests cause prohibitive load Apr 2, 2024
@rs rs closed this as completed in 4c32059 Apr 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants