From afe497a954cb06842a9e2581393381c4e01f940a Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Thu, 28 Mar 2019 13:53:54 +0100 Subject: [PATCH] Dealing with basesting (one baby step closer to Py3 salvation) --- lib/controller/checks.py | 3 +- lib/core/common.py | 83 +++++++++++++------------ lib/core/convert.py | 3 +- lib/core/dump.py | 12 ++-- lib/core/option.py | 7 ++- lib/core/settings.py | 2 +- lib/parse/payloads.py | 4 +- lib/request/basic.py | 4 +- lib/request/connect.py | 11 ++-- lib/request/inject.py | 3 +- lib/request/redirecthandler.py | 2 +- lib/takeover/metasploit.py | 3 +- lib/takeover/udf.py | 4 +- lib/techniques/blind/inference.py | 10 +-- lib/techniques/error/use.py | 7 ++- lib/techniques/union/use.py | 9 +-- lib/utils/hash.py | 7 ++- lib/utils/pivotdumptable.py | 2 +- plugins/dbms/maxdb/enumeration.py | 3 +- plugins/dbms/mssqlserver/enumeration.py | 8 +-- plugins/dbms/sybase/enumeration.py | 5 +- plugins/generic/databases.py | 6 +- plugins/generic/entries.py | 5 +- plugins/generic/search.py | 3 +- thirdparty/clientform/clientform.py | 4 +- 25 files changed, 112 insertions(+), 98 deletions(-) diff --git a/lib/controller/checks.py b/lib/controller/checks.py index 26eeaa855..ab0110845 100644 --- a/lib/controller/checks.py +++ b/lib/controller/checks.py @@ -105,6 +105,7 @@ from lib.request.inject import checkBooleanExpression from lib.request.templates import getPageTemplate from lib.techniques.union.test import unionTest from lib.techniques.union.use import configUnion +from thirdparty import six from thirdparty.six.moves import http_client as _http_client def checkSqlInjection(place, parameter, value): @@ -692,7 +693,7 @@ def checkSqlInjection(place, parameter, value): # Test for UNION query SQL injection reqPayload, vector = unionTest(comment, place, parameter, value, prefix, suffix) - if isinstance(reqPayload, basestring): + if isinstance(reqPayload, six.string_types): infoMsg = "%s parameter '%s' is '%s' injectable" % (paramType, parameter, title) logger.info(infoMsg) diff --git a/lib/core/common.py b/lib/core/common.py index 0c00d1cc0..a2d4ccd14 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -167,6 +167,7 @@ from lib.core.settings import VERSION_STRING from lib.core.settings import WEBSCARAB_SPLITTER from lib.core.threads import getCurrentThreadData from lib.utils.sqlalchemy import _sqlalchemy +from thirdparty import six from thirdparty.clientform.clientform import ParseResponse from thirdparty.clientform.clientform import ParseError from thirdparty.colorama.initialise import init as coloramainit @@ -355,7 +356,7 @@ class Backend: @staticmethod def setVersion(version): - if isinstance(version, basestring): + if isinstance(version, six.string_types): kb.dbmsVersion = [version] return kb.dbmsVersion @@ -364,7 +365,7 @@ class Backend: def setVersionList(versionsList): if isinstance(versionsList, list): kb.dbmsVersion = versionsList - elif isinstance(versionsList, basestring): + elif isinstance(versionsList, six.string_types): Backend.setVersion(versionsList) else: logger.error("invalid format of versionsList") @@ -387,7 +388,7 @@ class Backend: return None # Little precaution, in theory this condition should always be false - elif kb.os is not None and isinstance(os, basestring) and kb.os.lower() != os.lower(): + elif kb.os is not None and isinstance(os, six.string_types) and kb.os.lower() != os.lower(): msg = "sqlmap previously fingerprinted back-end DBMS " msg += "operating system %s. However now it has " % kb.os msg += "been fingerprinted to be %s. " % os @@ -406,7 +407,7 @@ class Backend: warnMsg = "invalid value" logger.warn(warnMsg) - elif kb.os is None and isinstance(os, basestring): + elif kb.os is None and isinstance(os, six.string_types): kb.os = os.capitalize() return kb.os @@ -416,7 +417,7 @@ class Backend: if version is None: return None - elif kb.osVersion is None and isinstance(version, basestring): + elif kb.osVersion is None and isinstance(version, six.string_types): kb.osVersion = version @staticmethod @@ -436,7 +437,7 @@ class Backend: while True: choice = readInput(msg, default='1') - if isinstance(choice, basestring) and choice.isdigit() and int(choice) in (1, 2): + if hasattr(choice, "isdigit") and choice.isdigit() and int(choice) in (1, 2): kb.arch = 32 if int(choice) == 1 else 64 break else: @@ -640,7 +641,7 @@ def paramToDict(place, parameters=None): if isinstance(value, (list, tuple, set, dict)): if value: walk(head, value) - elif isinstance(value, (bool, int, float, basestring)): + elif isinstance(value, (bool, int, float, six.string_types)): original = current[key] if isinstance(value, bool): current[key] = "%s%s" % (getUnicode(value).lower(), BOUNDED_INJECTION_MARKER) @@ -884,7 +885,7 @@ def setColor(message, color=None, bold=False, level=None): if bold or color: retVal = colored(message, color=color, on_color=None, attrs=("bold",) if bold else None) elif level: - level = getattr(logging, level, None) if isinstance(level, basestring) else level + level = getattr(logging, level, None) if isinstance(level, six.string_types) else level retVal = LOGGER_HANDLER.colorize(message, level) return retVal @@ -935,7 +936,7 @@ def dataToStdout(data, forceOutput=False, bold=False, content_type=None, status= if multiThreadMode: logging._releaseLock() - kb.prependFlag = isinstance(data, basestring) and (len(data) == 1 and data not in ('\n', '\r') or len(data) > 2 and data[0] == '\r' and data[-1] != '\n') + kb.prependFlag = isinstance(data, six.string_types) and (len(data) == 1 and data not in ('\n', '\r') or len(data) > 2 and data[0] == '\r' and data[-1] != '\n') def dataToTrafficFile(data): if not conf.trafficFile: @@ -1068,7 +1069,7 @@ def readInput(message, default=None, checkBatch=True, boolean=False): finally: logging._releaseLock() - if retVal and default and isinstance(default, basestring) and len(default) == 1: + if retVal and default and isinstance(default, six.string_types) and len(default) == 1: retVal = retVal.strip() if boolean: @@ -1663,7 +1664,7 @@ def parseUnionPage(page): else: data = page - if len(data) == 1 and isinstance(data[0], basestring): + if len(data) == 1 and isinstance(data[0], six.string_types): data = data[0] return data @@ -1861,7 +1862,7 @@ def safeStringFormat(format_, params): else: retVal = re.sub(r"(\A|[^A-Za-z0-9])(%d)([^A-Za-z0-9]|\Z)", r"\g<1>%s\g<3>", format_) - if isinstance(params, basestring): + if isinstance(params, six.string_types): retVal = retVal.replace("%s", params, 1) elif not isListLike(params): retVal = retVal.replace("%s", getUnicode(params), 1) @@ -2383,9 +2384,9 @@ def getUnicode(value, encoding=None, noneToNull=False): if noneToNull and value is None: return NULL - if isinstance(value, unicode): + if isinstance(value, six.text_type): return value - elif isinstance(value, basestring): + elif isinstance(value, six.binary_type): # Heuristics (if encoding not explicitly specified) candidates = filter(None, (encoding, kb.get("pageEncoding") if kb.get("originalPage") else None, conf.get("encoding"), UNICODE_ENCODING, sys.getfilesystemencoding())) if all(_ in value for _ in ('<', '>')): @@ -2397,16 +2398,16 @@ def getUnicode(value, encoding=None, noneToNull=False): for candidate in candidates: try: - return unicode(value, candidate) + return six.text_type(value, candidate) except UnicodeDecodeError: pass while True: try: - return unicode(value, encoding or (kb.get("pageEncoding") if kb.get("originalPage") else None) or UNICODE_ENCODING) + return six.text_type(value, encoding or (kb.get("pageEncoding") if kb.get("originalPage") else None) or UNICODE_ENCODING) except UnicodeDecodeError as ex: try: - return unicode(value, UNICODE_ENCODING) + return six.text_type(value, UNICODE_ENCODING) except: value = value[:ex.start] + "".join(INVALID_UNICODE_CHAR_FORMAT % ord(_) for _ in value[ex.start:ex.end]) + value[ex.end:] elif isListLike(value): @@ -2414,9 +2415,9 @@ def getUnicode(value, encoding=None, noneToNull=False): return value else: try: - return unicode(value) + return six.text_type(value) except UnicodeDecodeError: - return unicode(str(value), errors="ignore") # encoding ignored for non-basestring instances + return six.text_type(str(value), errors="ignore") # encoding ignored for non-basestring instances def longestCommonPrefix(*sequences): """ @@ -2568,7 +2569,7 @@ def extractErrorMessage(page): retVal = None - if isinstance(page, basestring): + if isinstance(page, six.string_types): for regex in ERROR_PARSING_REGEXES: match = re.search(regex, page, re.IGNORECASE) @@ -2867,7 +2868,7 @@ def isNumPosStrValue(value): False """ - return (value and isinstance(value, basestring) and value.isdigit() and int(value) > 0) or (isinstance(value, int) and value > 0) + return (hasattr(value, "isdigit") and value.isdigit() and int(value) > 0) or (isinstance(value, int) and value > 0) @cachedmethod def aliasToDbmsEnum(dbms): @@ -3015,7 +3016,7 @@ def isDBMSVersionAtLeast(version): value = filterStringValue(value, '[0-9.><=]') - if value and isinstance(value, basestring): + if value and isinstance(value, six.string_types): if value.startswith(">="): value = float(value.replace(">=", "")) elif value.startswith(">"): @@ -3145,7 +3146,7 @@ def saveConfig(conf, filename): elif datatype == OPTION_TYPE.STRING: value = "" - if isinstance(value, basestring): + if isinstance(value, six.string_types): value = value.replace("\n", "\n ") config.set(family, option, value) @@ -3176,7 +3177,7 @@ def initTechnique(technique=None): for key, value in kb.injection.conf.items(): if value and (not hasattr(conf, key) or (hasattr(conf, key) and not getattr(conf, key))): setattr(conf, key, value) - debugMsg = "resuming configuration option '%s' (%s)" % (key, ("'%s'" % value) if isinstance(value, basestring) else value) + debugMsg = "resuming configuration option '%s' (%s)" % (key, ("'%s'" % value) if isinstance(value, six.string_types) else value) logger.debug(debugMsg) if value and key == "optimize": @@ -3586,8 +3587,8 @@ def intersect(containerA, containerB, lowerCase=False): containerB = arrayizeValue(containerB) if lowerCase: - containerA = [val.lower() if isinstance(val, basestring) else val for val in containerA] - containerB = [val.lower() if isinstance(val, basestring) else val for val in containerB] + containerA = [val.lower() if hasattr(val, "lower") else val for val in containerA] + containerB = [val.lower() if hasattr(val, "lower") else val for val in containerB] retVal = [val for val in containerA if val in containerB] @@ -3730,7 +3731,7 @@ def safeSQLIdentificatorNaming(name, isTable=False): retVal = name - if isinstance(name, basestring): + if isinstance(name, six.string_types): retVal = getUnicode(name) _ = isTable and Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) @@ -3769,7 +3770,7 @@ def unsafeSQLIdentificatorNaming(name): retVal = name - if isinstance(name, basestring): + if isinstance(name, six.string_types): if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ACCESS): retVal = name.replace("`", "") elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.SQLITE, DBMS.INFORMIX, DBMS.HSQLDB): @@ -3800,7 +3801,7 @@ def isNoneValue(value): False """ - if isinstance(value, basestring): + if isinstance(value, six.string_types): return value in ("None", "") elif isListLike(value): return all(isNoneValue(_) for _ in value) @@ -3819,7 +3820,7 @@ def isNullValue(value): False """ - return isinstance(value, basestring) and value.upper() == NULL + return hasattr(value, "upper") and value.upper() == NULL def expandMnemonics(mnemonics, parser, args): """ @@ -3921,7 +3922,7 @@ def safeCSValue(value): retVal = value - if retVal and isinstance(retVal, basestring): + if retVal and isinstance(retVal, six.string_types): if not (retVal[0] == retVal[-1] == '"'): if any(_ in retVal for _ in (conf.get("csvDel", defaults.csvDel), '"', '\n')): retVal = '"%s"' % retVal.replace('"', '""') @@ -4375,7 +4376,7 @@ def decodeHexValue(value, raw=False): def _(value): retVal = value - if value and isinstance(value, basestring): + if value and isinstance(value, six.string_types): if len(value) % 2 != 0: retVal = "%s?" % hexdecode(value[:-1]) if len(value) > 1 else value singleTimeWarnMessage("there was a problem decoding value '%s' from expected hexadecimal form" % value) @@ -4423,7 +4424,7 @@ def extractExpectedValue(value, expected): elif expected == EXPECTED.BOOL: if isinstance(value, int): value = bool(value) - elif isinstance(value, basestring): + elif isinstance(value, six.string_types): value = value.strip().lower() if value in ("true", "false"): value = value == "true" @@ -4436,7 +4437,7 @@ def extractExpectedValue(value, expected): else: value = None elif expected == EXPECTED.INT: - if isinstance(value, basestring): + if isinstance(value, six.string_types): value = int(value) if value.isdigit() else None return value @@ -4447,7 +4448,7 @@ def hashDBWrite(key, value, serialize=False): """ if conf.hashDB: - _ = '|'.join((str(_) if not isinstance(_, basestring) else _) for _ in (conf.hostname, conf.path.strip('/') if conf.path is not None else conf.port, key, HASHDB_MILESTONE_VALUE)) + _ = '|'.join((str(_) if not isinstance(_, six.string_types) else _) for _ in (conf.hostname, conf.path.strip('/') if conf.path is not None else conf.port, key, HASHDB_MILESTONE_VALUE)) conf.hashDB.write(_, value, serialize) def hashDBRetrieve(key, unserialize=False, checkConf=False): @@ -4458,10 +4459,10 @@ def hashDBRetrieve(key, unserialize=False, checkConf=False): retVal = None if conf.hashDB: - _ = '|'.join((str(_) if not isinstance(_, basestring) else _) for _ in (conf.hostname, conf.path.strip('/') if conf.path is not None else conf.port, key, HASHDB_MILESTONE_VALUE)) + _ = '|'.join((str(_) if not isinstance(_, six.string_types) else _) for _ in (conf.hostname, conf.path.strip('/') if conf.path is not None else conf.port, key, HASHDB_MILESTONE_VALUE)) retVal = conf.hashDB.retrieve(_, unserialize) if kb.resumeValues and not (checkConf and any((conf.flushSession, conf.freshQueries))) else None - if not kb.inferenceMode and not kb.fileReadMode and isinstance(retVal, basestring) and any(_ in retVal for _ in (PARTIAL_VALUE_MARKER, PARTIAL_HEX_VALUE_MARKER)): + if not kb.inferenceMode and not kb.fileReadMode and isinstance(retVal, six.string_types) and any(_ in retVal for _ in (PARTIAL_VALUE_MARKER, PARTIAL_HEX_VALUE_MARKER)): retVal = None return retVal @@ -4697,7 +4698,7 @@ def parseRequestFile(reqFile, checkParams=True): reqResList = re.finditer(BURP_REQUEST_REGEX, content, re.I | re.S) for match in reqResList: - request = match if isinstance(match, basestring) else match.group(1) + request = match if isinstance(match, six.string_types) else match.group(1) request = re.sub(r"\A[^\w]+", "", request) schemePort = re.search(r"(http[\w]*)\:\/\/.*?\:([\d]+).+?={10,}", request, re.I | re.S) @@ -4789,7 +4790,7 @@ def parseRequestFile(reqFile, checkParams=True): data = data.rstrip("\r\n") if data else data if getPostReq and (params or cookie or not checkParams): - if not port and isinstance(scheme, basestring) and scheme.lower() == "https": + if not port and hasattr(scheme, "lower") and scheme.lower() == "https": port = "443" elif not scheme and port == "443": scheme = "https" @@ -4836,9 +4837,9 @@ def getSafeExString(ex, encoding=None): retVal = ex.message elif getattr(ex, "msg", None): retVal = ex.msg - elif isinstance(ex, (list, tuple)) and len(ex) > 1 and isinstance(ex[1], basestring): + elif isinstance(ex, (list, tuple)) and len(ex) > 1 and isinstance(ex[1], six.string_types): retVal = ex[1] - elif isinstance(ex, (list, tuple)) and len(ex) > 0 and isinstance(ex[0], basestring): + elif isinstance(ex, (list, tuple)) and len(ex) > 0 and isinstance(ex[0], six.string_types): retVal = ex[0] if retVal is None: diff --git a/lib/core/convert.py b/lib/core/convert.py index 91abe7f9a..16c6d6b55 100644 --- a/lib/core/convert.py +++ b/lib/core/convert.py @@ -17,6 +17,7 @@ import sys from lib.core.settings import IS_WIN from lib.core.settings import UNICODE_ENCODING +from thirdparty import six def base64decode(value): """ @@ -145,7 +146,7 @@ def htmlunescape(value): """ retVal = value - if value and isinstance(value, basestring): + if value and isinstance(value, six.string_types): codes = (("<", '<'), (">", '>'), (""", '"'), (" ", ' '), ("&", '&'), ("'", "'")) retVal = reduce(lambda x, y: x.replace(y[0], y[1]), codes, retVal) try: diff --git a/lib/core/dump.py b/lib/core/dump.py index 71affa0ed..c43e10832 100644 --- a/lib/core/dump.py +++ b/lib/core/dump.py @@ -133,7 +133,7 @@ class Dump(object): if "\n" in _: self._write("%s:\n---\n%s\n---" % (header, _)) else: - self._write("%s: %s" % (header, ("'%s'" % _) if isinstance(data, basestring) else _)) + self._write("%s: %s" % (header, ("'%s'" % _) if isinstance(data, six.string_types) else _)) else: self._write("%s:\tNone" % header) @@ -142,7 +142,7 @@ class Dump(object): try: elements = set(elements) elements = list(elements) - elements.sort(key=lambda _: _.lower() if isinstance(_, basestring) else _) + elements.sort(key=lambda _: _.lower() if hasattr(_, "lower") else _) except: pass @@ -154,7 +154,7 @@ class Dump(object): self._write("%s [%d]:" % (header, len(elements))) for element in elements: - if isinstance(element, basestring): + if isinstance(element, six.string_types): self._write("[*] %s" % element) elif isListLike(element): self._write("[*] " + ", ".join(getUnicode(e) for e in element)) @@ -193,7 +193,7 @@ class Dump(object): userSettings = userSettings[0] users = userSettings.keys() - users.sort(key=lambda _: _.lower() if isinstance(_, basestring) else _) + users.sort(key=lambda _: _.lower() if hasattr(_, "lower") else _) if conf.api: self._write(userSettings, content_type=content_type) @@ -287,7 +287,7 @@ class Dump(object): colType = None colList = columns.keys() - colList.sort(key=lambda _: _.lower() if isinstance(_, basestring) else _) + colList.sort(key=lambda _: _.lower() if hasattr(_, "lower") else _) for column in colList: colType = columns[column] @@ -379,7 +379,7 @@ class Dump(object): if count is None: count = "Unknown" - tables.sort(key=lambda _: _.lower() if isinstance(_, basestring) else _) + tables.sort(key=lambda _: _.lower() if hasattr(_, "lower") else _) for table in tables: blank1 = " " * (maxlength1 - len(normalizeUnicode(table) or unicode(table))) diff --git a/lib/core/option.py b/lib/core/option.py index adb3291e0..72153e0c6 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -147,6 +147,7 @@ from lib.utils.crawler import crawl from lib.utils.deps import checkDependencies from lib.utils.search import search from lib.utils.purge import purge +from thirdparty import six from thirdparty.keepalive import keepalive from thirdparty.multipart import multipartpost from thirdparty.six.moves import http_client as _http_client @@ -658,7 +659,7 @@ def _setTechnique(): validTechniques = sorted(getPublicTypeMembers(PAYLOAD.TECHNIQUE), key=lambda x: x[1]) validLetters = [_[0][0].upper() for _ in validTechniques] - if conf.tech and isinstance(conf.tech, basestring): + if conf.tech and isinstance(conf.tech, six.string_types): _ = [] for letter in conf.tech.upper(): @@ -1737,7 +1738,7 @@ def _cleanupOptions(): if conf.csvDel: conf.csvDel = decodeStringEscape(conf.csvDel) - if conf.torPort and isinstance(conf.torPort, basestring) and conf.torPort.isdigit(): + if conf.torPort and hasattr(conf.torPort, "isdigit") and conf.torPort.isdigit(): conf.torPort = int(conf.torPort) if conf.torType: @@ -2576,7 +2577,7 @@ def _basicOptionValidation(): errMsg = "option '--crack' should be used as a standalone" raise SqlmapSyntaxException(errMsg) - if isinstance(conf.uCols, basestring): + if isinstance(conf.uCols, six.string_types): if not conf.uCols.isdigit() and ("-" not in conf.uCols or len(conf.uCols.split("-")) != 2): errMsg = "value for option '--union-cols' must be a range with hyphon " errMsg += "(e.g. 1-10) or integer value (e.g. 5)" diff --git a/lib/core/settings.py b/lib/core/settings.py index 00bc586ce..af1c89333 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.3.67" +VERSION = "1.3.3.68" 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/parse/payloads.py b/lib/parse/payloads.py index 46612d5b8..23368f2d4 100644 --- a/lib/parse/payloads.py +++ b/lib/parse/payloads.py @@ -24,8 +24,8 @@ def cleanupVals(text, tag): if tag in ("clause", "where"): text = text.split(',') - if isinstance(text, basestring): - text = int(text) if text.isdigit() else text + if hasattr(text, "isdigit") and text.isdigit(): + text = int(text) elif isinstance(text, list): count = 0 diff --git a/lib/request/basic.py b/lib/request/basic.py index 0345dff11..255c318af 100644 --- a/lib/request/basic.py +++ b/lib/request/basic.py @@ -257,12 +257,12 @@ def decodePage(page, contentEncoding, contentType): if not page or (conf.nullConnection and len(page) < 2): return getUnicode(page) - if isinstance(contentEncoding, basestring) and contentEncoding: + if hasattr(contentEncoding, "lower"): contentEncoding = contentEncoding.lower() else: contentEncoding = "" - if isinstance(contentType, basestring) and contentType: + if hasattr(contentType, "lower"): contentType = contentType.lower() else: contentType = "" diff --git a/lib/request/connect.py b/lib/request/connect.py index 483767ad2..aa8e89a98 100644 --- a/lib/request/connect.py +++ b/lib/request/connect.py @@ -118,6 +118,7 @@ from lib.request.basic import processResponse from lib.request.direct import direct from lib.request.comparison import comparison from lib.request.methodrequest import MethodRequest +from thirdparty import six from thirdparty.odict import OrderedDict from thirdparty.six.moves import http_client as _http_client from thirdparty.six.moves import urllib as _urllib @@ -432,7 +433,7 @@ class Connect(object): responseHeaders = _(ws.getheaders()) responseHeaders.headers = ["%s: %s\r\n" % (_[0].capitalize(), _[1]) for _ in responseHeaders.items()] - requestHeaders += "\r\n".join(["%s: %s" % (getUnicode(key.capitalize() if isinstance(key, basestring) else key), getUnicode(value)) for (key, value) in responseHeaders.items()]) + requestHeaders += "\r\n".join(["%s: %s" % (getUnicode(key.capitalize() if hasattr(key, "capitalize") else key), getUnicode(value)) for (key, value) in responseHeaders.items()]) requestMsg += "\r\n%s" % requestHeaders if post is not None: @@ -453,7 +454,7 @@ class Connect(object): else: return None, None, None - requestHeaders += "\r\n".join(["%s: %s" % (getUnicode(key.capitalize() if isinstance(key, basestring) else key), getUnicode(value)) for (key, value) in req.header_items()]) + requestHeaders += "\r\n".join(["%s: %s" % (getUnicode(key.capitalize() if hasattr(key, "capitalize") else key), getUnicode(value)) for (key, value) in req.header_items()]) if not getRequestHeader(req, HTTP_HEADER.COOKIE) and conf.cj: conf.cj._policy._now = conf.cj._now = int(time.time()) @@ -745,7 +746,7 @@ class Connect(object): raise SqlmapConnectionException(warnMsg) finally: - if isinstance(page, basestring) and not isinstance(page, unicode): + if isinstance(six.binary_type): if HTTP_HEADER.CONTENT_TYPE in (responseHeaders or {}) and not re.search(TEXT_CONTENT_TYPE_REGEX, responseHeaders[HTTP_HEADER.CONTENT_TYPE]): page = unicode(page, errors="ignore") else: @@ -858,7 +859,7 @@ class Connect(object): errMsg += "function '%s' ('%s')" % (function.func_name, getSafeExString(ex)) raise SqlmapGenericException(errMsg) - if not isinstance(payload, basestring): + if not isinstance(payload, six.string_types): errMsg = "tamper function '%s' returns " % function.func_name errMsg += "invalid payload type ('%s')" % type(payload) raise SqlmapValueException(errMsg) @@ -1156,7 +1157,7 @@ class Connect(object): for name, value in variables.items(): if name != "__builtins__" and originals.get(name, "") != value: - if isinstance(value, (basestring, int)): + if isinstance(value, (int, six.string_types)): found = False value = getUnicode(value, UNICODE_ENCODING) diff --git a/lib/request/inject.py b/lib/request/inject.py index 293fdf290..f08ffbefa 100644 --- a/lib/request/inject.py +++ b/lib/request/inject.py @@ -59,6 +59,7 @@ from lib.techniques.dns.test import dnsTest from lib.techniques.dns.use import dnsUse from lib.techniques.error.use import errorUse from lib.techniques.union.use import unionUse +from thirdparty import six def _goDns(payload, expression): value = None @@ -334,7 +335,7 @@ def _goUnion(expression, unpack=True, dump=False): output = unionUse(expression, unpack=unpack, dump=dump) - if isinstance(output, basestring): + if isinstance(output, six.string_types): output = parseUnionPage(output) return output diff --git a/lib/request/redirecthandler.py b/lib/request/redirecthandler.py index 798476892..0fd68d0bd 100644 --- a/lib/request/redirecthandler.py +++ b/lib/request/redirecthandler.py @@ -95,7 +95,7 @@ class SmartRedirectHandler(_urllib.request.HTTPRedirectHandler): redirectMsg += "[#%d] (%d %s):\r\n" % (threadData.lastRequestUID, code, getUnicode(msg)) if headers: - logHeaders = "\r\n".join("%s: %s" % (getUnicode(key.capitalize() if isinstance(key, basestring) else key), getUnicode(value)) for (key, value) in headers.items()) + logHeaders = "\r\n".join("%s: %s" % (getUnicode(key.capitalize() if hasattr(key, "capitalize") else key), getUnicode(value)) for (key, value) in headers.items()) else: logHeaders = "" diff --git a/lib/takeover/metasploit.py b/lib/takeover/metasploit.py index 7a50b1c6d..d8f40d7be 100644 --- a/lib/takeover/metasploit.py +++ b/lib/takeover/metasploit.py @@ -45,6 +45,7 @@ from lib.core.subprocessng import blockingWriteToFD from lib.core.subprocessng import Popen as execute from lib.core.subprocessng import send_all from lib.core.subprocessng import recv_some +from thirdparty import six if IS_WIN: import msvcrt @@ -186,7 +187,7 @@ class Metasploit: # choose which encoder to use. When called from --os-pwn the encoder # is always x86/alpha_mixed - used for sys_bineval() and # shellcodeexec - if isinstance(encode, basestring): + if isinstance(encode, six.string_types): return encode elif encode: diff --git a/lib/takeover/udf.py b/lib/takeover/udf.py index afb05c37f..7c744f3b2 100644 --- a/lib/takeover/udf.py +++ b/lib/takeover/udf.py @@ -300,7 +300,7 @@ class UDF: while True: retType = readInput(msg, default=defaultType) - if isinstance(retType, basestring) and retType.isdigit(): + if hasattr(retType, "isdigit") and retType.isdigit(): logger.warn("you need to specify the data-type of the return value") else: self.udfs[udfName]["return"] = retType @@ -338,7 +338,7 @@ class UDF: if choice == 'Q': break - elif isinstance(choice, basestring) and choice.isdigit() and int(choice) > 0 and int(choice) <= len(udfList): + elif hasattr(choice, "isdigit") and choice.isdigit() and int(choice) > 0 and int(choice) <= len(udfList): choice = int(choice) break elif isinstance(choice, int) and choice > 0 and choice <= len(udfList): diff --git a/lib/techniques/blind/inference.py b/lib/techniques/blind/inference.py index 741abf453..8355b5af1 100644 --- a/lib/techniques/blind/inference.py +++ b/lib/techniques/blind/inference.py @@ -117,20 +117,20 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None firstChar = len(partialValue) elif re.search(r"(?i)\b(LENGTH|LEN)\(", expression): firstChar = 0 - elif (kb.fileReadMode or dump) and conf.firstChar is not None and (isinstance(conf.firstChar, int) or (isinstance(conf.firstChar, basestring) and conf.firstChar.isdigit())): + elif (kb.fileReadMode or dump) and conf.firstChar is not None and (isinstance(conf.firstChar, int) or (hasattr(conf.firstChar, "isdigit") and conf.firstChar.isdigit())): firstChar = int(conf.firstChar) - 1 if kb.fileReadMode: firstChar <<= 1 - elif isinstance(firstChar, basestring) and firstChar.isdigit() or isinstance(firstChar, int): + elif hasattr(firstChar, "isdigit") and firstChar.isdigit() or isinstance(firstChar, int): firstChar = int(firstChar) - 1 else: firstChar = 0 if re.search(r"(?i)\b(LENGTH|LEN)\(", expression): lastChar = 0 - elif dump and conf.lastChar is not None and (isinstance(conf.lastChar, int) or (isinstance(conf.lastChar, basestring) and conf.lastChar.isdigit())): + elif dump and conf.lastChar is not None and (isinstance(conf.lastChar, int) or (hasattr(conf.lastChar, "isdigit") and conf.lastChar.isdigit())): lastChar = int(conf.lastChar) - elif isinstance(lastChar, basestring) and lastChar.isdigit() or isinstance(lastChar, int): + elif hasattr(lastChar, "isdigit") and lastChar.isdigit() or isinstance(lastChar, int): lastChar = int(lastChar) else: lastChar = 0 @@ -143,7 +143,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None else: expressionUnescaped = unescaper.escape(expression) - if isinstance(length, basestring) and length.isdigit() or isinstance(length, int): + if hasattr(length, "isdigit") and length.isdigit() or isinstance(length, int): length = int(length) else: length = None diff --git a/lib/techniques/error/use.py b/lib/techniques/error/use.py index 62b38c713..b68274f12 100644 --- a/lib/techniques/error/use.py +++ b/lib/techniques/error/use.py @@ -57,6 +57,7 @@ from lib.core.threads import runThreads from lib.core.unescaper import unescaper from lib.request.connect import Connect as Request from lib.utils.progress import ProgressBar +from thirdparty import six def _oneShotErrorUse(expression, field=None, chunkTest=False): offset = 1 @@ -201,7 +202,7 @@ def _oneShotErrorUse(expression, field=None, chunkTest=False): retVal = decodeHexValue(retVal) if conf.hexConvert else retVal - if isinstance(retVal, basestring): + if isinstance(retVal, six.string_types): retVal = htmlunescape(retVal).replace("
", "\n") retVal = _errorReplaceChars(retVal) @@ -277,7 +278,7 @@ def _formatPartialContent(value): Prepares (possibly hex-encoded) partial content for safe console output """ - if value and isinstance(value, basestring): + if value and isinstance(value, six.string_types): try: value = hexdecode(value) except: @@ -447,7 +448,7 @@ def errorUse(expression, dump=False): value = _errorFields(expression, expressionFields, expressionFieldsList) if value and isListLike(value): - if len(value) == 1 and isinstance(value[0], basestring): + if len(value) == 1 and isinstance(value[0], six.string_types): value = unArrayizeValue(value) elif len(value) > 1 and stopLimit == 1: value = [value] diff --git a/lib/techniques/union/use.py b/lib/techniques/union/use.py index 234e3eeab..0611359d6 100644 --- a/lib/techniques/union/use.py +++ b/lib/techniques/union/use.py @@ -59,6 +59,7 @@ from lib.core.threads import runThreads from lib.core.unescaper import unescaper from lib.request.connect import Connect as Request from lib.utils.progress import ProgressBar +from thirdparty import six from thirdparty.odict import OrderedDict def _oneShotUnionUse(expression, unpack=True, limited=False): @@ -163,7 +164,7 @@ def _oneShotUnionUse(expression, unpack=True, limited=False): def configUnion(char=None, columns=None): def _configUnionChar(char): - if not isinstance(char, basestring): + if not isinstance(char, six.string_types): return kb.uChar = char @@ -172,7 +173,7 @@ def configUnion(char=None, columns=None): kb.uChar = char.replace("[CHAR]", conf.uChar if conf.uChar.isdigit() else "'%s'" % conf.uChar.strip("'")) def _configUnionCols(columns): - if not isinstance(columns, basestring): + if not isinstance(columns, six.string_types): return columns = columns.replace(" ", "") @@ -261,7 +262,7 @@ def unionUse(expression, unpack=True, dump=False): infoMsg += "%d %s" % (stopLimit, "entries" if stopLimit > 1 else "entry") logger.info(infoMsg) - elif count and (not isinstance(count, basestring) or not count.isdigit()): + elif count and (not isinstance(count, six.string_types) or not count.isdigit()): warnMsg = "it was not possible to count the number " warnMsg += "of entries for the SQL query provided. " warnMsg += "sqlmap will assume that it returns only " @@ -373,7 +374,7 @@ def unionUse(expression, unpack=True, dump=False): del threadData.shared.buffered[0] if conf.verbose == 1 and not (threadData.resumed and kb.suppressResumeInfo) and not threadData.shared.showEta: - _ = ','.join("'%s'" % _ for _ in (flattenValue(arrayizeValue(items)) if not isinstance(items, basestring) else [items])) + _ = ','.join("'%s'" % _ for _ in (flattenValue(arrayizeValue(items)) if not isinstance(items, six.string_types) else [items])) status = "[%s] [INFO] %s: %s" % (time.strftime("%X"), "resumed" if threadData.resumed else "retrieved", _ if kb.safeCharEncode else safecharencode(_)) if len(status) > width: diff --git a/lib/utils/hash.py b/lib/utils/hash.py index 968ca6772..ca876edf6 100644 --- a/lib/utils/hash.py +++ b/lib/utils/hash.py @@ -86,6 +86,7 @@ from lib.core.settings import NULL from lib.core.settings import UNICODE_ENCODING from lib.core.settings import ROTATING_CHARS from lib.core.wordlist import Wordlist +from thirdparty import six from thirdparty.colorama.initialise import init as coloramainit from thirdparty.pydes.pyDes import des from thirdparty.pydes.pyDes import CBC @@ -695,7 +696,7 @@ def hashRecognition(value): isOracle, isMySQL = Backend.isDbms(DBMS.ORACLE), Backend.isDbms(DBMS.MYSQL) - if isinstance(value, basestring): + 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: @@ -726,7 +727,7 @@ def _bruteProcessVariantA(attack_info, hash_regex, suffix, retVal, proc_id, proc count += 1 - if not isinstance(word, basestring): + if not isinstance(word, six.string_types): continue if suffix: @@ -801,7 +802,7 @@ def _bruteProcessVariantB(user, hash_, kwargs, hash_regex, suffix, retVal, found count += 1 - if not isinstance(word, basestring): + if not isinstance(word, six.string_types): continue if suffix: diff --git a/lib/utils/pivotdumptable.py b/lib/utils/pivotdumptable.py index 07cf5b8ee..ef5947936 100644 --- a/lib/utils/pivotdumptable.py +++ b/lib/utils/pivotdumptable.py @@ -46,7 +46,7 @@ def pivotDumpTable(table, colList, count=None, blind=True, alias=None): query = agent.whereQuery(query) count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) if blind else inject.getValue(query, blind=False, time=False, expected=EXPECTED.INT) - if isinstance(count, basestring) and count.isdigit(): + if hasattr(count, "isdigit") and count.isdigit(): count = int(count) if count == 0: diff --git a/plugins/dbms/maxdb/enumeration.py b/plugins/dbms/maxdb/enumeration.py index cd0980370..dfb8a4349 100644 --- a/plugins/dbms/maxdb/enumeration.py +++ b/plugins/dbms/maxdb/enumeration.py @@ -21,6 +21,7 @@ from lib.core.settings import CURRENT_DB from lib.utils.brute import columnExists from lib.utils.pivotdumptable import pivotDumpTable from plugins.generic.enumeration import Enumeration as GenericEnumeration +from thirdparty import six class Enumeration(GenericEnumeration): def __init__(self): @@ -71,7 +72,7 @@ class Enumeration(GenericEnumeration): dbs[dbs.index(db)] = safeSQLIdentificatorNaming(db) infoMsg = "fetching tables for database" - infoMsg += "%s: %s" % ("s" if len(dbs) > 1 else "", ", ".join(db if isinstance(db, basestring) else db[0] for db in sorted(dbs))) + infoMsg += "%s: %s" % ("s" if len(dbs) > 1 else "", ", ".join(db if isinstance(db, six.string_types) else db[0] for db in sorted(dbs))) logger.info(infoMsg) rootQuery = queries[DBMS.MAXDB].tables diff --git a/plugins/dbms/mssqlserver/enumeration.py b/plugins/dbms/mssqlserver/enumeration.py index 56d952879..c949c10b3 100644 --- a/plugins/dbms/mssqlserver/enumeration.py +++ b/plugins/dbms/mssqlserver/enumeration.py @@ -28,8 +28,8 @@ from lib.core.enums import PAYLOAD from lib.core.exception import SqlmapNoneDataException from lib.core.settings import CURRENT_DB from lib.request import inject - from plugins.generic.enumeration import Enumeration as GenericEnumeration +from thirdparty import six class Enumeration(GenericEnumeration): def getPrivileges(self, *args): @@ -83,7 +83,7 @@ class Enumeration(GenericEnumeration): dbs = [_ for _ in dbs if _] infoMsg = "fetching tables for database" - infoMsg += "%s: %s" % ("s" if len(dbs) > 1 else "", ", ".join(db if isinstance(db, basestring) else db[0] for db in sorted(dbs))) + infoMsg += "%s: %s" % ("s" if len(dbs) > 1 else "", ", ".join(db if isinstance(db, six.string_types) else db[0] for db in sorted(dbs))) logger.info(infoMsg) rootQuery = queries[DBMS.MSSQL].tables @@ -219,7 +219,7 @@ class Enumeration(GenericEnumeration): values = inject.getValue(query, blind=False, time=False) if not isNoneValue(values): - if isinstance(values, basestring): + if isinstance(values, six.string_types): values = [values] for foundTbl in values: @@ -353,7 +353,7 @@ class Enumeration(GenericEnumeration): values = inject.getValue(query, blind=False, time=False) if not isNoneValue(values): - if isinstance(values, basestring): + if isinstance(values, six.string_types): values = [values] for foundTbl in values: diff --git a/plugins/dbms/sybase/enumeration.py b/plugins/dbms/sybase/enumeration.py index 2658bccd0..002991a72 100644 --- a/plugins/dbms/sybase/enumeration.py +++ b/plugins/dbms/sybase/enumeration.py @@ -26,6 +26,7 @@ from lib.core.settings import CURRENT_DB from lib.utils.brute import columnExists from lib.utils.pivotdumptable import pivotDumpTable from plugins.generic.enumeration import Enumeration as GenericEnumeration +from thirdparty import six class Enumeration(GenericEnumeration): def getUsers(self): @@ -128,7 +129,7 @@ class Enumeration(GenericEnumeration): dbs = [_ for _ in dbs if _] infoMsg = "fetching tables for database" - infoMsg += "%s: %s" % ("s" if len(dbs) > 1 else "", ", ".join(db if isinstance(db, basestring) else db[0] for db in sorted(dbs))) + infoMsg += "%s: %s" % ("s" if len(dbs) > 1 else "", ", ".join(db if isinstance(db, six.string_types) else db[0] for db in sorted(dbs))) logger.info(infoMsg) if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: @@ -279,7 +280,7 @@ class Enumeration(GenericEnumeration): columns = {} for name, type_ in filterPairValues(zip(retVal[0]["%s.name" % kb.aliasName], retVal[0]["%s.usertype" % kb.aliasName])): - columns[name] = SYBASE_TYPES.get(int(type_) if isinstance(type_, basestring) and type_.isdigit() else type_, type_) + columns[name] = SYBASE_TYPES.get(int(type_) if hasattr(type_, "isdigit") and type_.isdigit() else type_, type_) table[safeSQLIdentificatorNaming(tbl, True)] = columns kb.data.cachedColumns[safeSQLIdentificatorNaming(conf.db)] = table diff --git a/plugins/generic/databases.py b/plugins/generic/databases.py index 5412f1b0b..ac855c3c5 100644 --- a/plugins/generic/databases.py +++ b/plugins/generic/databases.py @@ -605,7 +605,7 @@ class Databases: if values is None: values = inject.getValue(query, blind=False, time=False) - if values and isinstance(values[0], basestring): + if values and isinstance(values[0], six.string_types): values = [values] if Backend.isDbms(DBMS.MSSQL) and isNoneValue(values): @@ -658,7 +658,7 @@ class Databases: if len(columnData) == 1: columns[name] = None else: - key = int(columnData[1]) if isinstance(columnData[1], basestring) and columnData[1].isdigit() else columnData[1] + key = int(columnData[1]) if isinstance(columnData[1], six.string_types) and columnData[1].isdigit() else columnData[1] if Backend.isDbms(DBMS.FIREBIRD): columnData[1] = FIREBIRD_TYPES.get(key, columnData[1]) elif Backend.isDbms(DBMS.INFORMIX): @@ -829,7 +829,7 @@ class Databases: colType = unArrayizeValue(inject.getValue(query, union=False, error=False)) - key = int(colType) if isinstance(colType, basestring) and colType.isdigit() else colType + key = int(colType) if hasattr(colType, "isdigit") and colType.isdigit() else colType if Backend.isDbms(DBMS.FIREBIRD): colType = FIREBIRD_TYPES.get(key, colType) elif Backend.isDbms(DBMS.INFORMIX): diff --git a/plugins/generic/entries.py b/plugins/generic/entries.py index 4094fa47e..632ad349b 100644 --- a/plugins/generic/entries.py +++ b/plugins/generic/entries.py @@ -45,6 +45,7 @@ from lib.core.settings import NULL from lib.request import inject from lib.utils.hash import attackDumpedTable from lib.utils.pivotdumptable import pivotDumpTable +from thirdparty import six class Entries: """ @@ -244,7 +245,7 @@ class Entries: logger.warn(warnMsg) if not isNoneValue(entries): - if isinstance(entries, basestring): + if isinstance(entries, six.string_types): entries = [entries] elif not isListLike(entries): entries = [] @@ -259,7 +260,7 @@ class Entries: if entry is None or len(entry) == 0: continue - if isinstance(entry, basestring): + if isinstance(entry, six.string_types): colEntry = entry else: colEntry = unArrayizeValue(entry[index]) if index < len(entry) else u'' diff --git a/plugins/generic/search.py b/plugins/generic/search.py index ffd231ebd..088019786 100644 --- a/plugins/generic/search.py +++ b/plugins/generic/search.py @@ -35,6 +35,7 @@ from lib.core.settings import METADB_SUFFIX from lib.request import inject from lib.utils.brute import columnExists from lib.utils.brute import tableExists +from thirdparty import six class Search: """ @@ -204,7 +205,7 @@ class Search: if values and Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD): newValues = [] - if isinstance(values, basestring): + if isinstance(values, six.string_types): values = [values] for value in values: dbName = "SQLite" if Backend.isDbms(DBMS.SQLITE) else "Firebird" diff --git a/thirdparty/clientform/clientform.py b/thirdparty/clientform/clientform.py index 2f5c18c83..46b6f18f2 100644 --- a/thirdparty/clientform/clientform.py +++ b/thirdparty/clientform/clientform.py @@ -95,11 +95,11 @@ else: try: from thirdparty.six.moves import cStringIO as _cStringIO - from thirdparty.six.moves import http_client as _html_entities + from thirdparty.six.moves import html_entities as _html_entities from thirdparty.six.moves import urllib as _urllib except ImportError: from six.moves import cStringIO as _cStringIO - from six.moves import urllib as _html_entities + from six.moves import html_entities as _html_entities from six.moves import urllib as _urllib try: