diff --git a/lib/core/settings.py b/lib/core/settings.py index 4424ed251..ee2ac49de 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -20,7 +20,7 @@ from lib.core.enums import OS from thirdparty import six # sqlmap version (...) -VERSION = "1.10.8.0" +VERSION = "1.10.8.1" TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable" TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34} VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE) diff --git a/lib/request/redirecthandler.py b/lib/request/redirecthandler.py index f7a6fce81..33d498627 100644 --- a/lib/request/redirecthandler.py +++ b/lib/request/redirecthandler.py @@ -160,7 +160,13 @@ class SmartRedirectHandler(_urllib.request.HTTPRedirectHandler): # Note: multiple cookies arrive as SEPARATE Set-Cookie headers (RFC-6265 forbids folding # them into one comma-joined value), and __getitem__ returns only the FIRST - iterate all # values so 2nd+ cookies (e.g. a CSRF token) are not silently dropped across the redirect - setCookies = headers.get_all(HTTP_HEADER.SET_COOKIE) if hasattr(headers, "get_all") else [headers[HTTP_HEADER.SET_COOKIE]] + # (get_all on py3 email.message.Message, getheaders on py2 mimetools.Message) + if hasattr(headers, "get_all"): + setCookies = headers.get_all(HTTP_HEADER.SET_COOKIE) + elif hasattr(headers, "getheaders"): + setCookies = headers.getheaders(HTTP_HEADER.SET_COOKIE) + else: + setCookies = [headers[HTTP_HEADER.SET_COOKIE]] for setCookie in setCookies: for match in re.finditer(r"(?:^|,\s*)([^=;,]+)=([^;,]+)", setCookie): key = match.group(1).strip() diff --git a/tests/test_request_basic.py b/tests/test_request_basic.py index c9e69be24..5456b552e 100644 --- a/tests/test_request_basic.py +++ b/tests/test_request_basic.py @@ -102,9 +102,8 @@ class TestRedirectSetCookieMerge(unittest.TestCase): kb.choices.redirect = self._redirect def test_all_set_cookies_merged_across_redirect(self): - import email, io - from http.client import HTTPMessage from lib.core.enums import HTTP_HEADER, REDIRECTION + from thirdparty import six from thirdparty.six.moves import urllib as _urllib import lib.request.redirecthandler as rh @@ -112,23 +111,32 @@ class TestRedirectSetCookieMerge(unittest.TestCase): conf.scope = None kb.choices.redirect = REDIRECTION.YES + raw = ("Location: http://example.com/home\r\n" + "Set-Cookie: sid=NEW; Path=/; HttpOnly\r\n" + "Set-Cookie: csrf=XYZ; Path=/\r\n\r\n") + # build the same headers object type the redirect handler receives on this interpreter: + # py3 http.client.HTTPMessage (email.message.Message, get_all) / py2 mimetools.Message (getheaders) + if six.PY2: + import mimetools + headers = mimetools.Message(six.StringIO(raw)) + else: + from email import message_from_string + from thirdparty.six.moves.http_client import HTTPMessage + headers = message_from_string(raw, _class=HTTPMessage) + # stub the network-following parent so the test touches no socket saved = _urllib.request.HTTPRedirectHandler.http_error_302 _urllib.request.HTTPRedirectHandler.http_error_302 = lambda self, req, fp, code, msg, headers: fp try: req = _urllib.request.Request("http://example.com/login", headers={"Cookie": "sid=OLD"}) - raw = ("Location: http://example.com/home\r\n" - "Set-Cookie: sid=NEW; Path=/; HttpOnly\r\n" - "Set-Cookie: csrf=XYZ; Path=/\r\n\r\n") - headers = email.message_from_string(raw, _class=HTTPMessage) - fp = _urllib.response.addinfourl(io.BytesIO(b""), headers, req.get_full_url()) + fp = _urllib.response.addinfourl(six.BytesIO(b""), headers, req.get_full_url()) rh.SmartRedirectHandler().http_error_302(req, fp, 302, "Found", headers) finally: _urllib.request.HTTPRedirectHandler.http_error_302 = saved merged = req.headers.get(HTTP_HEADER.COOKIE) or req.headers.get("Cookie") or "" self.assertIn("sid=NEW", merged) - self.assertIn("csrf=XYZ", merged) # the 2nd Set-Cookie must survive the redirect + self.assertIn("csrf=XYZ", merged) # the 2nd Set-Cookie must survive the redirect (order-independent) class TestForgeHeadersCookieMerge(unittest.TestCase):