mirror of
https://github.com/frappe/gunicorn.git
synced 2026-01-14 11:09:11 +08:00
forbid lone CR/LF and NUL in headers
New parser rule: refuse HTTP requests where a header field value contains characters that a) should never appear there in the first place, b) might have lead to incorrect treatment in a proxy in front, and c) might lead to unintended behaviour in applications. From RFC 9110 section 5.5: "Field values containing CR, LF, or NUL characters are invalid and dangerous, due to the varying ways that implementations might parse and interpret those characters; a recipient of CR, LF, or NUL within a field value MUST either reject the message or replace each of those characters with SP before further processing or forwarding of that message."
This commit is contained in:
parent
e3fa50d1c5
commit
eda9d456d3
@ -2254,7 +2254,7 @@ class StripHeaderSpaces(Setting):
|
|||||||
This is known to induce vulnerabilities and is not compliant with the HTTP/1.1 standard.
|
This is known to induce vulnerabilities and is not compliant with the HTTP/1.1 standard.
|
||||||
See https://portswigger.net/research/http-desync-attacks-request-smuggling-reborn.
|
See https://portswigger.net/research/http-desync-attacks-request-smuggling-reborn.
|
||||||
|
|
||||||
Use with care and only if necessary. May be removed in a future version.
|
Use with care and only if necessary. Deprecated; scheduled for removal in 25.0.0
|
||||||
|
|
||||||
.. versionadded:: 20.0.1
|
.. versionadded:: 20.0.1
|
||||||
"""
|
"""
|
||||||
@ -2274,9 +2274,13 @@ class PermitUnconventionalHTTPMethod(Setting):
|
|||||||
methods with lowercase characters or methods containing the # character.
|
methods with lowercase characters or methods containing the # character.
|
||||||
HTTP methods are case sensitive by definition, and merely uppercase by convention.
|
HTTP methods are case sensitive by definition, and merely uppercase by convention.
|
||||||
|
|
||||||
This option is provided to diagnose backwards-incompatible changes.
|
If unset, Gunicorn will apply nonstandard restrictions and cause 400 response status
|
||||||
|
in cases where otherwise 501 status is expected. While this option does modify that
|
||||||
|
behaviour, it should not be depended upon to guarantee standards-compliant behaviour.
|
||||||
|
Rather, it is provided temporarily, to assist in diagnosing backwards-incompatible
|
||||||
|
changes around the incomplete application of those restrictions.
|
||||||
|
|
||||||
Use with care and only if necessary. May be removed in a future version.
|
Use with care and only if necessary. Temporary; scheduled for removal in 24.0.0
|
||||||
|
|
||||||
.. versionadded:: 22.0.0
|
.. versionadded:: 22.0.0
|
||||||
"""
|
"""
|
||||||
@ -2296,7 +2300,8 @@ class PermitUnconventionalHTTPVersion(Setting):
|
|||||||
It is unusual to specify HTTP 1 versions other than 1.0 and 1.1.
|
It is unusual to specify HTTP 1 versions other than 1.0 and 1.1.
|
||||||
|
|
||||||
This option is provided to diagnose backwards-incompatible changes.
|
This option is provided to diagnose backwards-incompatible changes.
|
||||||
Use with care and only if necessary. May be removed in a future version.
|
Use with care and only if necessary. Temporary; the precise effect of this option may
|
||||||
|
change in a future version, or it may be removed altogether.
|
||||||
|
|
||||||
.. versionadded:: 22.0.0
|
.. versionadded:: 22.0.0
|
||||||
"""
|
"""
|
||||||
@ -2316,7 +2321,7 @@ class CasefoldHTTPMethod(Setting):
|
|||||||
|
|
||||||
This option is provided because previous versions of gunicorn defaulted to this behaviour.
|
This option is provided because previous versions of gunicorn defaulted to this behaviour.
|
||||||
|
|
||||||
Use with care and only if necessary. May be removed in a future version.
|
Use with care and only if necessary. Deprecated; scheduled for removal in 24.0.0
|
||||||
|
|
||||||
.. versionadded:: 22.0.0
|
.. versionadded:: 22.0.0
|
||||||
"""
|
"""
|
||||||
@ -2378,7 +2383,16 @@ class TolerateDangerousFraming(Setting):
|
|||||||
|
|
||||||
This is known to induce vulnerabilities, but not strictly forbidden by RFC9112.
|
This is known to induce vulnerabilities, but not strictly forbidden by RFC9112.
|
||||||
|
|
||||||
Use with care and only if necessary. May be removed in a future version.
|
In any case, the connection is closed after the malformed request,
|
||||||
|
as it is unclear if and at which boundary additional requests start.
|
||||||
|
|
||||||
|
Use with care and only if necessary.
|
||||||
|
Temporary; will be changed or removed in a future version.
|
||||||
|
|
||||||
.. versionadded:: 22.0.0
|
.. versionadded:: 22.0.0
|
||||||
|
.. versionchanged: 22.1.0
|
||||||
|
The newly added rejection of invalid and dangerous characters CR, LF and NUL in
|
||||||
|
header field values is also controlled with this setting. rfc9110 permits both
|
||||||
|
rejecting and SP-replacing. With this option set, Gunicorn passes the field value
|
||||||
|
unchanged. With this option unset, Gunicorn rejects the request.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -28,6 +28,7 @@ TOKEN_RE = re.compile(r"[%s0-9a-zA-Z]+" % (re.escape(RFC9110_5_6_2_TOKEN_SPECIAL
|
|||||||
METHOD_BADCHAR_RE = re.compile("[a-z#]")
|
METHOD_BADCHAR_RE = re.compile("[a-z#]")
|
||||||
# usually 1.0 or 1.1 - RFC9112 permits restricting to single-digit versions
|
# usually 1.0 or 1.1 - RFC9112 permits restricting to single-digit versions
|
||||||
VERSION_RE = re.compile(r"HTTP/(\d)\.(\d)")
|
VERSION_RE = re.compile(r"HTTP/(\d)\.(\d)")
|
||||||
|
RFC9110_5_5_INVALID_AND_DANGEROUS = re.compile(r"[\0\r\n]")
|
||||||
|
|
||||||
|
|
||||||
class Message(object):
|
class Message(object):
|
||||||
@ -121,6 +122,12 @@ class Message(object):
|
|||||||
value.append(curr.strip("\t "))
|
value.append(curr.strip("\t "))
|
||||||
value = " ".join(value)
|
value = " ".join(value)
|
||||||
|
|
||||||
|
if RFC9110_5_5_INVALID_AND_DANGEROUS.search(value):
|
||||||
|
if not self.cfg.tolerate_dangerous_framing:
|
||||||
|
raise InvalidHeader(name)
|
||||||
|
# value = RFC9110_5_5_INVALID_AND_DANGEROUS.sub(" ", value)
|
||||||
|
self.force_close()
|
||||||
|
|
||||||
if header_length > self.limit_request_field_size > 0:
|
if header_length > self.limit_request_field_size > 0:
|
||||||
raise LimitRequestHeaders("limit request headers fields size")
|
raise LimitRequestHeaders("limit request headers fields size")
|
||||||
|
|
||||||
|
|||||||
7
tests/requests/invalid/invalid_field_value_01.http
Normal file
7
tests/requests/invalid/invalid_field_value_01.http
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
GET / HTTP/1.1\r\n
|
||||||
|
Host: x\r\n
|
||||||
|
Newline: a\n
|
||||||
|
Content-Length: 26\r\n
|
||||||
|
GET / HTTP/1.1\n
|
||||||
|
Host: x\r\n
|
||||||
|
\r\n
|
||||||
5
tests/requests/invalid/invalid_field_value_01.py
Normal file
5
tests/requests/invalid/invalid_field_value_01.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from gunicorn.config import Config
|
||||||
|
from gunicorn.http.errors import InvalidHeader
|
||||||
|
|
||||||
|
cfg = Config()
|
||||||
|
request = InvalidHeader
|
||||||
8
tests/requests/valid/invalid_field_value_01_compat.http
Normal file
8
tests/requests/valid/invalid_field_value_01_compat.http
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GET / HTTP/1.1\r\n
|
||||||
|
Host: x\r\n
|
||||||
|
Newline: a\n
|
||||||
|
Content-Length: 26\r\n
|
||||||
|
X-Forwarded-By: broken-proxy\r\n\r\n
|
||||||
|
GET / HTTP/1.1\n
|
||||||
|
Host: x\r\n
|
||||||
|
\r\n
|
||||||
18
tests/requests/valid/invalid_field_value_01_compat.py
Normal file
18
tests/requests/valid/invalid_field_value_01_compat.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
from gunicorn.config import Config
|
||||||
|
|
||||||
|
cfg = Config()
|
||||||
|
cfg.set("tolerate_dangerous_framing", True)
|
||||||
|
|
||||||
|
req1 = {
|
||||||
|
"method": "GET",
|
||||||
|
"uri": uri("/"),
|
||||||
|
"version": (1, 1),
|
||||||
|
"headers": [
|
||||||
|
("HOST", "x"),
|
||||||
|
("NEWLINE", "a\nContent-Length: 26"),
|
||||||
|
("X-FORWARDED-BY", "broken-proxy"),
|
||||||
|
],
|
||||||
|
"body": b""
|
||||||
|
}
|
||||||
|
|
||||||
|
request = [req1]
|
||||||
Loading…
x
Reference in New Issue
Block a user