aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Shepelev <temotor@gmail.com>2020-05-20 14:56:12 +0300
committerSergey Shepelev <temotor@gmail.com>2020-05-20 15:00:24 +0300
commita1457cc31f3206cf691d11d2bf34e98865873e9e (patch)
treeeea5f3ce040d060ccda4f94aba7cdb68d60063a6
parent9413ffc973a2dc90abf787509ee82238345d5602 (diff)
downloadhttplib2-a1457cc31f3206cf691d11d2bf34e98865873e9e.tar.gz
IMPORTANT security vulnerability CWE-93 CRLF injection
Force %xx quote of space, CR, LF characters in uri. Special thanks to Recar https://github.com/Ciyfly for discrete notification. https://cwe.mitre.org/data/definitions/93.html
-rw-r--r--python2/httplib2/__init__.py3
-rw-r--r--python3/httplib2/__init__.py3
-rw-r--r--tests/__init__.py2
-rw-r--r--tests/test_http.py30
4 files changed, 37 insertions, 1 deletions
diff --git a/python2/httplib2/__init__.py b/python2/httplib2/__init__.py
index 97e06c1..34281b7 100644
--- a/python2/httplib2/__init__.py
+++ b/python2/httplib2/__init__.py
@@ -1985,6 +1985,9 @@ class Http(object):
headers["user-agent"] = "Python-httplib2/%s (gzip)" % __version__
uri = iri2uri(uri)
+ # Prevent CWE-75 space injection to manipulate request via part of uri.
+ # Prevent CWE-93 CRLF injection to modify headers via part of uri.
+ uri = uri.replace(" ", "%20").replace("\r", "%0D").replace("\n", "%0A")
(scheme, authority, request_uri, defrag_uri) = urlnorm(uri)
diff --git a/python3/httplib2/__init__.py b/python3/httplib2/__init__.py
index 8785cc1..c0b1418 100644
--- a/python3/httplib2/__init__.py
+++ b/python3/httplib2/__init__.py
@@ -1790,6 +1790,9 @@ a string that contains the response entity body.
headers["user-agent"] = "Python-httplib2/%s (gzip)" % __version__
uri = iri2uri(uri)
+ # Prevent CWE-75 space injection to manipulate request via part of uri.
+ # Prevent CWE-93 CRLF injection to modify headers via part of uri.
+ uri = uri.replace(" ", "%20").replace("\r", "%0D").replace("\n", "%0A")
(scheme, authority, request_uri, defrag_uri) = urlnorm(uri)
diff --git a/tests/__init__.py b/tests/__init__.py
index a15db9e..02a3ecf 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -75,7 +75,7 @@ class BufferedReader(object):
chunk = b""
else:
chunk = self._sock.recv(8 << 10)
- # print('!!! recv', chunk)
+ # print("!!! recv", chunk)
if not chunk:
self._end = True
if untilend:
diff --git a/tests/test_http.py b/tests/test_http.py
index df99016..f61992c 100644
--- a/tests/test_http.py
+++ b/tests/test_http.py
@@ -703,3 +703,33 @@ def test_custom_redirect_codes():
response, content = http.request(uri, "GET")
assert response.status == 301
assert response.previous is None
+
+
+def test_cwe93_inject_crlf():
+ # https://cwe.mitre.org/data/definitions/93.html
+ # GET /?q= HTTP/1.1 <- injected "HTTP/1.1" from attacker
+ # injected: attack
+ # ignore-http: HTTP/1.1 <- nominal "HTTP/1.1" from library
+ # Host: localhost:57285
+ http = httplib2.Http()
+ with tests.server_reflect() as uri:
+ danger_url = urllib.parse.urljoin(
+ uri, "?q= HTTP/1.1\r\ninjected: attack\r\nignore-http:"
+ )
+ response, content = http.request(danger_url, "GET")
+ assert response.status == 200
+ req = tests.HttpRequest.from_bytes(content)
+ assert req.headers.get("injected") is None
+
+
+def test_inject_space():
+ # Injecting space into request line is precursor to CWE-93 and possibly other injections
+ http = httplib2.Http()
+ with tests.server_reflect() as uri:
+ # "\r\nignore-http:" suffix is nuance for current server implementation
+ # please only pay attention to space after "?q="
+ danger_url = urllib.parse.urljoin(uri, "?q= HTTP/1.1\r\nignore-http:")
+ response, content = http.request(danger_url, "GET")
+ assert response.status == 200
+ req = tests.HttpRequest.from_bytes(content)
+ assert req.uri == "/?q=%20HTTP/1.1%0D%0Aignore-http:"