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 · 3 comments
Closed

Some malicious/spoofed preflight requests cause prohibitive load #170

jub0bs opened this issue Mar 27, 2024 · 3 comments

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.

@ilayathalapathy-3719
Copy link

Do we have any CVE assigned for this issue?

@jub0bs
Copy link
Contributor Author

jub0bs commented Jul 5, 2024

@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?

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

3 participants