diff --git a/extra/vulnserver/vulnserver.py b/extra/vulnserver/vulnserver.py index 4c6d2f4f5..b5175711b 100644 --- a/extra/vulnserver/vulnserver.py +++ b/extra/vulnserver/vulnserver.py @@ -193,6 +193,25 @@ class ReqHandler(BaseHTTPRequestHandler): data = self.rfile.read(length) data = unquote_plus(data.decode(UNICODE_ENCODING, "ignore")) self.data = data + elif self.headers.get("Transfer-encoding") == "chunked": + data, line = b"", b"" + count = 0 + + while True: + line += self.rfile.read(1) + if line.endswith(b'\n'): + if count % 2 == 1: + current = line.rstrip(b"\r\n") + if not current: + break + else: + data += current + + count += 1 + line = b"" + + self.data = data.decode(UNICODE_ENCODING, "ignore") + self.do_REQUEST() def log_message(self, format, *args): diff --git a/lib/core/patch.py b/lib/core/patch.py index 6d809e413..94185d048 100644 --- a/lib/core/patch.py +++ b/lib/core/patch.py @@ -26,10 +26,12 @@ from lib.core.common import readInput from lib.core.common import shellExec from lib.core.common import singleTimeWarnMessage from lib.core.convert import stdoutEncode +from lib.core.data import conf from lib.core.option import _setHTTPHandlers from lib.core.option import setVerbosity from lib.core.settings import IS_WIN from lib.request.templates import getPageTemplate +from thirdparty import six from thirdparty.six.moves import http_client as _http_client def dirtyPatches(): @@ -40,6 +42,17 @@ def dirtyPatches(): # accept overly long result lines (e.g. SQLi results in HTTP header responses) _http_client._MAXLINE = 1 * 1024 * 1024 + # prevent double chunked encoding in case of sqlmap chunking (Note: Python3 does it automatically if 'Content-length' is missing) + if six.PY3: + if not hasattr(_http_client.HTTPConnection, "__send_output"): + _http_client.HTTPConnection.__send_output = _http_client.HTTPConnection._send_output + def _send_output(self, *args, **kwargs): + if conf.chunked and "encode_chunked" in kwargs: + kwargs["encode_chunked"] = False + self.__send_output(*args, **kwargs) + + _http_client.HTTPConnection._send_output = _send_output + # add support for inet_pton() on Windows OS if IS_WIN: from thirdparty.wininetpton import win_inet_pton diff --git a/lib/core/settings.py b/lib/core/settings.py index 9f11a06b4..b3a4635d6 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -18,7 +18,7 @@ from lib.core.enums import OS from thirdparty.six import unichr as _unichr # sqlmap version (...) -VERSION = "1.4.1.52" +VERSION = "1.4.1.53" 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/core/testing.py b/lib/core/testing.py index 8e9640cb8..c282a6839 100644 --- a/lib/core/testing.py +++ b/lib/core/testing.py @@ -52,6 +52,7 @@ def vulnTest(): ("-l --flush-session --keep-alive --skip-waf -v 5 --technique=U --union-from=users --banner --parse-errors", ("banner: '3.", "ORDER BY term out of range", "~xp_cmdshell", "Connection: keep-alive")), ("-l --offline --banner -v 5", ("banner: '3.", "~[TRAFFIC OUT]")), ("-u --flush-session --encoding=ascii --forms --crawl=2 --threads=2 --banner", ("total of 2 targets", "might be injectable", "Type: UNION query", "banner: '3.")), + ("-u --flush-session --data='id=1' --banner --chunked -v 5", ("Parameter: id (POST)", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", "banner: '3.", "Transfer-encoding: chunked")), ("-u --flush-session --data='{\"id\": 1}' --banner", ("might be injectable", "3 columns", "Payload: {\"id\"", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", "banner: '3.")), ("-u --flush-session -H 'Foo: Bar' -H 'Sna: Fu' --data='' --union-char=1 --mobile --answers='smartphone=3' --banner --smart -v 5", ("might be injectable", "Payload: --flush-session --method=PUT --data='a=1&b=2&c=3&id=1' --skip-static --dump -T users --start=1 --stop=2", ("might be injectable", "Parameter: id (PUT)", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", "2 entries")),