diff options
author | Sergey Shepelev <temotor@gmail.com> | 2020-05-20 14:56:12 +0300 |
---|---|---|
committer | Sergey Shepelev <temotor@gmail.com> | 2020-05-20 15:00:24 +0300 |
commit | a1457cc31f3206cf691d11d2bf34e98865873e9e (patch) | |
tree | eea5f3ce040d060ccda4f94aba7cdb68d60063a6 | |
parent | 9413ffc973a2dc90abf787509ee82238345d5602 (diff) | |
download | httplib2-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__.py | 3 | ||||
-rw-r--r-- | python3/httplib2/__init__.py | 3 | ||||
-rw-r--r-- | tests/__init__.py | 2 | ||||
-rw-r--r-- | tests/test_http.py | 30 |
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:" |