+39
-0
lines changedFilter options
+39
-0
lines changed Original file line number Diff line number Diff line change
@@ -150,6 +150,10 @@
150
150
# _is_allowed_url_pchars_re = re.compile(r"^[/!$&'()*+,;=:@%a-zA-Z0-9._~-]+$")
151
151
# We are more lenient for assumed real world compatibility purposes.
152
152
153
+
# These characters are not allowed within HTTP method names
154
+
# to prevent http header injection.
155
+
_contains_disallowed_method_pchar_re = re.compile('[\x00-\x1f]')
156
+
153
157
# We always set the Content-Length header for these methods because some
154
158
# servers will otherwise respond with a 411
155
159
_METHODS_EXPECTING_BODY = {'PATCH', 'POST', 'PUT'}
@@ -1109,6 +1113,8 @@ def putrequest(self, method, url, skip_host=False,
1109
1113
else:
1110
1114
raise CannotSendRequest(self.__state)
1111
1115
1116
+
self._validate_method(method)
1117
+
1112
1118
# Save the method for use later in the response phase
1113
1119
self._method = method
1114
1120
@@ -1199,6 +1205,15 @@ def _encode_request(self, request):
1199
1205
# ASCII also helps prevent CVE-2019-9740.
1200
1206
return request.encode('ascii')
1201
1207
1208
+
def _validate_method(self, method):
1209
+
"""Validate a method name for putrequest."""
1210
+
# prevent http header injection
1211
+
match = _contains_disallowed_method_pchar_re.search(method)
1212
+
if match:
1213
+
raise ValueError(
1214
+
f"method can't contain control characters. {method!r} "
1215
+
f"(found at least {match.group()!r})")
1216
+
1202
1217
def _validate_path(self, url):
1203
1218
"""Validate a url for putrequest."""
1204
1219
# Prevent CVE-2019-9740.
Original file line number Diff line number Diff line change
@@ -363,6 +363,28 @@ def test_headers_debuglevel(self):
363
363
self.assertEqual(lines[3], "header: Second: val2")
364
364
365
365
366
+
class HttpMethodTests(TestCase):
367
+
def test_invalid_method_names(self):
368
+
methods = (
369
+
'GET\r',
370
+
'POST\n',
371
+
'PUT\n\r',
372
+
'POST\nValue',
373
+
'POST\nHOST:abc',
374
+
'GET\nrHost:abc\n',
375
+
'POST\rRemainder:\r',
376
+
'GET\rHOST:\n',
377
+
'\nPUT'
378
+
)
379
+
380
+
for method in methods:
381
+
with self.assertRaisesRegex(
382
+
ValueError, "method can't contain control characters"):
383
+
conn = client.HTTPConnection('example.com')
384
+
conn.sock = FakeSocket(None)
385
+
conn.request(method=method, url="/")
386
+
387
+
366
388
class TransferEncodingTest(TestCase):
367
389
expected_body = b"It's just a flesh wound"
368
390
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
1
+
Prevent http header injection by rejecting control characters in
2
+
http.client.putrequest(...).
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4