From 5eb2263c428ce7330a2e03ed7eae23de158769ca Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Wed, 26 Feb 2020 17:33:47 +0100 Subject: [PATCH] Adding support for eXtremeDB --- data/txt/common-tables.txt | 1 + data/xml/queries.xml | 51 +++++++++++++-- lib/controller/handler.py | 4 ++ lib/core/agent.py | 4 +- lib/core/common.py | 4 +- lib/core/dicts.py | 3 + lib/core/enums.py | 2 + lib/core/settings.py | 8 ++- plugins/dbms/extremedb/__init__.py | 29 +++++++++ plugins/dbms/extremedb/connector.py | 15 +++++ plugins/dbms/extremedb/enumeration.py | 84 ++++++++++++++++++++++++ plugins/dbms/extremedb/filesystem.py | 18 ++++++ plugins/dbms/extremedb/fingerprint.py | 93 +++++++++++++++++++++++++++ plugins/dbms/extremedb/syntax.py | 18 ++++++ plugins/dbms/extremedb/takeover.py | 28 ++++++++ plugins/generic/databases.py | 32 ++++----- plugins/generic/entries.py | 8 +-- plugins/generic/search.py | 4 +- 18 files changed, 373 insertions(+), 33 deletions(-) create mode 100644 plugins/dbms/extremedb/__init__.py create mode 100644 plugins/dbms/extremedb/connector.py create mode 100644 plugins/dbms/extremedb/enumeration.py create mode 100644 plugins/dbms/extremedb/filesystem.py create mode 100644 plugins/dbms/extremedb/fingerprint.py create mode 100644 plugins/dbms/extremedb/syntax.py create mode 100644 plugins/dbms/extremedb/takeover.py diff --git a/data/txt/common-tables.txt b/data/txt/common-tables.txt index 7f111c621..41558db03 100644 --- a/data/txt/common-tables.txt +++ b/data/txt/common-tables.txt @@ -442,6 +442,7 @@ exchange Status WORKS_ON lines +testusers booleantests QRTZ_SIMPLE_TRIGGERS mobile_menu diff --git a/data/xml/queries.xml b/data/xml/queries.xml index 97b6fb3fa..be1f273d5 100644 --- a/data/xml/queries.xml +++ b/data/xml/queries.xml @@ -756,7 +756,7 @@ - + @@ -882,7 +882,7 @@ - + @@ -1505,8 +1505,8 @@ - - + + @@ -1517,4 +1517,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/controller/handler.py b/lib/controller/handler.py index 0cf250f92..9ff195075 100644 --- a/lib/controller/handler.py +++ b/lib/controller/handler.py @@ -18,6 +18,7 @@ from lib.core.settings import CRATEDB_ALIASES from lib.core.settings import CUBRID_ALIASES from lib.core.settings import DB2_ALIASES from lib.core.settings import DERBY_ALIASES +from lib.core.settings import EXTREMEDB_ALIASES from lib.core.settings import FIREBIRD_ALIASES from lib.core.settings import H2_ALIASES from lib.core.settings import HSQLDB_ALIASES @@ -50,6 +51,8 @@ from plugins.dbms.db2.connector import Connector as DB2Conn from plugins.dbms.db2 import DB2Map from plugins.dbms.derby.connector import Connector as DerbyConn from plugins.dbms.derby import DerbyMap +from plugins.dbms.extremedb.connector import Connector as ExtremeDBConn +from plugins.dbms.extremedb import ExtremeDBMap from plugins.dbms.firebird.connector import Connector as FirebirdConn from plugins.dbms.firebird import FirebirdMap from plugins.dbms.h2.connector import Connector as H2Conn @@ -113,6 +116,7 @@ def setHandler(): (DBMS.CRATEDB, CRATEDB_ALIASES, CrateDBMap, CrateDBConn), (DBMS.CUBRID, CUBRID_ALIASES, CubridMap, CubridConn), (DBMS.CACHE, CACHE_ALIASES, CacheMap, CacheConn), + (DBMS.EXTREMEDB, EXTREMEDB_ALIASES, ExtremeDBMap, ExtremeDBConn), ] _ = 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 c1c3d19f0..cbed9c624 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, DBMS.CACHE): + 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, DBMS.EXTREMEDB): if fieldsExists: concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1) concatenatedQuery += "||'%s'" % kb.chars.stop @@ -971,7 +971,7 @@ class Agent(object): fromFrom = limitedQuery[fromIndex + 1:] orderBy = None - if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE, DBMS.H2, DBMS.VERTICA, DBMS.PRESTO, DBMS.MIMERSQL, DBMS.CUBRID): + if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE, DBMS.H2, DBMS.VERTICA, DBMS.PRESTO, DBMS.MIMERSQL, DBMS.CUBRID, DBMS.EXTREMEDB): limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (num, 1) limitedQuery += " %s" % limitStr diff --git a/lib/core/common.py b/lib/core/common.py index 7956a1309..c053a9f06 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, DBMS.CACHE): + 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, DBMS.EXTREMEDB): 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, DBMS.CACHE): + 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, DBMS.EXTREMEDB): 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 27e58c527..05386c9e1 100644 --- a/lib/core/dicts.py +++ b/lib/core/dicts.py @@ -17,6 +17,7 @@ from lib.core.settings import CRATEDB_ALIASES from lib.core.settings import CUBRID_ALIASES from lib.core.settings import DB2_ALIASES from lib.core.settings import DERBY_ALIASES +from lib.core.settings import EXTREMEDB_ALIASES from lib.core.settings import FIREBIRD_ALIASES from lib.core.settings import H2_ALIASES from lib.core.settings import HSQLDB_ALIASES @@ -240,6 +241,7 @@ DBMS_DICT = { 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), + DBMS.EXTREMEDB: (EXTREMEDB_ALIASES, None, None, None), } # Reference: https://blog.jooq.org/tag/sysibm-sysdummy1/ @@ -274,6 +276,7 @@ HEURISTIC_NULL_EVAL = { DBMS.CRATEDB: "MD5(NULL~NULL)", # Note: NULL~NULL also being evaluated on H2 and Ignite DBMS.CUBRID: "(NULL SETEQ NULL)", DBMS.CACHE: "%SQLUPPER NULL", + DBMS.EXTREMEDB: "NULLIFZERO(hashcode(NULL))", } SQL_STATEMENTS = { diff --git a/lib/core/enums.py b/lib/core/enums.py index f110b6033..c0f99c3fc 100644 --- a/lib/core/enums.py +++ b/lib/core/enums.py @@ -55,6 +55,7 @@ class DBMS(object): CRATEDB = "CrateDB" CUBRID = "Cubrid" CACHE = "InterSystems Cache" + EXTREMEDB = "eXtremeDB" class DBMS_DIRECTORY_NAME(object): ACCESS = "access" @@ -80,6 +81,7 @@ class DBMS_DIRECTORY_NAME(object): CRATEDB = "cratedb" CUBRID = "cubrid" CACHE = "cache" + EXTREMEDB = "extremedb" class FORK(object): MARIADB = "MariaDB" diff --git a/lib/core/settings.py b/lib/core/settings.py index 97c6721d6..6f3f4792a 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.39" +VERSION = "1.4.2.40" 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) @@ -269,6 +269,7 @@ 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") +EXTREMEDB_SYSTEM_DBS = ("",) # Note: () + () MSSQL_ALIASES = ("microsoft sql server", "mssqlserver", "mssql", "ms") @@ -294,13 +295,14 @@ MIMERSQL_ALIASES = ("mimersql", "mimer") CRATEDB_ALIASES = ("cratedb", "crate") CUBRID_ALIASES = ("cubrid",) CACHE_ALIASES = ("cachedb", "cache") +EXTREMEDB_ALIASES = ("extremedb", "extreme") 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 + CACHE_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 + EXTREMEDB_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.CACHE, CACHE_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), (DBMS.EXTREMEDB, EXTREMEDB_ALIASES)) USER_AGENT_ALIASES = ("ua", "useragent", "user-agent") REFERER_ALIASES = ("ref", "referer", "referrer") diff --git a/plugins/dbms/extremedb/__init__.py b/plugins/dbms/extremedb/__init__.py new file mode 100644 index 000000000..cc6de9863 --- /dev/null +++ b/plugins/dbms/extremedb/__init__.py @@ -0,0 +1,29 @@ +#!/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 EXTREMEDB_SYSTEM_DBS +from lib.core.unescaper import unescaper +from plugins.dbms.extremedb.enumeration import Enumeration +from plugins.dbms.extremedb.filesystem import Filesystem +from plugins.dbms.extremedb.fingerprint import Fingerprint +from plugins.dbms.extremedb.syntax import Syntax +from plugins.dbms.extremedb.takeover import Takeover +from plugins.generic.misc import Miscellaneous + +class ExtremeDBMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover): + """ + This class defines eXtremeDB methods + """ + + def __init__(self): + self.excludeDbsList = EXTREMEDB_SYSTEM_DBS + + for cls in self.__class__.__bases__: + cls.__init__(self) + + unescaper[DBMS.EXTREMEDB] = Syntax.escape diff --git a/plugins/dbms/extremedb/connector.py b/plugins/dbms/extremedb/connector.py new file mode 100644 index 000000000..cf49b5bf4 --- /dev/null +++ b/plugins/dbms/extremedb/connector.py @@ -0,0 +1,15 @@ +#!/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.connector import Connector as GenericConnector + +class Connector(GenericConnector): + def connect(self): + errMsg = "on eXtremeDB it is not (currently) possible to establish a " + errMsg += "direct connection" + raise SqlmapUnsupportedFeatureException(errMsg) diff --git a/plugins/dbms/extremedb/enumeration.py b/plugins/dbms/extremedb/enumeration.py new file mode 100644 index 000000000..f507af2c5 --- /dev/null +++ b/plugins/dbms/extremedb/enumeration.py @@ -0,0 +1,84 @@ +#!/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 plugins.generic.enumeration import Enumeration as GenericEnumeration + +class Enumeration(GenericEnumeration): + def getBanner(self): + warnMsg = "on eXtremeDB it is not possible to get a banner" + logger.warn(warnMsg) + + return None + + def getCurrentUser(self): + warnMsg = "on eXtremeDB it is not possible to enumerate the current user" + logger.warn(warnMsg) + + def getCurrentDb(self): + warnMsg = "on eXtremeDB it is not possible to get name of the current database" + logger.warn(warnMsg) + + def isDba(self, user=None): + warnMsg = "on eXtremeDB it is not possible to test if current user is DBA" + logger.warn(warnMsg) + + def getUsers(self): + warnMsg = "on eXtremeDB it is not possible to enumerate the users" + logger.warn(warnMsg) + + return [] + + def getPasswordHashes(self): + warnMsg = "on eXtremeDB it is not possible to enumerate the user password hashes" + logger.warn(warnMsg) + + return {} + + def getPrivileges(self, *args, **kwargs): + warnMsg = "on eXtremeDB it is not possible to enumerate the user privileges" + logger.warn(warnMsg) + + return {} + + def getDbs(self): + warnMsg = "on eXtremeDB it is not possible to enumerate databases (use only '--tables')" + logger.warn(warnMsg) + + return [] + + def searchDb(self): + warnMsg = "on eXtremeDB it is not possible to search databases" + logger.warn(warnMsg) + + return [] + + def searchTable(self): + warnMsg = "on eXtremeDB it is not possible to search tables" + logger.warn(warnMsg) + + return [] + + def searchColumn(self): + warnMsg = "on eXtremeDB it is not possible to search columns" + logger.warn(warnMsg) + + return [] + + def search(self): + warnMsg = "on eXtremeDB search option is not available" + logger.warn(warnMsg) + + def getHostname(self): + warnMsg = "on eXtremeDB it is not possible to enumerate the hostname" + logger.warn(warnMsg) + + def getStatements(self): + warnMsg = "on eXtremeDB it is not possible to enumerate the SQL statements" + logger.warn(warnMsg) + + return [] diff --git a/plugins/dbms/extremedb/filesystem.py b/plugins/dbms/extremedb/filesystem.py new file mode 100644 index 000000000..b2f4e4458 --- /dev/null +++ b/plugins/dbms/extremedb/filesystem.py @@ -0,0 +1,18 @@ +#!/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.filesystem import Filesystem as GenericFilesystem + +class Filesystem(GenericFilesystem): + def readFile(self, remoteFile): + errMsg = "on eXtremeDB it is not possible to read files" + raise SqlmapUnsupportedFeatureException(errMsg) + + def writeFile(self, localFile, remoteFile, fileType=None, forceCheck=False): + errMsg = "on eXtremeDB it is not possible to write files" + raise SqlmapUnsupportedFeatureException(errMsg) diff --git a/plugins/dbms/extremedb/fingerprint.py b/plugins/dbms/extremedb/fingerprint.py new file mode 100644 index 000000000..4c63e590c --- /dev/null +++ b/plugins/dbms/extremedb/fingerprint.py @@ -0,0 +1,93 @@ +#!/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.data import conf +from lib.core.data import kb +from lib.core.data import logger +from lib.core.enums import DBMS +from lib.core.session import setDbms +from lib.core.settings import EXTREMEDB_ALIASES +from lib.core.settings import METADB_SUFFIX +from lib.request import inject +from plugins.generic.fingerprint import Fingerprint as GenericFingerprint + +class Fingerprint(GenericFingerprint): + def __init__(self): + GenericFingerprint.__init__(self, DBMS.EXTREMEDB) + + def getFingerprint(self): + 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.EXTREMEDB + 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) + + return value + + def checkDbms(self): + if not conf.extensiveFp and Backend.isDbmsWithin(EXTREMEDB_ALIASES): + setDbms(DBMS.EXTREMEDB) + return True + + infoMsg = "testing %s" % DBMS.EXTREMEDB + logger.info(infoMsg) + + result = inject.checkBooleanExpression("signature(NULL)=usignature(NULL)") + + if result: + infoMsg = "confirming %s" % DBMS.EXTREMEDB + logger.info(infoMsg) + + result = inject.checkBooleanExpression("hashcode(NULL)>=0") + + if not result: + warnMsg = "the back-end DBMS is not %s" % DBMS.EXTREMEDB + logger.warn(warnMsg) + + return False + + setDbms(DBMS.EXTREMEDB) + + return True + else: + warnMsg = "the back-end DBMS is not %s" % DBMS.EXTREMEDB + logger.warn(warnMsg) + + return False + + def forceDbmsEnum(self): + conf.db = ("%s%s" % (DBMS.EXTREMEDB, METADB_SUFFIX)).replace(' ', '_') diff --git a/plugins/dbms/extremedb/syntax.py b/plugins/dbms/extremedb/syntax.py new file mode 100644 index 000000000..dc6c66174 --- /dev/null +++ b/plugins/dbms/extremedb/syntax.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/) +See the file 'LICENSE' for copying permission +""" + +from plugins.generic.syntax import Syntax as GenericSyntax + +class Syntax(GenericSyntax): + @staticmethod + def escape(expression, quote=True): + """ + >>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") == u"SELECT 'abcdefgh' FROM foobar" + True + """ + + return expression diff --git a/plugins/dbms/extremedb/takeover.py b/plugins/dbms/extremedb/takeover.py new file mode 100644 index 000000000..7e41f3cb3 --- /dev/null +++ b/plugins/dbms/extremedb/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 eXtremeDB it is not possible to execute commands" + raise SqlmapUnsupportedFeatureException(errMsg) + + def osShell(self): + errMsg = "on eXtremeDB it is not possible to execute commands" + raise SqlmapUnsupportedFeatureException(errMsg) + + def osPwn(self): + errMsg = "on eXtremeDB it is not possible to establish an " + errMsg += "out-of-band connection" + raise SqlmapUnsupportedFeatureException(errMsg) + + def osSmb(self): + errMsg = "on eXtremeDB it is not possible to establish an " + errMsg += "out-of-band connection" + raise SqlmapUnsupportedFeatureException(errMsg) diff --git a/plugins/generic/databases.py b/plugins/generic/databases.py index aa98ee574..8fb6e50c0 100644 --- a/plugins/generic/databases.py +++ b/plugins/generic/databases.py @@ -86,12 +86,12 @@ class Databases(object): 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, DBMS.CACHE): - warnMsg = "on '%s' you'll need to use " % Backend.getIdentifiedDbms() + 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) @@ -111,7 +111,7 @@ class Databases(object): 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, DBMS.CACHE): - warnMsg = "schema names are going to be used on '%s' " % Backend.getIdentifiedDbms() + 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) @@ -119,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) @@ -225,7 +225,7 @@ class Databases(object): logger.error(errMsg) bruteForce = True - elif Backend.getIdentifiedDbms() in (DBMS.MCKOI,): + elif Backend.getIdentifiedDbms() in (DBMS.MCKOI, DBMS.EXTREMEDB): bruteForce = True elif Backend.getIdentifiedDbms() in (DBMS.ACCESS,): @@ -276,7 +276,7 @@ class Databases(object): return kb.data.cachedTables - message = "do you want to use common table existence check? %s " % ("[Y/n/q]" if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI) else "[y/N/q]") + message = "do you want to use common table existence check? %s " % ("[Y/n/q]" if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI, DBMS.EXTREMEDB) else "[y/N/q]") choice = readInput(message, default='Y' if 'Y' in message else 'N').upper() if choice == 'N': @@ -343,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) @@ -368,7 +368,7 @@ class Databases(object): infoMsg += "database '%s'" % unsafeSQLIdentificatorNaming(db) logger.info(infoMsg) - if Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD, DBMS.MAXDB, DBMS.ACCESS, DBMS.MCKOI): + if Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD, DBMS.MAXDB, DBMS.ACCESS, DBMS.MCKOI, DBMS.EXTREMEDB): query = rootQuery.blind.count else: query = rootQuery.blind.count % unsafeSQLIdentificatorNaming(db) @@ -395,7 +395,7 @@ class Databases(object): for index in indexRange: if Backend.isDbms(DBMS.SYBASE): query = rootQuery.blind.query % (db, (kb.data.cachedTables[-1] if kb.data.cachedTables else " ")) - elif Backend.getIdentifiedDbms() in (DBMS.MAXDB, DBMS.ACCESS, DBMS.MCKOI): + elif Backend.getIdentifiedDbms() in (DBMS.MAXDB, DBMS.ACCESS, DBMS.MCKOI, DBMS.EXTREMEDB): query = rootQuery.blind.query % (kb.data.cachedTables[-1] if kb.data.cachedTables else " ") elif Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD): query = rootQuery.blind.query % index @@ -425,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) @@ -534,7 +534,7 @@ class Databases(object): logger.error(errMsg) bruteForce = True - elif Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI): + elif Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI, DBMS.EXTREMEDB): errMsg = "cannot retrieve column names, " errMsg += "back-end DBMS is %s" % Backend.getIdentifiedDbms() logger.error(errMsg) @@ -567,7 +567,7 @@ class Databases(object): return kb.data.cachedColumns - message = "do you want to use common column existence check? %s" % ("[Y/n/q]" if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI) else "[y/N/q]") + message = "do you want to use common column existence check? %s" % ("[Y/n/q]" if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI, DBMS.EXTREMEDB) else "[y/N/q]") choice = readInput(message, default='Y' if 'Y' in message else 'N').upper() if choice == 'N': @@ -698,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) @@ -868,7 +868,7 @@ 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) @@ -964,7 +964,7 @@ class Databases(object): db = db.upper() table = table.upper() - if Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD, DBMS.MCKOI): + if Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD, DBMS.MCKOI, DBMS.EXTREMEDB): query = "SELECT %s FROM %s" % (queries[Backend.getIdentifiedDbms()].count.query % '*', safeSQLIdentificatorNaming(table, True)) else: query = "SELECT %s FROM %s.%s" % (queries[Backend.getIdentifiedDbms()].count.query % '*', safeSQLIdentificatorNaming(db), safeSQLIdentificatorNaming(table, True)) @@ -992,7 +992,7 @@ class Databases(object): if not conf.db: conf.db, conf.tbl = conf.tbl.split('.', 1) - if conf.tbl is not None and conf.db is None and Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD, DBMS.MCKOI): + if conf.tbl is not None and conf.db is None and Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD, DBMS.MCKOI, DBMS.EXTREMEDB): warnMsg = "missing database parameter. sqlmap is going to " warnMsg += "use the current database to retrieve the " warnMsg += "number of entries for table '%s'" % unsafeSQLIdentificatorNaming(conf.tbl) diff --git a/plugins/generic/entries.py b/plugins/generic/entries.py index f5d85ef89..7f5dc2c96 100644 --- a/plugins/generic/entries.py +++ b/plugins/generic/entries.py @@ -180,7 +180,7 @@ class Entries(object): if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE, DBMS.MIMERSQL): query = rootQuery.inband.query % (colString, tbl.upper() if not conf.db else ("%s.%s" % (conf.db.upper(), tbl.upper()))) - elif Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD, DBMS.MAXDB, DBMS.MCKOI): + elif Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD, DBMS.MAXDB, DBMS.MCKOI, DBMS.EXTREMEDB): query = rootQuery.inband.query % (colString, tbl) elif Backend.getIdentifiedDbms() in (DBMS.SYBASE, DBMS.MSSQL): # Partial inband and error @@ -289,7 +289,7 @@ class Entries(object): if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE, DBMS.MIMERSQL): query = rootQuery.blind.count % (tbl.upper() if not conf.db else ("%s.%s" % (conf.db.upper(), tbl.upper()))) - elif Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD, DBMS.MCKOI): + elif Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD, DBMS.MCKOI, DBMS.EXTREMEDB): query = rootQuery.blind.count % tbl elif Backend.getIdentifiedDbms() in (DBMS.SYBASE, DBMS.MSSQL): query = rootQuery.blind.count % ("%s.%s" % (conf.db, tbl)) @@ -328,7 +328,7 @@ class Entries(object): continue elif Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.SYBASE, DBMS.MAXDB, DBMS.MSSQL, DBMS.INFORMIX, DBMS.MCKOI): - if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI): + if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI, DBMS.EXTREMEDB): table = tbl elif Backend.getIdentifiedDbms() in (DBMS.SYBASE, DBMS.MSSQL, DBMS.MAXDB): table = "%s.%s" % (conf.db, tbl) @@ -411,7 +411,7 @@ class Entries(object): query = rootQuery.blind.query % (agent.preprocessField(tbl, column), tbl.upper() if not conf.db else ("%s.%s" % (conf.db.upper(), tbl.upper())), index) elif Backend.getIdentifiedDbms() in (DBMS.MIMERSQL,): query = rootQuery.blind.query % (agent.preprocessField(tbl, column), tbl.upper() if not conf.db else ("%s.%s" % (conf.db.upper(), tbl.upper())), sorted(colList, key=len)[0], index) - elif Backend.isDbms(DBMS.SQLITE): + elif Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.EXTREMEDB): query = rootQuery.blind.query % (agent.preprocessField(tbl, column), tbl, index) elif Backend.isDbms(DBMS.FIREBIRD): query = rootQuery.blind.query % (index, agent.preprocessField(tbl, column), tbl) diff --git a/plugins/generic/search.py b/plugins/generic/search.py index db717f4a4..080d47476 100644 --- a/plugins/generic/search.py +++ b/plugins/generic/search.py @@ -149,7 +149,7 @@ class Search(object): bruteForce = True if bruteForce: - message = "do you want to use common table existence check? %s" % ("[Y/n/q]" if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI) else "[y/N/q]") + message = "do you want to use common table existence check? %s" % ("[Y/n/q]" if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI, DBMS.EXTREMEDB) else "[y/N/q]") choice = readInput(message, default='Y' if 'Y' in message else 'N').upper() if choice == 'N': @@ -353,7 +353,7 @@ class Search(object): bruteForce = True if bruteForce: - message = "do you want to use common column existence check? %s" % ("[Y/n/q]" if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI) else "[y/N/q]") + message = "do you want to use common column existence check? %s" % ("[Y/n/q]" if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI, DBMS.EXTREMEDB) else "[y/N/q]") choice = readInput(message, default='Y' if 'Y' in message else 'N').upper() if choice == 'N':