From ff968c2331e83800506b0e65e838ce1895b04bf8 Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Thu, 2 May 2019 16:54:54 +0200 Subject: [PATCH] More drei stuff --- extra/safe2bin/safe2bin.py | 4 +- lib/controller/checks.py | 2 +- lib/core/common.py | 76 ++++++++++++++++--------------- lib/core/compat.py | 4 ++ lib/core/convert.py | 52 +++++++++++---------- lib/core/option.py | 3 +- lib/core/settings.py | 6 +-- lib/request/connect.py | 6 ++- lib/techniques/blind/inference.py | 21 +++++---- lib/utils/hash.py | 23 +++++----- tamper/between.py | 4 +- tamper/hex2char.py | 3 +- tamper/symboliclogical.py | 3 +- 13 files changed, 113 insertions(+), 94 deletions(-) diff --git a/extra/safe2bin/safe2bin.py b/extra/safe2bin/safe2bin.py index 9efc81bda..478592225 100644 --- a/extra/safe2bin/safe2bin.py +++ b/extra/safe2bin/safe2bin.py @@ -64,7 +64,9 @@ def safecharencode(value): for char in SAFE_ENCODE_SLASH_REPLACEMENTS: retVal = retVal.replace(char, repr(char).strip('\'')) - retVal = reduce(lambda x, y: x + (y if (y in string.printable or isinstance(value, text_type) and ord(y) >= 160) else '\\x%02x' % ord(y)), retVal, type(value)()) + for char in set(retVal): + if not (char in string.printable or isinstance(value, text_type) and ord(char) >= 160): + retVal = retVal.replace(char, '\\x%02x' % ord(char)) retVal = retVal.replace(SLASH_MARKER, "\\\\") retVal = retVal.replace(HEX_ENCODED_PREFIX_MARKER, HEX_ENCODED_PREFIX) diff --git a/lib/controller/checks.py b/lib/controller/checks.py index cd912cec2..b66f35cab 100644 --- a/lib/controller/checks.py +++ b/lib/controller/checks.py @@ -1377,7 +1377,7 @@ def checkWaf(): conf.timeout = IDS_WAF_CHECK_TIMEOUT try: - retVal = Request.queryPage(place=place, value=value, getRatioValue=True, noteResponseTime=False, silent=True, disableTampering=True)[1] < IDS_WAF_CHECK_RATIO + retVal = (Request.queryPage(place=place, value=value, getRatioValue=True, noteResponseTime=False, silent=True, disableTampering=True)[1] or 0) < IDS_WAF_CHECK_RATIO except SqlmapConnectionException: retVal = True finally: diff --git a/lib/core/common.py b/lib/core/common.py index ba69a3e26..7a111d803 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -11,6 +11,7 @@ import collections import contextlib import copy import distutils +import functools import getpass import hashlib import inspect @@ -1849,7 +1850,7 @@ def safeFilepathEncode(filepath): retVal = filepath - if filepath and isinstance(filepath, six.text_type): + if filepath and six.PY2 and isinstance(filepath, six.text_type): retVal = filepath.encode(sys.getfilesystemencoding() or UNICODE_ENCODING) return retVal @@ -1929,8 +1930,8 @@ def getFilteredPageContent(page, onlyText=True, split=" "): Returns filtered page content without script, style and/or comments or all HTML tags - >>> getFilteredPageContent(u'foobartest') - u'foobar test' + >>> getFilteredPageContent(u'foobartest') == "foobar test" + True """ retVal = page @@ -1947,8 +1948,8 @@ def getPageWordSet(page): """ Returns word set used in page content - >>> sorted(getPageWordSet(u'foobartest')) - [u'foobar', u'test'] + >>> sorted(getPageWordSet(u'foobartest')) == [u'foobar', u'test'] + True """ retVal = set() @@ -2459,13 +2460,13 @@ def decodeHex(value): True """ - return bytes.fromhex(value) if hasattr(bytes, "fromhex") else value.decode("hex") + return bytes.fromhex(getUnicode(value)) if hasattr(bytes, "fromhex") else value.decode("hex") def getBytes(value, encoding=UNICODE_ENCODING, errors="strict"): """ Returns byte representation of provided Unicode value - >>> getBytes(getUnicode("foo\x01\x83\xffbar")) == b"foo\x01\x83\xffbar" + >>> getBytes(getUnicode(b"foo\\x01\\x83\\xffbar")) == b"foo\\x01\\x83\\xffbar" True """ @@ -2488,9 +2489,9 @@ def getOrds(value): """ Returns ORD(...) representation of provided string value - >>> getOrds(u'fo\xf6bar') + >>> getOrds(u'fo\\xf6bar') [102, 111, 246, 98, 97, 114] - >>> getOrds(b"fo\xc3\xb6bar") + >>> getOrds(b"fo\\xc3\\xb6bar") [102, 111, 195, 182, 98, 97, 114] """ @@ -2642,8 +2643,8 @@ def extractErrorMessage(page): """ Returns reported error message from page if it founds one - >>> extractErrorMessage(u'Test\\nWarning: oci_parse() [function.oci-parse]: ORA-01756: quoted string not properly terminated

Only a test page

') - u'oci_parse() [function.oci-parse]: ORA-01756: quoted string not properly terminated' + >>> extractErrorMessage(u'Test\\nWarning: oci_parse() [function.oci-parse]: ORA-01756: quoted string not properly terminated

Only a test page

') == u'oci_parse() [function.oci-parse]: ORA-01756: quoted string not properly terminated' + True """ retVal = None @@ -2716,10 +2717,10 @@ def urldecode(value, encoding=None, unsafe="%%&=;+%s" % CUSTOM_INJECTION_MARK_CH """ URL decodes given value - >>> urldecode('AND%201%3E%282%2B3%29%23', convall=True) - u'AND 1>(2+3)#' - >>> urldecode('AND%201%3E%282%2B3%29%23', convall=False) - u'AND 1>(2%2B3)#' + >>> urldecode('AND%201%3E%282%2B3%29%23', convall=True) == 'AND 1>(2+3)#' + True + >>> urldecode('AND%201%3E%282%2B3%29%23', convall=False) == 'AND 1>(2%2B3)#' + True """ result = value @@ -2738,7 +2739,7 @@ def urldecode(value, encoding=None, unsafe="%%&=;+%s" % CUSTOM_INJECTION_MARK_CH charset = set(string.printable) - set(unsafe) def _(match): - char = chr(ord(match.group(1).decode("hex"))) + char = getUnicode(decodeHex(match.group(1))) return char if char in charset else match.group(0) if spaceplus: @@ -3020,13 +3021,15 @@ def findDynamicContent(firstPage, secondPage): prefix = prefix[-DYNAMICITY_BOUNDARY_LENGTH:] suffix = suffix[:DYNAMICITY_BOUNDARY_LENGTH] - infix = max(re.search(r"(?s)%s(.+)%s" % (re.escape(prefix), re.escape(suffix)), _) for _ in (firstPage, secondPage)).group(1) - - if infix[0].isalnum(): - prefix = trimAlphaNum(prefix) - - if infix[-1].isalnum(): - suffix = trimAlphaNum(suffix) + for _ in (firstPage, secondPage): + match = re.search(r"(?s)%s(.+)%s" % (re.escape(prefix), re.escape(suffix)), _) + if match: + infix = match.group(1) + if infix[0].isalnum(): + prefix = trimAlphaNum(prefix) + if infix[-1].isalnum(): + suffix = trimAlphaNum(suffix) + break kb.dynamicMarkings.append((prefix if prefix else None, suffix if suffix else None)) @@ -3557,7 +3560,7 @@ def getLatestRevision(): req = _urllib.request.Request(url="https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/lib/core/settings.py") try: - content = _urllib.request.urlopen(req).read() + content = getUnicode(_urllib.request.urlopen(req).read()) retVal = extractRegexResult(r"VERSION\s*=\s*[\"'](?P[\d.]+)", content) except: pass @@ -4423,12 +4426,8 @@ def serializeObject(object_): """ Serializes given object - >>> serializeObject([1, 2, 3, ('a', 'b')]) - 'gAJdcQEoSwFLAksDVQFhVQFihnECZS4=' - >>> serializeObject(None) - 'gAJOLg==' - >>> serializeObject('foobar') - 'gAJVBmZvb2JhcnEBLg==' + >>> type(serializeObject([1, 2, 3, ('a', 'b')])) == six.binary_type + True """ return base64pickle(object_) @@ -4668,7 +4667,10 @@ def prioritySortColumns(columns): def _(column): return column and "id" in column.lower() - return sorted(sorted(columns, key=len), lambda x, y: -1 if _(x) and not _(y) else 1 if not _(x) and _(y) else 0) + if six.PY2: + return sorted(sorted(columns, key=len), lambda x, y: -1 if _(x) and not _(y) else 1 if not _(x) and _(y) else 0) + else: + return sorted(sorted(columns, key=len), key=functools.cmp_to_key(lambda x, y: -1 if _(x) and not _(y) else 1 if not _(x) and _(y) else 0)) def getRequestHeader(request, name): """ @@ -4975,12 +4977,12 @@ def safeVariableNaming(value): """ Returns escaped safe-representation of a given variable name that can be used in Python evaluated code - >>> safeVariableNaming("class.id") - 'EVAL_636c6173732e6964' + >>> safeVariableNaming("class.id") == "EVAL_636c6173732e6964" + True """ if value in keyword.kwlist or re.search(r"\A[^a-zA-Z]|[^\w]", value): - value = "%s%s" % (EVALCODE_ENCODED_PREFIX, value.encode(UNICODE_ENCODING).encode("hex")) + value = "%s%s" % (EVALCODE_ENCODED_PREFIX, getUnicode(binascii.hexlify(getBytes(value)))) return value @@ -4988,12 +4990,12 @@ def unsafeVariableNaming(value): """ Returns unescaped safe-representation of a given variable name - >>> unsafeVariableNaming("EVAL_636c6173732e6964") - u'class.id' + >>> unsafeVariableNaming("EVAL_636c6173732e6964") == "class.id" + True """ if value.startswith(EVALCODE_ENCODED_PREFIX): - value = value[len(EVALCODE_ENCODED_PREFIX):].decode("hex").decode(UNICODE_ENCODING) + value = getUnicode(decodeHex(value[len(EVALCODE_ENCODED_PREFIX):])) return value diff --git a/lib/core/compat.py b/lib/core/compat.py index 0cb669f81..850d86bbc 100644 --- a/lib/core/compat.py +++ b/lib/core/compat.py @@ -162,6 +162,10 @@ class WichmannHill(random.Random): z = (z + a) % 256 or 1 self.__whseed(x, y, z) +def patchHeaders(headers): + if not hasattr(headers, "headers"): + headers.headers = ["%s: %s\r\n" % (header, headers[header]) for header in headers] + # Reference: https://github.com/urllib3/urllib3/blob/master/src/urllib3/filepost.py def choose_boundary(): return uuid.uuid4().hex diff --git a/lib/core/convert.py b/lib/core/convert.py index f847f3afa..08fee210c 100644 --- a/lib/core/convert.py +++ b/lib/core/convert.py @@ -11,6 +11,7 @@ except: import pickle import base64 +import binascii import json import re import sys @@ -24,8 +25,8 @@ def base64decode(value): """ Decodes string value from Base64 to plain format - >>> base64decode('Zm9vYmFy') - 'foobar' + >>> base64decode('Zm9vYmFy') == b'foobar' + True """ return base64.b64decode(unicodeencode(value)) @@ -34,8 +35,8 @@ def base64encode(value): """ Encodes string value from plain to Base64 format - >>> base64encode('foobar') - 'Zm9vYmFy' + >>> base64encode('foobar') == b'Zm9vYmFy' + True """ return base64.b64encode(unicodeencode(value)) @@ -44,8 +45,8 @@ def base64pickle(value): """ Serializes (with pickle) and encodes to Base64 format supplied (binary) value - >>> base64pickle('foobar') - 'gAJVBmZvb2JhcnEBLg==' + >>> base64unpickle(base64pickle([1, 2, 3])) == [1, 2, 3] + True """ retVal = None @@ -68,8 +69,8 @@ def base64unpickle(value): """ Decodes value from Base64 to plain format and deserializes (with pickle) its content - >>> base64unpickle('gAJVBmZvb2JhcnEBLg==') - 'foobar' + >>> type(base64unpickle('gAJjX19idWlsdGluX18Kb2JqZWN0CnEBKYFxAi4=')) == object + True """ retVal = None @@ -85,8 +86,8 @@ def hexdecode(value): """ Decodes string value from hex to plain format - >>> hexdecode('666f6f626172') - 'foobar' + >>> hexdecode('666f6f626172') == b'foobar' + True """ value = value.lower() @@ -103,16 +104,12 @@ def hexencode(value, encoding=None): """ Encodes string value from plain to hex format - >>> hexencode('foobar') - '666f6f626172' + >>> hexencode('foobar') == b'666f6f626172' + True """ retVal = unicodeencode(value, encoding) - - if six.PY2: - retVal = retVal.encode("hex") - else: - retVal = retVal.hex() + retVal = binascii.hexlify(retVal) return retVal @@ -120,8 +117,8 @@ def unicodeencode(value, encoding=None): """ Returns 8-bit string representation of the supplied unicode value - >>> unicodeencode(u'foobar') - 'foobar' + >>> unicodeencode(u'foobar') == b'foobar' + True """ retVal = value @@ -138,8 +135,8 @@ def utf8encode(value): """ Returns 8-bit string representation of the supplied UTF-8 value - >>> utf8encode(u'foobar') - 'foobar' + >>> utf8encode(u'foobar') == b'foobar' + True """ return unicodeencode(value, "utf-8") @@ -148,11 +145,16 @@ def utf8decode(value): """ Returns UTF-8 representation of the supplied 8-bit string representation - >>> utf8decode('foobar') + >>> utf8decode(b'foobar') u'foobar' """ - return value.decode("utf-8") + retVal = value + + if isinstance(value, six.binary_type): + retVal = value.decode("utf-8") + + return retVal def htmlunescape(value): """ @@ -217,8 +219,8 @@ def dejsonize(data): """ Returns JSON deserialized data - >>> dejsonize('{\\n "foo": "bar"\\n}') - {u'foo': u'bar'} + >>> dejsonize('{\\n "foo": "bar"\\n}') == {u'foo': u'bar'} + True """ return json.loads(data) diff --git a/lib/core/option.py b/lib/core/option.py index 1c53c07d3..c694fb4ec 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -1765,7 +1765,8 @@ def _cleanupOptions(): conf.string = decodeStringEscape(conf.string) if conf.getAll: - map(lambda _: conf.__setitem__(_, True), WIZARD.ALL) + for _ in WIZARD.ALL: + conf.__setitem__(_, True) if conf.noCast: for _ in list(DUMP_REPLACEMENTS.keys()): diff --git a/lib/core/settings.py b/lib/core/settings.py index 10cbbdf5f..117dc21b9 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -17,7 +17,7 @@ from lib.core.enums import DBMS_DIRECTORY_NAME from lib.core.enums import OS # sqlmap version (...) -VERSION = "1.3.5.3" +VERSION = "1.3.5.4" 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) @@ -839,8 +839,8 @@ for key, value in os.environ.items(): def _reversible(ex): if isinstance(ex, UnicodeDecodeError): if INVALID_UNICODE_PRIVATE_AREA: - return ("".join(unichr(int('000f00%2x' % ord(_), 16)) for _ in ex.object[ex.start:ex.end]), ex.end) + return (u"".join(unichr(int('000f00%2x' % (_ if isinstance(_, int) else ord(_)), 16)) for _ in ex.object[ex.start:ex.end]), ex.end) else: - return ("".join(INVALID_UNICODE_CHAR_FORMAT % ord(_) for _ in ex.object[ex.start:ex.end]).decode(UNICODE_ENCODING), ex.end) + return (u"".join(INVALID_UNICODE_CHAR_FORMAT % (_ if isinstance(_, int) else ord(_)) for _ in ex.object[ex.start:ex.end]), ex.end) codecs.register_error("reversible", _reversible) diff --git a/lib/request/connect.py b/lib/request/connect.py index d6a88ed01..b1f8a9ef3 100644 --- a/lib/request/connect.py +++ b/lib/request/connect.py @@ -58,6 +58,7 @@ from lib.core.common import wasLastResponseDelayed from lib.core.common import unsafeVariableNaming from lib.core.common import urldecode from lib.core.common import urlencode +from lib.core.compat import patchHeaders from lib.core.compat import xrange from lib.core.data import conf from lib.core.data import kb @@ -517,6 +518,7 @@ class Connect(object): code = (code or conn.code) if conn.code == kb.originalCode else conn.code # do not override redirection code (for comparison purposes) responseHeaders = conn.info() responseHeaders[URI_HTTP_HEADER] = conn.geturl() + patchHeaders(responseHeaders) kb.serverHeader = responseHeaders.get(HTTP_HEADER.SERVER, kb.serverHeader) else: code = None @@ -592,6 +594,7 @@ class Connect(object): page = ex.read() if not skipRead else None responseHeaders = ex.info() responseHeaders[URI_HTTP_HEADER] = ex.geturl() + patchHeaders(responseHeaders) page = decodePage(page, responseHeaders.get(HTTP_HEADER.CONTENT_ENCODING), responseHeaders.get(HTTP_HEADER.CONTENT_TYPE)) except socket.timeout: warnMsg = "connection timed out while trying " @@ -1349,8 +1352,7 @@ class Connect(object): kb.permissionFlag = True singleTimeWarnMessage("potential permission problems detected ('%s')" % message) - if not hasattr(headers, "headers"): - headers.headers = ["%s: %s\r\n" % (header, headers[header]) for header in headers] + patchHeaders(headers) if content or response: return page, headers, code diff --git a/lib/techniques/blind/inference.py b/lib/techniques/blind/inference.py index 8355b5af1..87fcf8e9b 100644 --- a/lib/techniques/blind/inference.py +++ b/lib/techniques/blind/inference.py @@ -158,7 +158,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None length = None showEta = conf.eta and isinstance(length, int) - numThreads = min(conf.threads, length) or 1 + numThreads = min(conf.threads or 0, length or 0) or 1 if showEta: progress = ProgressBar(maxValue=length) @@ -198,8 +198,10 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None else: posValue = ord(hintValue[idx - 1]) + markingValue = "'%s'" % CHAR_INFERENCE_MARK + unescapedCharValue = unescaper.escape("'%s'" % decodeIntToUnicode(posValue)) forgedPayload = agent.extractPayload(payload) - forgedPayload = safeStringFormat(forgedPayload.replace(INFERENCE_GREATER_CHAR, INFERENCE_EQUALS_CHAR), (expressionUnescaped, idx, posValue)) + forgedPayload = safeStringFormat(forgedPayload.replace(INFERENCE_GREATER_CHAR, INFERENCE_EQUALS_CHAR), (expressionUnescaped, idx, posValue)).replace(markingValue, unescapedCharValue) result = Request.queryPage(agent.replacePayload(payload, forgedPayload), timeBasedCompare=timeBasedCompare, raise404=False) incrementCounter(kb.technique) @@ -293,12 +295,13 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None lastChar = [_ for _ in threadData.shared.value if _ is not None][-1] except IndexError: lastChar = None - if 'a' <= lastChar <= 'z': - position = charTbl.index(ord('a') - 1) # 96 - elif 'A' <= lastChar <= 'Z': - position = charTbl.index(ord('A') - 1) # 64 - elif '0' <= lastChar <= '9': - position = charTbl.index(ord('0') - 1) # 47 + else: + if 'a' <= lastChar <= 'z': + position = charTbl.index(ord('a') - 1) # 96 + elif 'A' <= lastChar <= 'Z': + position = charTbl.index(ord('A') - 1) # 64 + elif '0' <= lastChar <= '9': + position = charTbl.index(ord('0') - 1) # 47 except ValueError: pass finally: @@ -633,7 +636,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None dataToStdout(filterControlChars(val)) # some DBMSes (e.g. Firebird, DB2, etc.) have issues with trailing spaces - if len(partialValue) > INFERENCE_BLANK_BREAK and partialValue[-INFERENCE_BLANK_BREAK:].isspace(): + if Backend.getIdentifiedDbms() in (DBMS.FIREBIRD, DBMS.DB2, DBMS.MAXDB) and len(partialValue) > INFERENCE_BLANK_BREAK and partialValue[-INFERENCE_BLANK_BREAK:].isspace(): finalValue = partialValue[:-INFERENCE_BLANK_BREAK] break elif charsetType and partialValue[-1:].isspace(): diff --git a/lib/utils/hash.py b/lib/utils/hash.py index cf52fb562..d39a72506 100644 --- a/lib/utils/hash.py +++ b/lib/utils/hash.py @@ -724,19 +724,20 @@ def attackDumpedTable(): def hashRecognition(value): retVal = None - isOracle, isMySQL = Backend.isDbms(DBMS.ORACLE), Backend.isDbms(DBMS.MYSQL) + if six.PY2: # currently only supported on Python2 + isOracle, isMySQL = Backend.isDbms(DBMS.ORACLE), Backend.isDbms(DBMS.MYSQL) - if isinstance(value, six.string_types): - for name, regex in getPublicTypeMembers(HASH): - # Hashes for Oracle and old MySQL look the same hence these checks - if isOracle and regex == HASH.MYSQL_OLD or isMySQL and regex == HASH.ORACLE_OLD: - continue - elif regex == HASH.CRYPT_GENERIC: - if any((value.lower() == value, value.upper() == value)): + if isinstance(value, six.string_types): + for name, regex in getPublicTypeMembers(HASH): + # Hashes for Oracle and old MySQL look the same hence these checks + if isOracle and regex == HASH.MYSQL_OLD or isMySQL and regex == HASH.ORACLE_OLD: continue - elif re.match(regex, value): - retVal = regex - break + elif regex == HASH.CRYPT_GENERIC: + if any((value.lower() == value, value.upper() == value)): + continue + elif re.match(regex, value): + retVal = regex + break return retVal diff --git a/tamper/between.py b/tamper/between.py index d9c971660..5c8392990 100644 --- a/tamper/between.py +++ b/tamper/between.py @@ -34,6 +34,8 @@ def tamper(payload, **kwargs): '1 AND A NOT BETWEEN 0 AND B--' >>> tamper('1 AND A = B--') '1 AND A BETWEEN B AND B--' + >>> tamper('1 AND LAST_INSERT_ROWID()=LAST_INSERT_ROWID()') + '1 AND LAST_INSERT_ROWID() BETWEEN LAST_INSERT_ROWID() AND LAST_INSERT_ROWID()' """ retVal = payload @@ -48,7 +50,7 @@ def tamper(payload, **kwargs): retVal = re.sub(r"\s*>\s*(\d+|'[^']+'|\w+\(\d+\))", r" NOT BETWEEN 0 AND \g<1>", payload) if retVal == payload: - match = re.search(r"(?i)(\b(AND|OR)\b\s+)(?!.*\b(AND|OR)\b)([^=]+?)\s*=\s*(\w+)\s*", payload) + match = re.search(r"(?i)(\b(AND|OR)\b\s+)(?!.*\b(AND|OR)\b)([^=]+?)\s*=\s*([\w()]+)\s*", payload) if match: _ = "%s %s BETWEEN %s AND %s" % (match.group(2), match.group(4), match.group(5), match.group(5)) diff --git a/tamper/hex2char.py b/tamper/hex2char.py index 37d9fd3c8..3f86aa86f 100644 --- a/tamper/hex2char.py +++ b/tamper/hex2char.py @@ -8,6 +8,7 @@ See the file 'LICENSE' for copying permission import re from lib.core.common import decodeHex +from lib.core.common import getOrds from lib.core.enums import PRIORITY __priority__ = PRIORITY.NORMAL @@ -37,7 +38,7 @@ def tamper(payload, **kwargs): if payload: for match in re.finditer(r"\b0x([0-9a-f]+)\b", retVal): if len(match.group(1)) > 2: - result = "CONCAT(%s)" % ','.join("CHAR(%d)" % ord(_) for _ in decodeHex(match.group(1))) + result = "CONCAT(%s)" % ','.join("CHAR(%d)" % _ for _ in getOrds(decodeHex(match.group(1)))) else: result = "CHAR(%d)" % ord(decodeHex(match.group(1))) retVal = retVal.replace(match.group(0), result) diff --git a/tamper/symboliclogical.py b/tamper/symboliclogical.py index df542d4b5..bbf55737b 100644 --- a/tamper/symboliclogical.py +++ b/tamper/symboliclogical.py @@ -6,7 +6,6 @@ See the file 'LICENSE' for copying permission """ import re -import urllib from lib.core.enums import PRIORITY @@ -26,6 +25,6 @@ def tamper(payload, **kwargs): retVal = payload if payload: - retVal = re.sub(r"(?i)\bAND\b", urllib.quote("&&"), re.sub(r"(?i)\bOR\b", urllib.quote("||"), payload)) + retVal = re.sub(r"(?i)\bAND\b", "%26%26", re.sub(r"(?i)\bOR\b", "%7C%7C", payload)) return retVal