headers: enforce a max number of response header to accept

The limit is 5000 headers in a single transfer. To avoid problems caused
by mistakes or malice.

Add test 747 to verify

Reported-by: wolfsage on hackerone

Closes #17281
This commit is contained in:
Daniel Stenberg 2025-05-08 00:21:26 +02:00
parent d689bd915e
commit 40ef77b6da
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
5 changed files with 67 additions and 2 deletions

View file

@ -313,6 +313,11 @@ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header,
return CURLE_WEIRD_SERVER_REPLY;
}
}
if(Curl_llist_count(&data->state.httphdrs) >= MAX_HTTP_RESP_HEADER_COUNT) {
failf(data, "Too many response headers, %d is max",
MAX_HTTP_RESP_HEADER_COUNT);
return CURLE_TOO_LARGE;
}
hs = calloc(1, sizeof(*hs) + hlen);
if(!hs)

View file

@ -174,6 +174,10 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl,
version. This count includes CONNECT response headers. */
#define MAX_HTTP_RESP_HEADER_SIZE (300*1024)
/* MAX_HTTP_RESP_HEADER_COUNT is the maximum number of response headers that
libcurl allows for a single HTTP response, including CONNECT and
redirects. */
#define MAX_HTTP_RESP_HEADER_COUNT 5000
#endif /* CURL_DISABLE_HTTP */

View file

@ -107,7 +107,7 @@ test709 test710 test711 test712 test713 test714 test715 test716 test717 \
test718 test719 test720 test721 test722 test723 test724 test725 test726 \
test727 test728 test729 test730 test731 test732 test733 test734 test735 \
test736 test737 test738 test739 test740 test741 test742 test743 test744 \
test745 test746 \
test745 test746 test747 \
\
test780 test781 test782 test783 test784 test785 test786 test787 test788 \
test789 test790 test791 \

View file

@ -20,7 +20,7 @@ Content-Length: 6
Location: /
Connection: close
Content-Type: text/html
%repeat[1700 x Repeat-this-Header-a-large-number-of-times: Dorothy lived in the midst of the great Kansas prairies, with Uncle Henry, who was a farmer, and Aunt Em, who was the farmers wife.%0a]%
%repeat[1700 x Repeat-this-Header-a-large-number-of-times: Dorothy lived in the midst of the great Kansas prairies, with Uncle Henry, who was a farmer, and Aunt Em, who was the farmer's wife. Their house was small, for the lumber to build it had to be carried by wagon many miles. There were four walls, a floor and a roof, which made one room; and this room contained a rusty looking cookstove, a cupboard for the dishes, a table, three or four chairs, and the beds. Uncle Henry and Aunt Em had a big bed in one corner, and Dorothy a little bed in another corner. There was no garret at all, and no cellar--except a small hole dug in the ground, called a cyclone cellar, where the family could go in case one of those great whirlwinds arose, mighty enough to crush any building in its path. It was reached by a trap door in the middle of the floor, from which a ladder led down into the small, dark hole.%0a]%
-foo-
</data>
</reply>

56
tests/data/test747 Normal file
View file

@ -0,0 +1,56 @@
<testcase>
<info>
<keywords>
HTTP
HTTP GET
</keywords>
</info>
#
# Server-side
<reply>
<data nocheck="yes">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Content-Length: 6
Connection: close
Content-Type: text/html
%repeat[5001 x Tiny: but many.%0a]%
-foo-
</data>
</reply>
#
# Client-side
<client>
<server>
http
</server>
<name>
Reject too many HTTP response headers
</name>
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
</client>
#
# Verify data after the test has been "shot"
<verify>
<protocol crlf="yes">
GET /%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
</protocol>
# curl: (100) Too many response headers, 5000 is max
<errorcode>
100
</errorcode>
</verify>
</testcase>