diff --git a/lib/controller/checks.py b/lib/controller/checks.py index fac6027e4..4ef33249b 100644 --- a/lib/controller/checks.py +++ b/lib/controller/checks.py @@ -89,6 +89,7 @@ from lib.core.settings import IDS_WAF_CHECK_TIMEOUT from lib.core.settings import MAX_DIFFLIB_SEQUENCE_LENGTH from lib.core.settings import NON_SQLI_CHECK_PREFIX_SUFFIX_LENGTH from lib.core.settings import PRECONNECT_INCOMPATIBLE_SERVERS +from lib.core.settings import SINGLE_QUOTE_MARKER from lib.core.settings import SLEEP_TIME_MARKER from lib.core.settings import SUHOSIN_MAX_VALUE_LENGTH from lib.core.settings import SUPPORTED_DBMS @@ -859,8 +860,8 @@ def heuristicCheckDbms(injection): if conf.noEscape and dbms not in FROM_DUMMY_TABLE: continue - if checkBooleanExpression("(SELECT '%s'%s)='%s'" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), randStr1)): - if not checkBooleanExpression("(SELECT '%s'%s)='%s'" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), randStr2)): + if checkBooleanExpression("(SELECT '%s'%s)=%s%s%s" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), SINGLE_QUOTE_MARKER, randStr1, SINGLE_QUOTE_MARKER)): + if not checkBooleanExpression("(SELECT '%s'%s)=%s%s%s" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), SINGLE_QUOTE_MARKER, randStr2, SINGLE_QUOTE_MARKER)): retVal = dbms break diff --git a/lib/controller/handler.py b/lib/controller/handler.py index 6ce752dd2..9dab40488 100644 --- a/lib/controller/handler.py +++ b/lib/controller/handler.py @@ -21,6 +21,7 @@ from lib.core.settings import MAXDB_ALIASES from lib.core.settings import SYBASE_ALIASES from lib.core.settings import DB2_ALIASES from lib.core.settings import HSQLDB_ALIASES +from lib.core.settings import H2_ALIASES from lib.core.settings import INFORMIX_ALIASES from lib.utils.sqlalchemy import SQLAlchemy @@ -46,6 +47,8 @@ from plugins.dbms.db2 import DB2Map from plugins.dbms.db2.connector import Connector as DB2Conn from plugins.dbms.hsqldb import HSQLDBMap from plugins.dbms.hsqldb.connector import Connector as HSQLDBConn +from plugins.dbms.h2 import H2Map +from plugins.dbms.h2.connector import Connector as H2Conn from plugins.dbms.informix import InformixMap from plugins.dbms.informix.connector import Connector as InformixConn @@ -67,6 +70,7 @@ def setHandler(): (DBMS.SYBASE, SYBASE_ALIASES, SybaseMap, SybaseConn), (DBMS.DB2, DB2_ALIASES, DB2Map, DB2Conn), (DBMS.HSQLDB, HSQLDB_ALIASES, HSQLDBMap, HSQLDBConn), + (DBMS.H2, H2_ALIASES, H2Map, H2Conn), (DBMS.INFORMIX, INFORMIX_ALIASES, InformixMap, InformixConn), ] diff --git a/lib/core/agent.py b/lib/core/agent.py index 423f66bd7..10ee4cfdd 100644 --- a/lib/core/agent.py +++ b/lib/core/agent.py @@ -43,6 +43,7 @@ from lib.core.settings import INFERENCE_MARKER from lib.core.settings import NULL from lib.core.settings import PAYLOAD_DELIMITER from lib.core.settings import REPLACEMENT_MARKER +from lib.core.settings import SINGLE_QUOTE_MARKER from lib.core.settings import SLEEP_TIME_MARKER from lib.core.unescaper import unescaper @@ -348,6 +349,7 @@ class Agent(object): if payload: payload = payload.replace(SLEEP_TIME_MARKER, str(conf.timeSec)) + payload = payload.replace(SINGLE_QUOTE_MARKER, "'") for _ in set(re.findall(r"\[RANDNUM(?:\d+)?\]", payload, re.I)): payload = payload.replace(_, str(randomInt())) @@ -821,7 +823,7 @@ class Agent(object): limitRegExp2 = None if (limitRegExp or limitRegExp2) or (Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit): - if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE): + if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE, DBMS.H2): limitGroupStart = queries[Backend.getIdentifiedDbms()].limitgroupstart.query limitGroupStop = queries[Backend.getIdentifiedDbms()].limitgroupstop.query @@ -911,7 +913,7 @@ class Agent(object): fromFrom = limitedQuery[fromIndex + 1:] orderBy = None - if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE): + if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE, DBMS.H2): limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (num, 1) limitedQuery += " %s" % limitStr diff --git a/lib/core/common.py b/lib/core/common.py index 175747822..da7605458 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -3649,7 +3649,7 @@ def safeSQLIdentificatorNaming(name, isTable=False): if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ACCESS): retVal = "`%s`" % retVal - elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.SQLITE, DBMS.INFORMIX, DBMS.HSQLDB): + elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.SQLITE, DBMS.HSQLDB, DBMS.H2, DBMS.INFORMIX): retVal = "\"%s\"" % retVal elif Backend.getIdentifiedDbms() in (DBMS.ORACLE,): retVal = "\"%s\"" % retVal.upper() @@ -4275,7 +4275,7 @@ def decodeHexValue(value, raw=False): retVal = retVal.decode("utf-16-le") except UnicodeDecodeError: pass - elif Backend.isDbms(DBMS.HSQLDB): + elif Backend.getIdentifiedDbms() in (DBMS.HSQLDB, DBMS.H2): try: retVal = retVal.decode("utf-16-be") except UnicodeDecodeError: diff --git a/lib/core/dicts.py b/lib/core/dicts.py index b291aeff9..5cfb8633c 100644 --- a/lib/core/dicts.py +++ b/lib/core/dicts.py @@ -22,6 +22,7 @@ from lib.core.settings import MAXDB_ALIASES from lib.core.settings import SYBASE_ALIASES from lib.core.settings import DB2_ALIASES from lib.core.settings import HSQLDB_ALIASES +from lib.core.settings import H2_ALIASES from lib.core.settings import INFORMIX_ALIASES FIREBIRD_TYPES = { @@ -195,6 +196,7 @@ DBMS_DICT = { DBMS.SYBASE: (SYBASE_ALIASES, "python-pymssql", "https://github.com/pymssql/pymssql", "sybase"), DBMS.DB2: (DB2_ALIASES, "python ibm-db", "https://github.com/ibmdb/python-ibmdb", "ibm_db_sa"), DBMS.HSQLDB: (HSQLDB_ALIASES, "python jaydebeapi & python-jpype", "https://pypi.python.org/pypi/JayDeBeApi/ & http://jpype.sourceforge.net/", None), + DBMS.H2: (H2_ALIASES, None, None), DBMS.INFORMIX: (INFORMIX_ALIASES, "python ibm-db", "https://github.com/ibmdb/python-ibmdb", "ibm_db_sa"), } diff --git a/lib/core/enums.py b/lib/core/enums.py index ab21db6bd..181cae66c 100644 --- a/lib/core/enums.py +++ b/lib/core/enums.py @@ -43,6 +43,7 @@ class DBMS: SQLITE = "SQLite" SYBASE = "Sybase" HSQLDB = "HSQLDB" + H2 = "H2" INFORMIX = "Informix" class DBMS_DIRECTORY_NAME: @@ -57,6 +58,7 @@ class DBMS_DIRECTORY_NAME: SQLITE = "sqlite" SYBASE = "sybase" HSQLDB = "hsqldb" + H2 = "h2" INFORMIX = "informix" class CUSTOM_LOGGING: diff --git a/lib/core/settings.py b/lib/core/settings.py index fd209742c..e99c4a326 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -19,7 +19,7 @@ from lib.core.enums import DBMS_DIRECTORY_NAME from lib.core.enums import OS # sqlmap version (...) -VERSION = "1.2.10.20" +VERSION = "1.2.10.21" 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) @@ -71,6 +71,7 @@ RANDOM_INTEGER_MARKER = "[RANDINT]" RANDOM_STRING_MARKER = "[RANDSTR]" SLEEP_TIME_MARKER = "[SLEEPTIME]" INFERENCE_MARKER = "[INFERENCE]" +SINGLE_QUOTE_MARKER = "[SINGLE_QUOTE]" PAYLOAD_DELIMITER = "__PAYLOAD_DELIMITER__" CHAR_INFERENCE_MARK = "%c" @@ -236,6 +237,7 @@ MAXDB_SYSTEM_DBS = ("SYSINFO", "DOMAIN") SYBASE_SYSTEM_DBS = ("master", "model", "sybsystemdb", "sybsystemprocs") DB2_SYSTEM_DBS = ("NULLID", "SQLJ", "SYSCAT", "SYSFUN", "SYSIBM", "SYSIBMADM", "SYSIBMINTERNAL", "SYSIBMTS", "SYSPROC", "SYSPUBLIC", "SYSSTAT", "SYSTOOLS") HSQLDB_SYSTEM_DBS = ("INFORMATION_SCHEMA", "SYSTEM_LOB") +H2_SYSTEM_DBS = ("INFORMATION_SCHEMA") INFORMIX_SYSTEM_DBS = ("sysmaster", "sysutils", "sysuser", "sysadmin") MSSQL_ALIASES = ("microsoft sql server", "mssqlserver", "mssql", "ms") @@ -249,14 +251,15 @@ MAXDB_ALIASES = ("maxdb", "sap maxdb", "sap db") SYBASE_ALIASES = ("sybase", "sybase sql server") DB2_ALIASES = ("db2", "ibm db2", "ibmdb2") HSQLDB_ALIASES = ("hsql", "hsqldb", "hs", "hypersql") +H2_ALIASES = ("h2",) INFORMIX_ALIASES = ("informix", "ibm informix", "ibminformix") 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 + INFORMIX_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 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_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)) USER_AGENT_ALIASES = ("ua", "useragent", "user-agent") REFERER_ALIASES = ("ref", "referer", "referrer") diff --git a/plugins/dbms/h2/__init__.py b/plugins/dbms/h2/__init__.py new file mode 100644 index 000000000..c35662f60 --- /dev/null +++ b/plugins/dbms/h2/__init__.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) +See the file 'LICENSE' for copying permission +""" + +from lib.core.enums import DBMS +from lib.core.settings import H2_SYSTEM_DBS +from lib.core.unescaper import unescaper +from plugins.dbms.h2.enumeration import Enumeration +from plugins.dbms.h2.filesystem import Filesystem +from plugins.dbms.h2.fingerprint import Fingerprint +from plugins.dbms.h2.syntax import Syntax +from plugins.dbms.h2.takeover import Takeover +from plugins.generic.misc import Miscellaneous + +class H2Map(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover): + """ + This class defines H2 methods + """ + + def __init__(self): + self.excludeDbsList = H2_SYSTEM_DBS + + Syntax.__init__(self) + Fingerprint.__init__(self) + Enumeration.__init__(self) + Filesystem.__init__(self) + Miscellaneous.__init__(self) + Takeover.__init__(self) + + unescaper[DBMS.H2] = Syntax.escape diff --git a/plugins/dbms/h2/connector.py b/plugins/dbms/h2/connector.py new file mode 100644 index 000000000..ee605409f --- /dev/null +++ b/plugins/dbms/h2/connector.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2018 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 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 __init__(self): + GenericConnector.__init__(self) + + def connect(self): + self.initConnection() + try: + msg = "what's the location of 'hsqldb.jar'? " + jar = readInput(msg) + checkFile(jar) + args = "-Djava.class.path=%s" % jar + jvm_path = jpype.getDefaultJVMPath() + jpype.startJVM(jvm_path, args) + except Exception, msg: + raise SqlmapConnectionException(msg[0]) + + try: + driver = 'org.hsqldb.jdbc.JDBCDriver' + connection_string = 'jdbc:hsqldb:mem:.' # 'jdbc:hsqldb:hsql://%s/%s' % (self.hostname, self.db) + self.connector = jaydebeapi.connect(driver, connection_string, str(self.user), str(self.password)) + except Exception, msg: + raise SqlmapConnectionException(msg[0]) + + self.initCursor() + self.printConnected() + + def fetchall(self): + try: + return self.cursor.fetchall() + except Exception, msg: + logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % msg[1]) + return None + + def execute(self, query): + retVal = False + + try: + self.cursor.execute(query) + retVal = True + except Exception, msg: # TODO: fix with specific error + logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % msg[1]) + + self.connector.commit() + + return retVal + + def select(self, query): + retVal = None + + upper_query = query.upper() + + if query and not (upper_query.startswith("SELECT ") or upper_query.startswith("VALUES ")): + query = "VALUES %s" % query + + if query and upper_query.startswith("SELECT ") and " FROM " not in upper_query: + query = "%s FROM (VALUES(0))" % query + + self.cursor.execute(query) + retVal = self.cursor.fetchall() + + return retVal diff --git a/plugins/dbms/h2/enumeration.py b/plugins/dbms/h2/enumeration.py new file mode 100644 index 000000000..2035d6f25 --- /dev/null +++ b/plugins/dbms/h2/enumeration.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) +See the file 'LICENSE' for copying permission +""" + +from plugins.generic.enumeration import Enumeration as GenericEnumeration +from lib.core.data import conf +from lib.core.data import kb +from lib.core.data import logger +from lib.core.data import queries +from lib.core.common import unArrayizeValue +from lib.core.enums import DBMS +from lib.request import inject + +class Enumeration(GenericEnumeration): + def __init__(self): + GenericEnumeration.__init__(self) + + def getBanner(self): + if not conf.getBanner: + return + + if kb.data.banner is None: + infoMsg = "fetching banner" + logger.info(infoMsg) + + query = queries[DBMS.H2].banner.query + kb.data.banner = unArrayizeValue(inject.getValue(query, safeCharEncode=True)) + + return kb.data.banner + + def getPrivileges(self, *args): + warnMsg = "on H2 it is not possible to enumerate the user privileges" + logger.warn(warnMsg) + + return {} + + def getHostname(self): + warnMsg = "on H2 it is not possible to enumerate the hostname" + logger.warn(warnMsg) diff --git a/plugins/dbms/h2/filesystem.py b/plugins/dbms/h2/filesystem.py new file mode 100644 index 000000000..7542ffb60 --- /dev/null +++ b/plugins/dbms/h2/filesystem.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2018 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 __init__(self): + GenericFilesystem.__init__(self) + + def readFile(self, rFile): + errMsg = "on H2 it is not possible to read files" + raise SqlmapUnsupportedFeatureException(errMsg) + + def writeFile(self, wFile, dFile, fileType=None, forceCheck=False): + errMsg = "on H2 it is not possible to read files" + raise SqlmapUnsupportedFeatureException(errMsg) diff --git a/plugins/dbms/h2/fingerprint.py b/plugins/dbms/h2/fingerprint.py new file mode 100644 index 000000000..d11313aff --- /dev/null +++ b/plugins/dbms/h2/fingerprint.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) +See the file 'LICENSE' for copying permission +""" + +import re + +from lib.core.common import Backend +from lib.core.common import Format +from lib.core.common import unArrayizeValue +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 H2_ALIASES +from lib.request import inject +from plugins.generic.fingerprint import Fingerprint as GenericFingerprint + +class Fingerprint(GenericFingerprint): + def __init__(self): + GenericFingerprint.__init__(self, DBMS.H2) + + def getFingerprint(self): + value = "" + wsOsFp = Format.getOs("web server", kb.headersFp) + + if wsOsFp and not conf.api: + value += "%s\n" % wsOsFp + + if kb.data.banner: + dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp) + + if dbmsOsFp and not conf.api: + value += "%s\n" % dbmsOsFp + + value += "back-end DBMS: " + actVer = Format.getDbms() + + if not conf.extensiveFp: + value += actVer + return value + + blank = " " * 15 + value += "active fingerprint: %s" % actVer + + if kb.bannerFp: + banVer = kb.bannerFp.get("dbmsVersion") + + if re.search(r"-log$", kb.data.banner): + banVer += ", logging enabled" + + banVer = Format.getDbms([banVer] if banVer else None) + 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(H2_ALIASES): + setDbms("%s %s" % (DBMS.H2, Backend.getVersion())) + + if Backend.isVersionGreaterOrEqualThan("1.7.2"): + kb.data.has_information_schema = True + + self.getBanner() + + return True + + infoMsg = "testing %s" % DBMS.H2 + logger.info(infoMsg) + + result = inject.checkBooleanExpression("ZERO() IS 0") + + if result: + infoMsg = "confirming %s" % DBMS.H2 + logger.info(infoMsg) + + result = inject.checkBooleanExpression("ROUNDMAGIC(PI())>=3") + + if not result: + warnMsg = "the back-end DBMS is not %s" % DBMS.H2 + logger.warn(warnMsg) + + return False + else: + kb.data.has_information_schema = True + Backend.setVersion(">= 1.7.2") + setDbms("%s 1.7.2" % DBMS.H2) + + banner = self.getBanner() + if banner: + Backend.setVersion("= %s" % banner) + else: + if inject.checkBooleanExpression("(SELECT [RANDNUM] FROM (VALUES(0)))=[RANDNUM]"): + Backend.setVersionList([">= 2.0.0", "< 2.3.0"]) + else: + banner = unArrayizeValue(inject.getValue("\"org.hsqldbdb.Library.getDatabaseFullProductVersion\"()", safeCharEncode=True)) + if banner: + Backend.setVersion("= %s" % banner) + else: + Backend.setVersionList([">= 1.7.2", "< 1.8.0"]) + + return True + else: + warnMsg = "the back-end DBMS is not %s" % DBMS.H2 + logger.warn(warnMsg) + + dbgMsg = "...or version is < 1.7.2" + logger.debug(dbgMsg) + + return False + + def getHostname(self): + warnMsg = "on H2 it is not possible to enumerate the hostname" + logger.warn(warnMsg) diff --git a/plugins/dbms/h2/syntax.py b/plugins/dbms/h2/syntax.py new file mode 100644 index 000000000..aab5e6b6c --- /dev/null +++ b/plugins/dbms/h2/syntax.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) +See the file 'LICENSE' for copying permission +""" + +from plugins.generic.syntax import Syntax as GenericSyntax + +class Syntax(GenericSyntax): + def __init__(self): + GenericSyntax.__init__(self) + + @staticmethod + def escape(expression, quote=True): + """ + >>> 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' + """ + + def escaper(value): + return "||".join("CHAR(%d)" % ord(value[i]) for i in xrange(len(value))) + + return Syntax._escape(expression, quote, escaper) diff --git a/plugins/dbms/h2/takeover.py b/plugins/dbms/h2/takeover.py new file mode 100644 index 000000000..28d922d3f --- /dev/null +++ b/plugins/dbms/h2/takeover.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2018 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 __init__(self): + GenericTakeover.__init__(self) + + def osCmd(self): + errMsg = "on H2 it is not possible to execute commands" + raise SqlmapUnsupportedFeatureException(errMsg) + + def osShell(self): + errMsg = "on H2 it is not possible to execute commands" + raise SqlmapUnsupportedFeatureException(errMsg) + + def osPwn(self): + errMsg = "on H2 it is not possible to establish an " + errMsg += "out-of-band connection" + raise SqlmapUnsupportedFeatureException(errMsg) + + def osSmb(self): + errMsg = "on H2 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 a8edb98b8..3f0354974 100644 --- a/plugins/generic/databases.py +++ b/plugins/generic/databases.py @@ -569,7 +569,7 @@ class Databases: 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): + if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2): query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db)) query += condQuery elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): @@ -697,7 +697,7 @@ class Databases: 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): + if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2): query = rootQuery.blind.count % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db)) query += condQuery @@ -757,7 +757,7 @@ class Databases: continue for index in getLimitRange(count): - if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB): + if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2): query = rootQuery.blind.query % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db)) query += condQuery field = None @@ -800,7 +800,7 @@ class Databases: singleTimeWarnMessage(warnMsg) if not onlyColNames: - if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL): + if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2): query = rootQuery.blind.query2 % (unsafeSQLIdentificatorNaming(tbl), column, unsafeSQLIdentificatorNaming(conf.db)) elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): query = rootQuery.blind.query2 % (unsafeSQLIdentificatorNaming(tbl.upper()), column, unsafeSQLIdentificatorNaming(conf.db.upper())) diff --git a/plugins/generic/entries.py b/plugins/generic/entries.py index 80230ce0f..595e8f9a5 100644 --- a/plugins/generic/entries.py +++ b/plugins/generic/entries.py @@ -67,7 +67,7 @@ class Entries: conf.db = self.getCurrentDb() elif conf.db is not None: - if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB): + if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB, DBMS.H2): conf.db = conf.db.upper() if ',' in conf.db: @@ -83,7 +83,7 @@ class Entries: conf.db = safeSQLIdentificatorNaming(conf.db) if conf.tbl: - if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB): + if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB, DBMS.H2): conf.tbl = conf.tbl.upper() tblList = conf.tbl.split(',') @@ -226,7 +226,7 @@ class Entries: entries = 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): + elif Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2): query = rootQuery.inband.query % (colString, conf.db, tbl, prioritySortColumns(colList)[0]) else: query = rootQuery.inband.query % (colString, conf.db, tbl) @@ -399,7 +399,7 @@ class Entries: if column not in entries: entries[column] = BigArray() - if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB): + if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2): 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): 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/txt/checksum.md5 b/txt/checksum.md5 index 53ef4b474..4f2c6d2ae 100644 --- a/txt/checksum.md5 +++ b/txt/checksum.md5 @@ -23,21 +23,21 @@ b3e60ea4e18a65c48515d04aab28ff68 extra/sqlharvest/sqlharvest.py 1e5532ede194ac9c083891c2f02bca93 extra/wafdetectify/__init__.py c1bccc94522d3425a372dcd57f78418e extra/wafdetectify/wafdetectify.py 3459c562a6abb9b4bdcc36925f751f3e lib/controller/action.py -51bd96b450cbfdbff8eea4801e7486ae lib/controller/checks.py +84316968d7235f53aac7e25069128725 lib/controller/checks.py d6deacb76e1f479b3c690c215fad1c08 lib/controller/controller.py -c7443613a0a2505b1faec931cee2a6ef lib/controller/handler.py +97a0f363bfc33a5ee4853cdf91515423 lib/controller/handler.py 1e5532ede194ac9c083891c2f02bca93 lib/controller/__init__.py -6f9bc9a98821572b68819b8f12de6b59 lib/core/agent.py +a866dd953fdc4b5273a9c28f6b2361f1 lib/core/agent.py c347f085bd561adfa26d3a9512e5f3b9 lib/core/bigarray.py -11448f59efbfdceff2437239e36d9dc5 lib/core/common.py +ce7fb7270b104f05d1e2be088b69c976 lib/core/common.py 0d082da16c388b3445e656e0760fb582 lib/core/convert.py 9f87391b6a3395f7f50830b391264f27 lib/core/data.py 72016ea5c994a711a262fd64572a0fcd lib/core/datatype.py 4086fb55f42e27de5330505605baad0f lib/core/decorators.py fbb55cc6100318ff922957b6577dc58f lib/core/defaults.py -4d50e0f893477196d83608175d1a7de4 lib/core/dicts.py +56b79ee7acd2da19c1678250edfdafab lib/core/dicts.py d4b3d448bcfd9f15d089fc81d38f4825 lib/core/dump.py -705fcf5b66cb4518a54e4d717c915968 lib/core/enums.py +ee7da34f4947739778a07d6c9c05ab54 lib/core/enums.py cada93357a7321655927fc9625b3bfec lib/core/exception.py 1e5532ede194ac9c083891c2f02bca93 lib/core/__init__.py 458a194764805cd8312c14ecd4be4d1e lib/core/log.py @@ -49,7 +49,7 @@ c8c386d644d57c659d74542f5f57f632 lib/core/patch.py 0c3eef46bdbf87e29a3f95f90240d192 lib/core/replication.py a7db43859b61569b601b97f187dd31c5 lib/core/revision.py fcb74fcc9577523524659ec49e2e964b lib/core/session.py -deced6d285dcd850e4e7d8e478527729 lib/core/settings.py +1eb1c8d9bf5f38efc0625524d7dfa8ed lib/core/settings.py dd68a9d02fccb4fa1428b20e15b0db5d lib/core/shell.py a7edc9250d13af36ac0108f259859c19 lib/core/subprocessng.py 47ad325975ab21fc9f11d90b46d0d143 lib/core/target.py @@ -140,6 +140,13 @@ bf98dbd666c162088f23ee697c065010 plugins/dbms/firebird/fingerprint.py d4ea3036492b8ae15340548b2936021f plugins/dbms/firebird/__init__.py c56f2dabe88fd761a1a9a51e4d104088 plugins/dbms/firebird/syntax.py 1522a29bd4b54ea78bb2855fc32b6c72 plugins/dbms/firebird/takeover.py +271a7f16e781d56a0a31a3d5515a1945 plugins/dbms/h2/connector.py +687005cf105ab50c62b6686866d6ef13 plugins/dbms/h2/enumeration.py +b1ed542fff0aa53c54e8bc07658aeaf1 plugins/dbms/h2/filesystem.py +443bc9ac09ce180360ff5a660ac3d6ba plugins/dbms/h2/fingerprint.py +1de698e4cfddd754ffe31ea2640a481a plugins/dbms/h2/__init__.py +4673ebfdce9859718c19e8a7765da8d3 plugins/dbms/h2/syntax.py +af746ef421cfefedc1aaa9dca1503de2 plugins/dbms/h2/takeover.py 271a7f16e781d56a0a31a3d5515a1945 plugins/dbms/hsqldb/connector.py 95919592e5bb83df00b99bb9e8a70977 plugins/dbms/hsqldb/enumeration.py 616595e74ecb644271cbbd31815d92e0 plugins/dbms/hsqldb/filesystem.py @@ -206,8 +213,8 @@ a3db8618eed5bb2807b6f77605cba9cc plugins/dbms/sybase/__init__.py 79f6c7017db4ded8f74a0117188836ff plugins/dbms/sybase/takeover.py 34d181a7086d6dfc7e72ae5f8a4cfe0f plugins/generic/connector.py ce6a6ff713852b5eca7b78316cc941c4 plugins/generic/custom.py -2e0c1c5ced14222d9fef2dd12447d815 plugins/generic/databases.py -ea3a7f87e3e0cbc3aacbd3af4b6f5ce6 plugins/generic/entries.py +ca122ea307ed367a55b12a67a6079e74 plugins/generic/databases.py +35546acab0eea406c23b84363df4d534 plugins/generic/entries.py d82f2c78c1d4d7c6487e94fd3a68a908 plugins/generic/enumeration.py 0a67b8b46f69df7cfacc286b47a0d9a5 plugins/generic/filesystem.py f5d5419efddfe04648ea5e953c650793 plugins/generic/fingerprint.py @@ -477,4 +484,4 @@ a279656ea3fcb85c727249b02f828383 xml/livetests.xml 82c65823a0af3fccbecf37f1c75f0b29 xml/payloads/stacked_queries.xml 92c41925eba27afeed76bceba6b18be2 xml/payloads/time_blind.xml ac649aff0e7db413e4937e446e398736 xml/payloads/union_query.xml -b148ef9ef70aaada9eb6e58ab1e384e1 xml/queries.xml +39173640d6807991a6b78e9bea973339 xml/queries.xml diff --git a/xml/queries.xml b/xml/queries.xml index 7278fb085..db9950f4b 100644 --- a/xml/queries.xml +++ b/xml/queries.xml @@ -720,6 +720,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +