From 7ff77ef05231cb35b406f9e51c8b6cdf249722df Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Tue, 25 Feb 2020 12:36:07 +0100 Subject: [PATCH] Adding support for InterSystems Cache (and IRIS) --- data/xml/queries.xml | 60 +++++++++++++ lib/controller/handler.py | 4 + lib/core/agent.py | 11 ++- lib/core/common.py | 4 +- lib/core/dicts.py | 5 +- lib/core/dump.py | 2 +- lib/core/enums.py | 4 + lib/core/settings.py | 14 ++- lib/request/basic.py | 3 +- lib/utils/deps.py | 2 +- plugins/dbms/cache/__init__.py | 30 +++++++ plugins/dbms/cache/connector.py | 77 +++++++++++++++++ plugins/dbms/cache/enumeration.py | 48 +++++++++++ plugins/dbms/cache/filesystem.py | 11 +++ plugins/dbms/cache/fingerprint.py | 113 +++++++++++++++++++++++++ plugins/dbms/cache/syntax.py | 23 +++++ plugins/dbms/cache/takeover.py | 28 ++++++ plugins/dbms/h2/fingerprint.py | 3 + plugins/dbms/hsqldb/connector.py | 2 +- plugins/dbms/postgresql/fingerprint.py | 2 + plugins/generic/databases.py | 35 ++++---- plugins/generic/entries.py | 7 +- plugins/generic/users.py | 7 +- 23 files changed, 459 insertions(+), 36 deletions(-) create mode 100644 plugins/dbms/cache/__init__.py create mode 100644 plugins/dbms/cache/connector.py create mode 100644 plugins/dbms/cache/enumeration.py create mode 100644 plugins/dbms/cache/filesystem.py create mode 100644 plugins/dbms/cache/fingerprint.py create mode 100644 plugins/dbms/cache/syntax.py create mode 100644 plugins/dbms/cache/takeover.py diff --git a/data/xml/queries.xml b/data/xml/queries.xml index ff324ba83..97b6fb3fa 100644 --- a/data/xml/queries.xml +++ b/data/xml/queries.xml @@ -1457,4 +1457,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/controller/handler.py b/lib/controller/handler.py index 97f87c407..0cf250f92 100644 --- a/lib/controller/handler.py +++ b/lib/controller/handler.py @@ -13,6 +13,7 @@ from lib.core.enums import DBMS from lib.core.exception import SqlmapConnectionException from lib.core.settings import ACCESS_ALIASES from lib.core.settings import ALTIBASE_ALIASES +from lib.core.settings import CACHE_ALIASES from lib.core.settings import CRATEDB_ALIASES from lib.core.settings import CUBRID_ALIASES from lib.core.settings import DB2_ALIASES @@ -39,6 +40,8 @@ from plugins.dbms.access.connector import Connector as AccessConn from plugins.dbms.access import AccessMap from plugins.dbms.altibase.connector import Connector as AltibaseConn from plugins.dbms.altibase import AltibaseMap +from plugins.dbms.cache.connector import Connector as CacheConn +from plugins.dbms.cache import CacheMap from plugins.dbms.cratedb.connector import Connector as CrateDBConn from plugins.dbms.cratedb import CrateDBMap from plugins.dbms.cubrid.connector import Connector as CubridConn @@ -109,6 +112,7 @@ def setHandler(): (DBMS.MIMERSQL, MIMERSQL_ALIASES, MimerSQLMap, MimerSQLConn), (DBMS.CRATEDB, CRATEDB_ALIASES, CrateDBMap, CrateDBConn), (DBMS.CUBRID, CUBRID_ALIASES, CubridMap, CubridConn), + (DBMS.CACHE, CACHE_ALIASES, CacheMap, CacheConn), ] _ = max(_ if (conf.get("dbms") or Backend.getIdentifiedDbms() or kb.heuristicExtendedDbms or "").lower() in _[1] else () for _ in items) diff --git a/lib/core/agent.py b/lib/core/agent.py index 51f79017e..c1c3d19f0 100644 --- a/lib/core/agent.py +++ b/lib/core/agent.py @@ -660,7 +660,7 @@ class Agent(object): elif fieldsNoSelect: concatenatedQuery = "CONCAT('%s',%s,'%s')" % (kb.chars.start, concatenatedQuery, kb.chars.stop) - elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE, DBMS.DB2, DBMS.FIREBIRD, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.DERBY, DBMS.VERTICA, DBMS.MCKOI, DBMS.PRESTO, DBMS.ALTIBASE, DBMS.MIMERSQL, DBMS.CRATEDB, DBMS.CUBRID): + elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE, DBMS.DB2, DBMS.FIREBIRD, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.DERBY, DBMS.VERTICA, DBMS.MCKOI, DBMS.PRESTO, DBMS.ALTIBASE, DBMS.MIMERSQL, DBMS.CRATEDB, DBMS.CUBRID, DBMS.CACHE): if fieldsExists: concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1) concatenatedQuery += "||'%s'" % kb.chars.stop @@ -1011,6 +1011,15 @@ class Agent(object): if match: orderBy = " ORDER BY %s" % match.group(1) + elif Backend.isDbms(DBMS.CACHE): + match = re.search(r"ORDER BY ([^ ]+)\Z", limitedQuery) + if match: + limitedQuery = re.sub(r"\s*%s\s*" % re.escape(match.group(0)), " ", limitedQuery).strip() + orderBy = " %s" % match.group(0) + field = match.group(1) + + limitedQuery = queries[Backend.getIdentifiedDbms()].limit.query % (1, field, limitedQuery, num) + elif Backend.isDbms(DBMS.FIREBIRD): limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (num + 1, num + 1) limitedQuery += " %s" % limitStr diff --git a/lib/core/common.py b/lib/core/common.py index ca9b9f51b..7956a1309 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -4091,7 +4091,7 @@ def safeSQLIdentificatorNaming(name, isTable=False): if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ACCESS, DBMS.CUBRID, DBMS.SQLITE): # Note: in SQLite double-quotes are treated as string if column/identifier is non-existent (e.g. SELECT "foobar" FROM users) retVal = "`%s`" % retVal - elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.INFORMIX, DBMS.MONETDB, DBMS.VERTICA, DBMS.MCKOI, DBMS.PRESTO, DBMS.CRATEDB): + elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.INFORMIX, DBMS.MONETDB, DBMS.VERTICA, DBMS.MCKOI, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CACHE): retVal = "\"%s\"" % retVal elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.ALTIBASE, DBMS.MIMERSQL): retVal = "\"%s\"" % retVal.upper() @@ -4129,7 +4129,7 @@ def unsafeSQLIdentificatorNaming(name): if isinstance(name, six.string_types): if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ACCESS, DBMS.CUBRID, DBMS.SQLITE): retVal = name.replace("`", "") - elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.INFORMIX, DBMS.MONETDB, DBMS.VERTICA, DBMS.MCKOI, DBMS.PRESTO, DBMS.CRATEDB): + elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.INFORMIX, DBMS.MONETDB, DBMS.VERTICA, DBMS.MCKOI, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CACHE): retVal = name.replace("\"", "") elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.ALTIBASE, DBMS.MIMERSQL): retVal = name.replace("\"", "").upper() diff --git a/lib/core/dicts.py b/lib/core/dicts.py index 57c6b9bca..27e58c527 100644 --- a/lib/core/dicts.py +++ b/lib/core/dicts.py @@ -12,6 +12,7 @@ from lib.core.enums import POST_HINT from lib.core.settings import ACCESS_ALIASES from lib.core.settings import ALTIBASE_ALIASES from lib.core.settings import BLANK +from lib.core.settings import CACHE_ALIASES from lib.core.settings import CRATEDB_ALIASES from lib.core.settings import CUBRID_ALIASES from lib.core.settings import DB2_ALIASES @@ -123,9 +124,7 @@ ALTIBASE_TYPES = { -8: "NCHAR", -9: "NVARCHAR", 2: "NUMERIC", - 2: "DECIMAL", 6: "FLOAT", - 6: "NUMBER", 8: "DOUBLE", 7: "REAL", -5: "BIGINT", @@ -240,6 +239,7 @@ DBMS_DICT = { DBMS.MIMERSQL: (MIMERSQL_ALIASES, "mimerpy", "https://github.com/mimersql/MimerPy", None), DBMS.CRATEDB: (CRATEDB_ALIASES, "python-psycopg2", "http://initd.org/psycopg/", "postgresql"), DBMS.CUBRID: (CUBRID_ALIASES, "CUBRID-Python", "https://github.com/CUBRID/cubrid-python", None), + DBMS.CACHE: (CACHE_ALIASES, "python jaydebeapi & python-jpype", "https://pypi.python.org/pypi/JayDeBeApi/ & http://jpype.sourceforge.net/", None), } # Reference: https://blog.jooq.org/tag/sysibm-sysdummy1/ @@ -273,6 +273,7 @@ HEURISTIC_NULL_EVAL = { DBMS.MIMERSQL: "ASCII_CHAR(256)", DBMS.CRATEDB: "MD5(NULL~NULL)", # Note: NULL~NULL also being evaluated on H2 and Ignite DBMS.CUBRID: "(NULL SETEQ NULL)", + DBMS.CACHE: "%SQLUPPER NULL", } SQL_STATEMENTS = { diff --git a/lib/core/dump.py b/lib/core/dump.py index 4a6680be5..ebc36a384 100644 --- a/lib/core/dump.py +++ b/lib/core/dump.py @@ -164,7 +164,7 @@ class Dump(object): self.string("current user", data, content_type=CONTENT_TYPE.CURRENT_USER) def currentDb(self, data): - if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.VERTICA, DBMS.CRATEDB): + if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.VERTICA, DBMS.CRATEDB, DBMS.CACHE): self.string("current database (equivalent to schema on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB) elif Backend.getIdentifiedDbms() in (DBMS.ALTIBASE, DBMS.DB2, DBMS.MIMERSQL, DBMS.MAXDB): self.string("current database (equivalent to owner on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB) diff --git a/lib/core/enums.py b/lib/core/enums.py index 45e96c263..f110b6033 100644 --- a/lib/core/enums.py +++ b/lib/core/enums.py @@ -54,6 +54,7 @@ class DBMS(object): MIMERSQL = "MimerSQL" CRATEDB = "CrateDB" CUBRID = "Cubrid" + CACHE = "InterSystems Cache" class DBMS_DIRECTORY_NAME(object): ACCESS = "access" @@ -78,6 +79,7 @@ class DBMS_DIRECTORY_NAME(object): MIMERSQL = "mimersql" CRATEDB = "cratedb" CUBRID = "cubrid" + CACHE = "cache" class FORK(object): MARIADB = "MariaDB" @@ -91,6 +93,8 @@ class FORK(object): IGNITE = "Apache Ignite" AURORA = "Aurora" ENTERPRISEDB = "EnterpriseDB" + YELLOWBRICK = "Yellowbrick" + IRIS = "Iris" class CUSTOM_LOGGING(object): PAYLOAD = 9 diff --git a/lib/core/settings.py b/lib/core/settings.py index e2ffc51cb..97c6721d6 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.2.38" +VERSION = "1.4.2.39" 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) @@ -268,11 +268,12 @@ ALTIBASE_SYSTEM_DBS = ("SYSTEM_",) MIMERSQL_SYSTEM_DBS = ("information_schema", "SYSTEM",) CRATEDB_SYSTEM_DBS = ("information_schema", "pg_catalog", "sys") CUBRID_SYSTEM_DBS = ("DBA",) +CACHE_SYSTEM_DBS = ("%Dictionary", "INFORMATION_SCHEMA", "%SYS") # Note: () + () MSSQL_ALIASES = ("microsoft sql server", "mssqlserver", "mssql", "ms") MYSQL_ALIASES = ("mysql", "my") + ("mariadb", "maria", "memsql", "tidb", "percona") -PGSQL_ALIASES = ("postgresql", "postgres", "pgsql", "psql", "pg") + ("cockroach", "cockroachdb") +PGSQL_ALIASES = ("postgresql", "postgres", "pgsql", "psql", "pg") + ("cockroach", "cockroachdb", "redshift", "greenplum", "yellowbrick", "enterprisedb", "aurora") ORACLE_ALIASES = ("oracle", "orcl", "ora", "or") SQLITE_ALIASES = ("sqlite", "sqlite3") ACCESS_ALIASES = ("msaccess", "access", "jet", "microsoft access") @@ -292,13 +293,14 @@ ALTIBASE_ALIASES = ("altibase",) MIMERSQL_ALIASES = ("mimersql", "mimer") CRATEDB_ALIASES = ("cratedb", "crate") CUBRID_ALIASES = ("cubrid",) +CACHE_ALIASES = ("cachedb", "cache") DBMS_DIRECTORY_DICT = dict((getattr(DBMS, _), getattr(DBMS_DIRECTORY_NAME, _)) for _ in dir(DBMS) if not _.startswith("_")) -SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES + SQLITE_ALIASES + ACCESS_ALIASES + FIREBIRD_ALIASES + MAXDB_ALIASES + SYBASE_ALIASES + DB2_ALIASES + HSQLDB_ALIASES + H2_ALIASES + INFORMIX_ALIASES + MONETDB_ALIASES + DERBY_ALIASES + VERTICA_ALIASES + MCKOI_ALIASES + PRESTO_ALIASES + ALTIBASE_ALIASES + MIMERSQL_ALIASES + CRATEDB_ALIASES + CUBRID_ALIASES +SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES + SQLITE_ALIASES + ACCESS_ALIASES + FIREBIRD_ALIASES + MAXDB_ALIASES + SYBASE_ALIASES + DB2_ALIASES + HSQLDB_ALIASES + H2_ALIASES + INFORMIX_ALIASES + MONETDB_ALIASES + DERBY_ALIASES + VERTICA_ALIASES + MCKOI_ALIASES + PRESTO_ALIASES + ALTIBASE_ALIASES + MIMERSQL_ALIASES + CRATEDB_ALIASES + CUBRID_ALIASES + CACHE_ALIASES SUPPORTED_OS = ("linux", "windows") -DBMS_ALIASES = ((DBMS.MSSQL, MSSQL_ALIASES), (DBMS.MYSQL, MYSQL_ALIASES), (DBMS.PGSQL, PGSQL_ALIASES), (DBMS.ORACLE, ORACLE_ALIASES), (DBMS.SQLITE, SQLITE_ALIASES), (DBMS.ACCESS, ACCESS_ALIASES), (DBMS.FIREBIRD, FIREBIRD_ALIASES), (DBMS.MAXDB, MAXDB_ALIASES), (DBMS.SYBASE, SYBASE_ALIASES), (DBMS.DB2, DB2_ALIASES), (DBMS.HSQLDB, HSQLDB_ALIASES), (DBMS.H2, H2_ALIASES), (DBMS.INFORMIX, INFORMIX_ALIASES), (DBMS.MONETDB, MONETDB_ALIASES), (DBMS.DERBY, DERBY_ALIASES), (DBMS.VERTICA, VERTICA_ALIASES), (DBMS.MCKOI, MCKOI_ALIASES), (DBMS.PRESTO, PRESTO_ALIASES), (DBMS.ALTIBASE, ALTIBASE_ALIASES), (DBMS.MIMERSQL, MIMERSQL_ALIASES), (DBMS.CRATEDB, CRATEDB_ALIASES), (DBMS.CUBRID, CUBRID_ALIASES)) +DBMS_ALIASES = ((DBMS.MSSQL, MSSQL_ALIASES), (DBMS.MYSQL, MYSQL_ALIASES), (DBMS.PGSQL, PGSQL_ALIASES), (DBMS.ORACLE, ORACLE_ALIASES), (DBMS.SQLITE, SQLITE_ALIASES), (DBMS.ACCESS, ACCESS_ALIASES), (DBMS.FIREBIRD, FIREBIRD_ALIASES), (DBMS.MAXDB, MAXDB_ALIASES), (DBMS.SYBASE, SYBASE_ALIASES), (DBMS.DB2, DB2_ALIASES), (DBMS.HSQLDB, HSQLDB_ALIASES), (DBMS.H2, H2_ALIASES), (DBMS.INFORMIX, INFORMIX_ALIASES), (DBMS.MONETDB, MONETDB_ALIASES), (DBMS.DERBY, DERBY_ALIASES), (DBMS.VERTICA, VERTICA_ALIASES), (DBMS.MCKOI, MCKOI_ALIASES), (DBMS.PRESTO, PRESTO_ALIASES), (DBMS.ALTIBASE, ALTIBASE_ALIASES), (DBMS.MIMERSQL, MIMERSQL_ALIASES), (DBMS.CRATEDB, CRATEDB_ALIASES), (DBMS.CUBRID, CUBRID_ALIASES), (DBMS.CACHE, CACHE_ALIASES)) USER_AGENT_ALIASES = ("ua", "useragent", "user-agent") REFERER_ALIASES = ("ref", "referer", "referrer") @@ -311,6 +313,10 @@ UPPER_CASE_DBMSES = set((DBMS.ORACLE, DBMS.DB2, DBMS.FIREBIRD, DBMS.HSQLDB, DBMS H2_DEFAULT_SCHEMA = HSQLDB_DEFAULT_SCHEMA = "PUBLIC" VERTICA_DEFAULT_SCHEMA = "public" MCKOI_DEFAULT_SCHEMA = "APP" +CACHE_DEFAULT_SCHEMA = "SQLUser" + +# DBMSes where OFFSET mechanism starts from 1 +PLUS_ONE_DBMSES = set((DBMS.ORACLE, DBMS.DB2, DBMS.ALTIBASE, DBMS.MSSQL, DBMS.CACHE)) # Names that can't be used to name files on Windows OS WINDOWS_RESERVED_NAMES = ("CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9") diff --git a/lib/request/basic.py b/lib/request/basic.py index 09d94d2be..1ebf9adf5 100644 --- a/lib/request/basic.py +++ b/lib/request/basic.py @@ -343,7 +343,8 @@ def decodePage(page, contentEncoding, contentType, percentDecode=True): # e.g. %20%28%29 if percentDecode: if b"%" in page: - page = re.sub(b"%([0-9a-fA-F]{2})", lambda _: decodeHex(_.group(1)), page) + page = re.sub(b"%([0-9a-f]{2})", lambda _: decodeHex(_.group(1)), page) + page = re.sub(b"%([0-9A-F]{2})", lambda _: decodeHex(_.group(1)), page) # Note: %DeepSee_SQL in CACHE # e.g. & page = re.sub(b"&([^;]+);", lambda _: six.int2byte(HTML_ENTITIES[getText(_.group(1))]) if HTML_ENTITIES.get(getText(_.group(1)), 256) < 256 else _.group(0), page) diff --git a/lib/utils/deps.py b/lib/utils/deps.py index 1c330931d..7b801fe7e 100644 --- a/lib/utils/deps.py +++ b/lib/utils/deps.py @@ -41,7 +41,7 @@ def checkDependencies(): __import__("kinterbasdb") elif dbmsName == DBMS.DB2: __import__("ibm_db_dbi") - elif dbmsName == DBMS.HSQLDB: + elif dbmsName in (DBMS.HSQLDB, DBMS.CACHE): __import__("jaydebeapi") __import__("jpype") elif dbmsName == DBMS.INFORMIX: diff --git a/plugins/dbms/cache/__init__.py b/plugins/dbms/cache/__init__.py new file mode 100644 index 000000000..2c64c78d0 --- /dev/null +++ b/plugins/dbms/cache/__init__.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/) +See the file 'LICENSE' for copying permission +""" + +from lib.core.enums import DBMS +from lib.core.settings import CACHE_SYSTEM_DBS +from lib.core.unescaper import unescaper + +from plugins.dbms.cache.enumeration import Enumeration +from plugins.dbms.cache.filesystem import Filesystem +from plugins.dbms.cache.fingerprint import Fingerprint +from plugins.dbms.cache.syntax import Syntax +from plugins.dbms.cache.takeover import Takeover +from plugins.generic.misc import Miscellaneous + +class CacheMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover): + """ + This class defines Cache methods + """ + + def __init__(self): + self.excludeDbsList = CACHE_SYSTEM_DBS + + for cls in self.__class__.__bases__: + cls.__init__(self) + + unescaper[DBMS.CACHE] = Syntax.escape diff --git a/plugins/dbms/cache/connector.py b/plugins/dbms/cache/connector.py new file mode 100644 index 000000000..fa5edf463 --- /dev/null +++ b/plugins/dbms/cache/connector.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/) +See the file 'LICENSE' for copying permission +""" + +try: + import jaydebeapi + import jpype +except: + pass + +import logging + +from lib.core.common import checkFile +from lib.core.common import getSafeExString +from lib.core.common import readInput +from lib.core.data import conf +from lib.core.data import logger +from lib.core.exception import SqlmapConnectionException +from plugins.generic.connector import Connector as GenericConnector + +class Connector(GenericConnector): + """ + Homepage: https://pypi.python.org/pypi/JayDeBeApi/ & http://jpype.sourceforge.net/ + User guide: https://pypi.python.org/pypi/JayDeBeApi/#usage & http://jpype.sourceforge.net/doc/user-guide/userguide.html + API: - + Debian package: - + License: LGPL & Apache License 2.0 + """ + + def connect(self): + self.initConnection() + try: + msg = "please enter the location of 'cachejdbc.jar'? " + jar = readInput(msg) + checkFile(jar) + args = "-Djava.class.path=%s" % jar + jvm_path = jpype.getDefaultJVMPath() + jpype.startJVM(jvm_path, args) + except Exception as ex: + raise SqlmapConnectionException(getSafeExString(ex)) + + try: + driver = 'com.intersys.jdbc.CacheDriver' + connection_string = 'jdbc:Cache://%s:%d/%s' % (self.hostname, self.port, self.db) + self.connector = jaydebeapi.connect(driver, connection_string, str(self.user), str(self.password)) + except Exception as ex: + raise SqlmapConnectionException(getSafeExString(ex)) + + self.initCursor() + self.printConnected() + + def fetchall(self): + try: + return self.cursor.fetchall() + except Exception as ex: + logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) '%s'" % getSafeExString(ex)) + return None + + def execute(self, query): + retVal = False + + try: + self.cursor.execute(query) + retVal = True + except Exception as ex: + logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) '%s'" % getSafeExString(ex)) + + self.connector.commit() + + return retVal + + def select(self, query): + self.execute(query) + return self.fetchall() diff --git a/plugins/dbms/cache/enumeration.py b/plugins/dbms/cache/enumeration.py new file mode 100644 index 000000000..2a831eb16 --- /dev/null +++ b/plugins/dbms/cache/enumeration.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/) +See the file 'LICENSE' for copying permission +""" + +from lib.core.data import logger +from lib.core.settings import CACHE_DEFAULT_SCHEMA +from plugins.generic.enumeration import Enumeration as GenericEnumeration + +class Enumeration(GenericEnumeration): + def getCurrentDb(self): + return CACHE_DEFAULT_SCHEMA + + def getUsers(self): + warnMsg = "on Cache it is not possible to enumerate the users" + logger.warn(warnMsg) + + return [] + + def getPasswordHashes(self): + warnMsg = "on Cache it is not possible to enumerate password hashes" + logger.warn(warnMsg) + + return {} + + def getPrivileges(self, *args, **kwargs): + warnMsg = "on Cache it is not possible to enumerate the user privileges" + logger.warn(warnMsg) + + return {} + + def getStatements(self): + warnMsg = "on Cache it is not possible to enumerate the SQL statements" + logger.warn(warnMsg) + + return [] + + def getRoles(self, *args, **kwargs): + warnMsg = "on Cache it is not possible to enumerate the user roles" + logger.warn(warnMsg) + + return {} + + def getHostname(self): + warnMsg = "on Cache it is not possible to enumerate the hostname" + logger.warn(warnMsg) diff --git a/plugins/dbms/cache/filesystem.py b/plugins/dbms/cache/filesystem.py new file mode 100644 index 000000000..e8c642492 --- /dev/null +++ b/plugins/dbms/cache/filesystem.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/) +See the file 'LICENSE' for copying permission +""" + +from plugins.generic.filesystem import Filesystem as GenericFilesystem + +class Filesystem(GenericFilesystem): + pass diff --git a/plugins/dbms/cache/fingerprint.py b/plugins/dbms/cache/fingerprint.py new file mode 100644 index 000000000..fbe09b194 --- /dev/null +++ b/plugins/dbms/cache/fingerprint.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/) +See the file 'LICENSE' for copying permission +""" + +from lib.core.common import Backend +from lib.core.common import Format +from lib.core.common import hashDBRetrieve +from lib.core.common import hashDBWrite +from lib.core.data import conf +from lib.core.data import kb +from lib.core.data import logger +from lib.core.enums import DBMS +from lib.core.enums import FORK +from lib.core.enums import HASHDB_KEYS +from lib.core.session import setDbms +from lib.core.settings import CACHE_ALIASES +from lib.request import inject +from plugins.generic.fingerprint import Fingerprint as GenericFingerprint + +class Fingerprint(GenericFingerprint): + def __init__(self): + GenericFingerprint.__init__(self, DBMS.CACHE) + + def getFingerprint(self): + fork = hashDBRetrieve(HASHDB_KEYS.DBMS_FORK) + + if fork is None: + if inject.checkBooleanExpression("$ZVERSION LIKE '%IRIS%'"): + fork = FORK.IRIS + else: + fork = "" + + hashDBWrite(HASHDB_KEYS.DBMS_FORK, fork) + + value = "" + wsOsFp = Format.getOs("web server", kb.headersFp) + + if wsOsFp: + value += "%s\n" % wsOsFp + + if kb.data.banner: + dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp) + + if dbmsOsFp: + value += "%s\n" % dbmsOsFp + + value += "back-end DBMS: " + + if not conf.extensiveFp: + value += DBMS.CACHE + if fork: + value += " (%s fork)" % fork + return value + + actVer = Format.getDbms() + blank = " " * 15 + value += "active fingerprint: %s" % actVer + + if kb.bannerFp: + banVer = kb.bannerFp.get("dbmsVersion") + + if banVer: + banVer = Format.getDbms([banVer]) + value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer) + + htmlErrorFp = Format.getErrorParsedDBMSes() + + if htmlErrorFp: + value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp) + + if fork: + value += "\n%sfork fingerprint: %s" % (blank, fork) + + return value + + def checkDbms(self): + if not conf.extensiveFp and Backend.isDbmsWithin(CACHE_ALIASES): + setDbms(DBMS.CACHE) + + self.getBanner() + + return True + + infoMsg = "testing %s" % DBMS.CACHE + logger.info(infoMsg) + + result = inject.checkBooleanExpression("$LISTLENGTH(NULL) IS NULL") + + if result: + infoMsg = "confirming %s" % DBMS.CACHE + logger.info(infoMsg) + + result = inject.checkBooleanExpression("%EXTERNAL %INTERNAL NULL IS NULL") + + if not result: + warnMsg = "the back-end DBMS is not %s" % DBMS.CACHE + logger.warn(warnMsg) + + return False + + setDbms(DBMS.CACHE) + + self.getBanner() + + return True + else: + warnMsg = "the back-end DBMS is not %s" % DBMS.CACHE + logger.warn(warnMsg) + + return False diff --git a/plugins/dbms/cache/syntax.py b/plugins/dbms/cache/syntax.py new file mode 100644 index 000000000..1a997b4a0 --- /dev/null +++ b/plugins/dbms/cache/syntax.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/) +See the file 'LICENSE' for copying permission +""" + +from lib.core.convert import getOrds +from plugins.generic.syntax import Syntax as GenericSyntax + +class Syntax(GenericSyntax): + @staticmethod + def escape(expression, quote=True): + """ + >>> from lib.core.common import Backend + >>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") == "SELECT CHAR(97)||CHAR(98)||CHAR(99)||CHAR(100)||CHAR(101)||CHAR(102)||CHAR(103)||CHAR(104) FROM foobar" + True + """ + + def escaper(value): + return "||".join("CHAR(%d)" % _ for _ in getOrds(value)) + + return Syntax._escape(expression, quote, escaper) diff --git a/plugins/dbms/cache/takeover.py b/plugins/dbms/cache/takeover.py new file mode 100644 index 000000000..5210fa529 --- /dev/null +++ b/plugins/dbms/cache/takeover.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/) +See the file 'LICENSE' for copying permission +""" + +from lib.core.exception import SqlmapUnsupportedFeatureException +from plugins.generic.takeover import Takeover as GenericTakeover + +class Takeover(GenericTakeover): + def osCmd(self): + errMsg = "on Cache it is not possible to execute commands" + raise SqlmapUnsupportedFeatureException(errMsg) + + def osShell(self): + errMsg = "on Cache it is not possible to execute commands" + raise SqlmapUnsupportedFeatureException(errMsg) + + def osPwn(self): + errMsg = "on Cache it is not possible to establish an " + errMsg += "out-of-band connection" + raise SqlmapUnsupportedFeatureException(errMsg) + + def osSmb(self): + errMsg = "on Cache it is not possible to establish an " + errMsg += "out-of-band connection" + raise SqlmapUnsupportedFeatureException(errMsg) diff --git a/plugins/dbms/h2/fingerprint.py b/plugins/dbms/h2/fingerprint.py index 69c836396..6a3ac0faa 100644 --- a/plugins/dbms/h2/fingerprint.py +++ b/plugins/dbms/h2/fingerprint.py @@ -71,6 +71,9 @@ class Fingerprint(GenericFingerprint): if htmlErrorFp: value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp) + if fork: + value += "\n%sfork fingerprint: %s" % (blank, fork) + return value def checkDbms(self): diff --git a/plugins/dbms/hsqldb/connector.py b/plugins/dbms/hsqldb/connector.py index 5aa9b2d57..d4ca29082 100644 --- a/plugins/dbms/hsqldb/connector.py +++ b/plugins/dbms/hsqldb/connector.py @@ -33,7 +33,7 @@ class Connector(GenericConnector): def connect(self): self.initConnection() try: - msg = "what's the location of 'hsqldb.jar'? " + msg = "please enter the location of 'hsqldb.jar'? " jar = readInput(msg) checkFile(jar) args = "-Djava.class.path=%s" % jar diff --git a/plugins/dbms/postgresql/fingerprint.py b/plugins/dbms/postgresql/fingerprint.py index c309fc156..bc5c37958 100644 --- a/plugins/dbms/postgresql/fingerprint.py +++ b/plugins/dbms/postgresql/fingerprint.py @@ -35,6 +35,8 @@ class Fingerprint(GenericFingerprint): fork = FORK.REDSHIFT elif inject.checkBooleanExpression("VERSION() LIKE '%Greenplum%'"): # Reference: http://www.sqldbpros.com/wordpress/wp-content/uploads/2014/08/what-version-of-greenplum.png fork = FORK.GREENPLUM + elif inject.checkBooleanExpression("VERSION() LIKE '%Yellowbrick%'"): # Reference: https://www.yellowbrick.com/docs/3.3/ybd_sqlref/version.html + fork = FORK.YELLOWBRICK elif inject.checkBooleanExpression("VERSION() LIKE '%EnterpriseDB%'"): # Reference: https://www.enterprisedb.com/edb-docs/d/edb-postgres-advanced-server/user-guides/user-guide/11/EDB_Postgres_Advanced_Server_Guide.1.087.html fork = FORK.ENTERPRISEDB elif inject.checkBooleanExpression("AURORA_VERSION() LIKE '%'"): # Reference: https://aws.amazon.com/premiumsupport/knowledge-center/aurora-version-number/ diff --git a/plugins/generic/databases.py b/plugins/generic/databases.py index e88b957ba..aa98ee574 100644 --- a/plugins/generic/databases.py +++ b/plugins/generic/databases.py @@ -49,6 +49,7 @@ from lib.core.exception import SqlmapMissingMandatoryOptionException from lib.core.exception import SqlmapNoneDataException from lib.core.exception import SqlmapUserQuitException from lib.core.settings import CURRENT_DB +from lib.core.settings import PLUS_ONE_DBMSES from lib.core.settings import REFLECTED_VALUE_MARKER from lib.core.settings import UPPER_CASE_DBMSES from lib.core.settings import VERTICA_DEFAULT_SCHEMA @@ -84,13 +85,13 @@ class Databases(object): if not kb.data.currentDb and Backend.isDbms(DBMS.VERTICA): kb.data.currentDb = VERTICA_DEFAULT_SCHEMA - if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.PGSQL, DBMS.MONETDB, DBMS.DERBY, DBMS.VERTICA, DBMS.PRESTO, DBMS.MIMERSQL, DBMS.CRATEDB): - warnMsg = "on %s you'll need to use " % Backend.getIdentifiedDbms() + if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.PGSQL, DBMS.MONETDB, DBMS.DERBY, DBMS.VERTICA, DBMS.PRESTO, DBMS.MIMERSQL, DBMS.CRATEDB, DBMS.CACHE): + warnMsg = "on '%s' you'll need to use " % Backend.getIdentifiedDbms() warnMsg += "schema names for enumeration as the counterpart to database " warnMsg += "names on other DBMSes" singleTimeWarnMessage(warnMsg) elif Backend.getIdentifiedDbms() in (DBMS.ALTIBASE, DBMS.CUBRID): - warnMsg = "on %s you'll need to use " % Backend.getIdentifiedDbms() + warnMsg = "on '%s' you'll need to use " % Backend.getIdentifiedDbms() warnMsg += "user names for enumeration as the counterpart to database " warnMsg += "names on other DBMSes" singleTimeWarnMessage(warnMsg) @@ -109,8 +110,8 @@ class Databases(object): warnMsg += "names will be fetched from 'mysql' database" logger.warn(warnMsg) - elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.PGSQL, DBMS.MONETDB, DBMS.DERBY, DBMS.VERTICA, DBMS.PRESTO, DBMS.MIMERSQL, DBMS.CRATEDB): - warnMsg = "schema names are going to be used on %s " % Backend.getIdentifiedDbms() + elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.PGSQL, DBMS.MONETDB, DBMS.DERBY, DBMS.VERTICA, DBMS.PRESTO, DBMS.MIMERSQL, DBMS.CRATEDB, DBMS.CACHE): + warnMsg = "schema names are going to be used on '%s' " % Backend.getIdentifiedDbms() warnMsg += "for enumeration as the counterpart to database " warnMsg += "names on other DBMSes" logger.warn(warnMsg) @@ -118,7 +119,7 @@ class Databases(object): infoMsg = "fetching database (schema) names" elif Backend.getIdentifiedDbms() in (DBMS.ALTIBASE, DBMS.CUBRID): - warnMsg = "user names are going to be used on %s " % Backend.getIdentifiedDbms() + warnMsg = "user names are going to be used on '%s' " % Backend.getIdentifiedDbms() warnMsg += "for enumeration as the counterpart to database " warnMsg += "names on other DBMSes" logger.warn(warnMsg) @@ -157,7 +158,7 @@ class Databases(object): errMsg = "unable to retrieve the number of databases" logger.error(errMsg) else: - plusOne = Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.ALTIBASE) + plusOne = Backend.getIdentifiedDbms() in PLUS_ONE_DBMSES indexRange = getLimitRange(count, plusOne=plusOne) for index in indexRange: @@ -342,7 +343,7 @@ class Databases(object): infoMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(db) logger.info(infoMsg) else: - warnMsg = "on %s it is not " % Backend.getIdentifiedDbms() + warnMsg = "on '%s' it is not " % Backend.getIdentifiedDbms() warnMsg += "possible to get table comments" singleTimeWarnMessage(warnMsg) @@ -388,7 +389,7 @@ class Databases(object): tables = [] - plusOne = Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.ALTIBASE) + plusOne = Backend.getIdentifiedDbms() in PLUS_ONE_DBMSES indexRange = getLimitRange(count, plusOne=plusOne) for index in indexRange: @@ -424,7 +425,7 @@ class Databases(object): infoMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(db) logger.info(infoMsg) else: - warnMsg = "on %s it is not " % Backend.getIdentifiedDbms() + warnMsg = "on '%s' it is not " % Backend.getIdentifiedDbms() warnMsg += "possible to get table comments" singleTimeWarnMessage(warnMsg) @@ -604,7 +605,7 @@ class Databases(object): condQueryStr = "%%s%s" % colCondParam condQuery = " AND (%s)" % " OR ".join(condQueryStr % (condition, unsafeSQLIdentificatorNaming(col)) for col in sorted(colList)) - if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CUBRID): + if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CUBRID, DBMS.CACHE): query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db)) query += condQuery @@ -697,7 +698,7 @@ class Databases(object): infoMsg = "retrieved comment '%s' for column '%s'" % (comment, name) logger.info(infoMsg) else: - warnMsg = "on %s it is not " % Backend.getIdentifiedDbms() + warnMsg = "on '%s' it is not " % Backend.getIdentifiedDbms() warnMsg += "possible to get column comments" singleTimeWarnMessage(warnMsg) @@ -751,7 +752,7 @@ class Databases(object): condQueryStr = "%%s%s" % colCondParam condQuery = " AND (%s)" % " OR ".join(condQueryStr % (condition, unsafeSQLIdentificatorNaming(col)) for col in sorted(colList)) - if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CUBRID): + if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CUBRID, DBMS.CACHE): query = rootQuery.blind.count % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db)) query += condQuery @@ -818,7 +819,7 @@ class Databases(object): continue for index in getLimitRange(count): - if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CUBRID): + if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CUBRID, DBMS.CACHE): query = rootQuery.blind.query % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db)) query += condQuery field = None @@ -867,12 +868,12 @@ class Databases(object): infoMsg = "retrieved comment '%s' for column '%s'" % (comment, column) logger.info(infoMsg) else: - warnMsg = "on %s it is not " % Backend.getIdentifiedDbms() + warnMsg = "on '%s' it is not " % Backend.getIdentifiedDbms() warnMsg += "possible to get column comments" singleTimeWarnMessage(warnMsg) if not onlyColNames: - if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB): + if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CACHE): query = rootQuery.blind.query2 % (unsafeSQLIdentificatorNaming(tbl), column, unsafeSQLIdentificatorNaming(conf.db)) elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE, DBMS.MIMERSQL): query = rootQuery.blind.query2 % (unsafeSQLIdentificatorNaming(tbl.upper()), column, unsafeSQLIdentificatorNaming(conf.db.upper())) @@ -1058,7 +1059,7 @@ class Databases(object): errMsg = "unable to retrieve the number of statements" raise SqlmapNoneDataException(errMsg) - plusOne = Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.ALTIBASE) + plusOne = Backend.getIdentifiedDbms() in PLUS_ONE_DBMSES indexRange = getLimitRange(count, plusOne=plusOne) for index in indexRange: diff --git a/plugins/generic/entries.py b/plugins/generic/entries.py index 117d9a221..f5d85ef89 100644 --- a/plugins/generic/entries.py +++ b/plugins/generic/entries.py @@ -43,6 +43,7 @@ from lib.core.exception import SqlmapUnsupportedFeatureException from lib.core.settings import CHECK_ZERO_COLUMNS_THRESHOLD from lib.core.settings import CURRENT_DB from lib.core.settings import NULL +from lib.core.settings import PLUS_ONE_DBMSES from lib.core.settings import UPPER_CASE_DBMSES from lib.request import inject from lib.utils.hash import attackDumpedTable @@ -233,7 +234,7 @@ class Entries(object): entries = BigArray(_zip(*[entries[colName] for colName in colList])) else: query = rootQuery.inband.query % (colString, conf.db, tbl) - elif Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB): + elif Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CACHE): query = rootQuery.inband.query % (colString, conf.db, tbl, prioritySortColumns(colList)[0]) else: query = rootQuery.inband.query % (colString, conf.db, tbl) @@ -379,7 +380,7 @@ class Entries(object): else: emptyColumns = [] - plusOne = Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.ALTIBASE) + plusOne = Backend.getIdentifiedDbms() in PLUS_ONE_DBMSES indexRange = getLimitRange(count, plusOne=plusOne) if len(colList) < len(indexRange) > CHECK_ZERO_COLUMNS_THRESHOLD: @@ -404,7 +405,7 @@ class Entries(object): if column not in entries: entries[column] = BigArray() - if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB): + if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CACHE): query = rootQuery.blind.query % (agent.preprocessField(tbl, column), conf.db, conf.tbl, sorted(colList, key=len)[0], index) elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE,): query = rootQuery.blind.query % (agent.preprocessField(tbl, column), tbl.upper() if not conf.db else ("%s.%s" % (conf.db.upper(), tbl.upper())), index) diff --git a/plugins/generic/users.py b/plugins/generic/users.py index 1ea627eb1..adbba052f 100644 --- a/plugins/generic/users.py +++ b/plugins/generic/users.py @@ -41,6 +41,7 @@ from lib.core.enums import PAYLOAD from lib.core.exception import SqlmapNoneDataException from lib.core.exception import SqlmapUserQuitException from lib.core.settings import CURRENT_USER +from lib.core.settings import PLUS_ONE_DBMSES from lib.core.threads import getCurrentThreadData from lib.request import inject from lib.utils.hash import attackCachedUsersPasswords @@ -140,7 +141,7 @@ class Users(object): errMsg = "unable to retrieve the number of database users" raise SqlmapNoneDataException(errMsg) - plusOne = Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.ALTIBASE) + plusOne = Backend.getIdentifiedDbms() in PLUS_ONE_DBMSES indexRange = getLimitRange(count, plusOne=plusOne) for index in indexRange: @@ -308,7 +309,7 @@ class Users(object): passwords = [] - plusOne = Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.ALTIBASE) + plusOne = Backend.getIdentifiedDbms() in PLUS_ONE_DBMSES indexRange = getLimitRange(count, plusOne=plusOne) for index in indexRange: @@ -556,7 +557,7 @@ class Users(object): privileges = set() - plusOne = Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.ALTIBASE) + plusOne = Backend.getIdentifiedDbms() in PLUS_ONE_DBMSES indexRange = getLimitRange(count, plusOne=plusOne) for index in indexRange: