From 4c804a3fd63c7637f22aa44e258cf0bff31257bd Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Mon, 20 Jan 2020 15:33:45 +0100 Subject: [PATCH] Adding support for Apache Derby --- data/xml/errors.xml | 7 +++ data/xml/queries.xml | 69 +++++++++++++++++++++ lib/controller/handler.py | 4 ++ lib/core/agent.py | 6 +- lib/core/common.py | 1 - lib/core/dicts.py | 5 +- lib/core/enums.py | 2 + lib/core/settings.py | 8 ++- lib/techniques/blind/inference.py | 2 +- lib/utils/deps.py | 2 + lib/utils/hash.py | 1 - plugins/dbms/db2/enumeration.py | 4 +- plugins/dbms/derby/__init__.py | 30 +++++++++ plugins/dbms/derby/connector.py | 62 +++++++++++++++++++ plugins/dbms/derby/enumeration.py | 43 +++++++++++++ plugins/dbms/derby/filesystem.py | 11 ++++ plugins/dbms/derby/fingerprint.py | 94 +++++++++++++++++++++++++++++ plugins/dbms/derby/syntax.py | 18 ++++++ plugins/dbms/derby/takeover.py | 15 +++++ plugins/dbms/monetdb/enumeration.py | 4 ++ plugins/dbms/monetdb/fingerprint.py | 13 ---- plugins/dbms/monetdb/syntax.py | 4 -- plugins/generic/databases.py | 26 ++++---- plugins/generic/entries.py | 10 +-- plugins/generic/search.py | 6 +- sqlmap.py | 5 ++ 26 files changed, 404 insertions(+), 48 deletions(-) create mode 100644 plugins/dbms/derby/__init__.py create mode 100644 plugins/dbms/derby/connector.py create mode 100644 plugins/dbms/derby/enumeration.py create mode 100644 plugins/dbms/derby/filesystem.py create mode 100644 plugins/dbms/derby/fingerprint.py create mode 100644 plugins/dbms/derby/syntax.py create mode 100644 plugins/dbms/derby/takeover.py diff --git a/data/xml/errors.xml b/data/xml/errors.xml index 822722cb0..f32b82734 100644 --- a/data/xml/errors.xml +++ b/data/xml/errors.xml @@ -176,4 +176,11 @@ + + + + + + + diff --git a/data/xml/queries.xml b/data/xml/queries.xml index ccd780474..e26c99dc8 100644 --- a/data/xml/queries.xml +++ b/data/xml/queries.xml @@ -942,4 +942,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/controller/handler.py b/lib/controller/handler.py index 0b430b907..03e5489d3 100644 --- a/lib/controller/handler.py +++ b/lib/controller/handler.py @@ -25,6 +25,7 @@ from lib.core.settings import HSQLDB_ALIASES from lib.core.settings import H2_ALIASES from lib.core.settings import INFORMIX_ALIASES from lib.core.settings import MONETDB_ALIASES +from lib.core.settings import DERBY_ALIASES from lib.utils.sqlalchemy import SQLAlchemy from plugins.dbms.mssqlserver import MSSQLServerMap @@ -55,6 +56,8 @@ from plugins.dbms.informix import InformixMap from plugins.dbms.informix.connector import Connector as InformixConn from plugins.dbms.monetdb import MonetDBMap from plugins.dbms.monetdb.connector import Connector as MonetDBConn +from plugins.dbms.derby import DerbyMap +from plugins.dbms.derby.connector import Connector as DerbyConn def setHandler(): """ @@ -77,6 +80,7 @@ def setHandler(): (DBMS.H2, H2_ALIASES, H2Map, H2Conn), (DBMS.INFORMIX, INFORMIX_ALIASES, InformixMap, InformixConn), (DBMS.MONETDB, MONETDB_ALIASES, MonetDBMap, MonetDBConn), + (DBMS.DERBY, DERBY_ALIASES, DerbyMap, DerbyConn), ] _ = 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 ecf9b26b4..98a0abb2e 100644 --- a/lib/core/agent.py +++ b/lib/core/agent.py @@ -648,7 +648,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): + elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE, DBMS.DB2, DBMS.FIREBIRD, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.DERBY): if fieldsExists: concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1) concatenatedQuery += "||'%s'" % kb.chars.stop @@ -941,6 +941,10 @@ class Agent(object): limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (num, 1) limitedQuery += " %s" % limitStr + elif Backend.getIdentifiedDbms() in (DBMS.DERBY,): + limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (1, num) + limitedQuery += " %s" % limitStr + elif Backend.getIdentifiedDbms() in (DBMS.MONETDB,): if query.startswith("SELECT ") and field is not None and field in query: original = query.split("SELECT ", 1)[1].split(" FROM", 1)[0] diff --git a/lib/core/common.py b/lib/core/common.py index b539f10f3..761f70841 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -40,7 +40,6 @@ import unicodedata from difflib import SequenceMatcher from math import sqrt from optparse import OptionValueError -from xml.dom import minidom from xml.sax import parse from xml.sax import SAXParseException diff --git a/lib/core/dicts.py b/lib/core/dicts.py index 48e8afe13..f02126aac 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 BLANK from lib.core.settings import DB2_ALIASES +from lib.core.settings import DERBY_ALIASES from lib.core.settings import FIREBIRD_ALIASES from lib.core.settings import H2_ALIASES from lib.core.settings import HSQLDB_ALIASES @@ -200,6 +201,7 @@ DBMS_DICT = { DBMS.H2: (H2_ALIASES, None, None, None), DBMS.INFORMIX: (INFORMIX_ALIASES, "python ibm-db", "https://github.com/ibmdb/python-ibmdb", "ibm_db_sa"), DBMS.MONETDB: (MONETDB_ALIASES, "pymonetdb", "https://github.com/gijzelaerr/pymonetdb", "monetdb"), + DBMS.DERBY: (DERBY_ALIASES, "pydrda", "https://github.com/nakagami/pydrda/", None), } FROM_DUMMY_TABLE = { @@ -209,7 +211,8 @@ FROM_DUMMY_TABLE = { DBMS.MAXDB: " FROM VERSIONS", DBMS.DB2: " FROM SYSIBM.SYSDUMMY1", DBMS.HSQLDB: " FROM INFORMATION_SCHEMA.SYSTEM_USERS", - DBMS.INFORMIX: " FROM SYSMASTER:SYSDUAL" + DBMS.INFORMIX: " FROM SYSMASTER:SYSDUAL", + DBMS.DERBY: " FROM SYSIBM.SYSDUMMY1" } SQL_STATEMENTS = { diff --git a/lib/core/enums.py b/lib/core/enums.py index 98bbca1b4..b429cd895 100644 --- a/lib/core/enums.py +++ b/lib/core/enums.py @@ -46,6 +46,7 @@ class DBMS(object): H2 = "H2" INFORMIX = "Informix" MONETDB = "MonetDB" + DERBY = "Apache Derby" class DBMS_DIRECTORY_NAME(object): ACCESS = "access" @@ -62,6 +63,7 @@ class DBMS_DIRECTORY_NAME(object): H2 = "h2" INFORMIX = "informix" MONETDB = "monetdb" + DERBY = "derby" class CUSTOM_LOGGING(object): PAYLOAD = 9 diff --git a/lib/core/settings.py b/lib/core/settings.py index ffe39f523..b4c572ad8 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.1.28" +VERSION = "1.4.1.29" 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) @@ -259,6 +259,7 @@ HSQLDB_SYSTEM_DBS = ("INFORMATION_SCHEMA", "SYSTEM_LOB") H2_SYSTEM_DBS = ("INFORMATION_SCHEMA",) INFORMIX_SYSTEM_DBS = ("sysmaster", "sysutils", "sysuser", "sysadmin") MONETDB_SYSTEM_DBS = ("tmp", "json", "profiler") +DERBY_SYSTEM_DBS = ("NULLID", "SQLJ", "SYS", "SYSCAT", "SYSCS_DIAG", "SYSCS_UTIL", "SYSFUN", "SYSIBM", "SYSPROC", "SYSSTAT") MSSQL_ALIASES = ("microsoft sql server", "mssqlserver", "mssql", "ms") MYSQL_ALIASES = ("mysql", "my", "mariadb", "maria") @@ -274,13 +275,14 @@ HSQLDB_ALIASES = ("hsql", "hsqldb", "hs", "hypersql") H2_ALIASES = ("h2",) INFORMIX_ALIASES = ("informix", "ibm informix", "ibminformix") MONETDB_ALIASES = ("monet", "monetdb",) +DERBY_ALIASES = ("derby", "apache derby",) 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 +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 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_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)) USER_AGENT_ALIASES = ("ua", "useragent", "user-agent") REFERER_ALIASES = ("ref", "referer", "referrer") diff --git a/lib/techniques/blind/inference.py b/lib/techniques/blind/inference.py index 063ad7334..37853748f 100644 --- a/lib/techniques/blind/inference.py +++ b/lib/techniques/blind/inference.py @@ -642,7 +642,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None dataToStdout(filterControlChars(val)) # some DBMSes (e.g. Firebird, DB2, etc.) have issues with trailing spaces - if Backend.getIdentifiedDbms() in (DBMS.FIREBIRD, DBMS.DB2, DBMS.MAXDB) and len(partialValue) > INFERENCE_BLANK_BREAK and partialValue[-INFERENCE_BLANK_BREAK:].isspace(): + if Backend.getIdentifiedDbms() in (DBMS.FIREBIRD, DBMS.DB2, DBMS.MAXDB, DBMS.DERBY) and len(partialValue) > INFERENCE_BLANK_BREAK and partialValue[-INFERENCE_BLANK_BREAK:].isspace(): finalValue = partialValue[:-INFERENCE_BLANK_BREAK] break elif charsetType and partialValue[-1:].isspace(): diff --git a/lib/utils/deps.py b/lib/utils/deps.py index 66225198a..8583e77a6 100644 --- a/lib/utils/deps.py +++ b/lib/utils/deps.py @@ -48,6 +48,8 @@ def checkDependencies(): __import__("ibm_db_dbi") elif dbmsName == DBMS.MONETDB: __import__("pymonetdb") + elif dbmsName == DBMS.DERBY: + __import__("drda") except: warnMsg = "sqlmap requires '%s' third-party library " % data[1] warnMsg += "in order to directly connect to the DBMS " diff --git a/lib/utils/hash.py b/lib/utils/hash.py index 19b6b021a..70b008e79 100644 --- a/lib/utils/hash.py +++ b/lib/utils/hash.py @@ -33,7 +33,6 @@ else: import base64 import binascii import gc -import hashlib import os import re import tempfile diff --git a/plugins/dbms/db2/enumeration.py b/plugins/dbms/db2/enumeration.py index 35cd69a37..d2235b0f5 100644 --- a/plugins/dbms/db2/enumeration.py +++ b/plugins/dbms/db2/enumeration.py @@ -10,13 +10,13 @@ from plugins.generic.enumeration import Enumeration as GenericEnumeration class Enumeration(GenericEnumeration): def getPasswordHashes(self): - warnMsg = "on DB2 it is not possible to enumerate password hashes" + warnMsg = "on IBM DB2 it is not possible to enumerate password hashes" logger.warn(warnMsg) return {} def getStatements(self): - warnMsg = "on DB2 it is not possible to enumerate the SQL statements" + warnMsg = "on IBM DB2 it is not possible to enumerate the SQL statements" logger.warn(warnMsg) return [] diff --git a/plugins/dbms/derby/__init__.py b/plugins/dbms/derby/__init__.py new file mode 100644 index 000000000..56a2776b4 --- /dev/null +++ b/plugins/dbms/derby/__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 DERBY_SYSTEM_DBS +from lib.core.unescaper import unescaper + +from plugins.dbms.derby.enumeration import Enumeration +from plugins.dbms.derby.filesystem import Filesystem +from plugins.dbms.derby.fingerprint import Fingerprint +from plugins.dbms.derby.syntax import Syntax +from plugins.dbms.derby.takeover import Takeover +from plugins.generic.misc import Miscellaneous + +class DerbyMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover): + """ + This class defines Apache Derby methods + """ + + def __init__(self): + self.excludeDbsList = DERBY_SYSTEM_DBS + + for cls in self.__class__.__bases__: + cls.__init__(self) + + unescaper[DBMS.DERBY] = Syntax.escape diff --git a/plugins/dbms/derby/connector.py b/plugins/dbms/derby/connector.py new file mode 100644 index 000000000..3cfbff1ff --- /dev/null +++ b/plugins/dbms/derby/connector.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/) +See the file 'LICENSE' for copying permission +""" + +try: + import drda +except: + pass + +import logging + +from lib.core.common import getSafeExString +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://github.com/nakagami/pydrda/ + User guide: https://github.com/nakagami/pydrda/blob/master/README.rst + API: https://www.python.org/dev/peps/pep-0249/ + License: MIT + """ + + def connect(self): + self.initConnection() + + try: + self.connector = drda.connect(host=self.hostname, database=self.db, port=self.port) + except drda.OperationalError as ex: + raise SqlmapConnectionException(getSafeExString(ex)) + + self.initCursor() + self.printConnected() + + def fetchall(self): + try: + return self.cursor.fetchall() + except drda.ProgrammingError as ex: + logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % getSafeExString(ex)) + return None + + def execute(self, query): + try: + self.cursor.execute(query) + except (drda.OperationalError, drda.ProgrammingError) as ex: + logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % getSafeExString(ex)) + except drda.InternalError as ex: + raise SqlmapConnectionException(getSafeExString(ex)) + + try: + self.connector.commit() + except drda.OperationalError: + pass + + def select(self, query): + self.execute(query) + return self.fetchall() diff --git a/plugins/dbms/derby/enumeration.py b/plugins/dbms/derby/enumeration.py new file mode 100644 index 000000000..4a64c197c --- /dev/null +++ b/plugins/dbms/derby/enumeration.py @@ -0,0 +1,43 @@ +#!/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 singleTimeWarnMessage +from lib.core.data import logger +from plugins.generic.enumeration import Enumeration as GenericEnumeration + +class Enumeration(GenericEnumeration): + def getPasswordHashes(self): + warnMsg = "on MonetDB it is not possible to enumerate password hashes" + logger.warn(warnMsg) + + return {} + + def getStatements(self): + warnMsg = "on Apache Derby it is not possible to enumerate the SQL statements" + logger.warn(warnMsg) + + return [] + + def getPrivileges(self, *args, **kwargs): + warnMsg = "on Apache Derby it is not possible to enumerate the user privileges" + logger.warn(warnMsg) + + return {} + + def getRoles(self, *args, **kwargs): + warnMsg = "on Apache Derby it is not possible to enumerate the user roles" + logger.warn(warnMsg) + + return {} + + def getHostname(self): + warnMsg = "on Apache Derby it is not possible to enumerate the hostname" + logger.warn(warnMsg) + + def getBanner(self): + warnMsg = "on Apache Derby it is not possible to enumerate the banner" + singleTimeWarnMessage(warnMsg) diff --git a/plugins/dbms/derby/filesystem.py b/plugins/dbms/derby/filesystem.py new file mode 100644 index 000000000..e8c642492 --- /dev/null +++ b/plugins/dbms/derby/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/derby/fingerprint.py b/plugins/dbms/derby/fingerprint.py new file mode 100644 index 000000000..ae9fe9422 --- /dev/null +++ b/plugins/dbms/derby/fingerprint.py @@ -0,0 +1,94 @@ +#!/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 DERBY_ALIASES +from lib.request import inject +from plugins.generic.fingerprint import Fingerprint as GenericFingerprint + +class Fingerprint(GenericFingerprint): + def __init__(self): + GenericFingerprint.__init__(self, DBMS.DERBY) + + 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.DERBY + 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(DERBY_ALIASES): + setDbms(DBMS.DERBY) + + self.getBanner() + + return True + + infoMsg = "testing %s" % DBMS.DERBY + logger.info(infoMsg) + + result = inject.checkBooleanExpression("[RANDNUM]=(SELECT [RANDNUM] FROM SYSIBM.SYSDUMMY1 {LIMIT 1 OFFSET 0})") + + if result: + infoMsg = "confirming %s" % DBMS.DERBY + logger.info(infoMsg) + + result = inject.checkBooleanExpression("(SELECT CURRENT SCHEMA FROM SYSIBM.SYSDUMMY1) IS NOT NULL") + + if not result: + warnMsg = "the back-end DBMS is not %s" % DBMS.DERBY + logger.warn(warnMsg) + + return False + + setDbms(DBMS.DERBY) + + self.getBanner() + + return True + else: + warnMsg = "the back-end DBMS is not %s" % DBMS.DERBY + logger.warn(warnMsg) + + return False diff --git a/plugins/dbms/derby/syntax.py b/plugins/dbms/derby/syntax.py new file mode 100644 index 000000000..dc6c66174 --- /dev/null +++ b/plugins/dbms/derby/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/derby/takeover.py b/plugins/dbms/derby/takeover.py new file mode 100644 index 000000000..432fa6f78 --- /dev/null +++ b/plugins/dbms/derby/takeover.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 plugins.generic.takeover import Takeover as GenericTakeover + +class Takeover(GenericTakeover): + def __init__(self): + self.__basedir = None + self.__datadir = None + + GenericTakeover.__init__(self) diff --git a/plugins/dbms/monetdb/enumeration.py b/plugins/dbms/monetdb/enumeration.py index 9d2d2ffe7..c798ce012 100644 --- a/plugins/dbms/monetdb/enumeration.py +++ b/plugins/dbms/monetdb/enumeration.py @@ -32,3 +32,7 @@ class Enumeration(GenericEnumeration): logger.warn(warnMsg) return {} + + def getHostname(self): + warnMsg = "on MonetDB it is not possible to enumerate the hostname" + logger.warn(warnMsg) diff --git a/plugins/dbms/monetdb/fingerprint.py b/plugins/dbms/monetdb/fingerprint.py index 5b1cefd5b..07eaa609c 100644 --- a/plugins/dbms/monetdb/fingerprint.py +++ b/plugins/dbms/monetdb/fingerprint.py @@ -86,19 +86,6 @@ class Fingerprint(GenericFingerprint): self.getBanner() - if not conf.extensiveFp: - return True - - infoMsg = "actively fingerprinting %s" % DBMS.MONETDB - logger.info(infoMsg) - - for version in ("14.1", "12.1", "11.7", "11.5", "10.0"): - output = inject.checkBooleanExpression("EXISTS(SELECT 1 FROM SYSMASTER:SYSDUAL WHERE DBINFO('VERSION,'FULL') LIKE '%%%s%%')" % version) - - if output: - Backend.setVersion(version) - break - return True else: warnMsg = "the back-end DBMS is not %s" % DBMS.MONETDB diff --git a/plugins/dbms/monetdb/syntax.py b/plugins/dbms/monetdb/syntax.py index 28701778f..42e969858 100644 --- a/plugins/dbms/monetdb/syntax.py +++ b/plugins/dbms/monetdb/syntax.py @@ -5,10 +5,6 @@ Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/) See the file 'LICENSE' for copying permission """ -import re - -from lib.core.common import isDBMSVersionAtLeast -from lib.core.common import randomStr from lib.core.convert import getOrds from plugins.generic.syntax import Syntax as GenericSyntax diff --git a/plugins/generic/databases.py b/plugins/generic/databases.py index d2387d1a8..1ad769275 100644 --- a/plugins/generic/databases.py +++ b/plugins/generic/databases.py @@ -97,7 +97,7 @@ class Databases(object): warnMsg += "names will be fetched from 'mysql' database" logger.warn(warnMsg) - elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.PGSQL): + elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.PGSQL, DBMS.DERBY): 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" @@ -221,7 +221,7 @@ class Databases(object): if conf.db == CURRENT_DB: conf.db = self.getCurrentDb() - if conf.db and Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB): + if conf.db and Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB, DBMS.DERBY): conf.db = conf.db.upper() if conf.db: @@ -308,7 +308,7 @@ class Databases(object): if conf.getComments: _ = queries[Backend.getIdentifiedDbms()].table_comment if hasattr(_, "query"): - if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): + if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY): query = _.query % (unsafeSQLIdentificatorNaming(db.upper()), unsafeSQLIdentificatorNaming(table.upper())) else: query = _.query % (unsafeSQLIdentificatorNaming(db), unsafeSQLIdentificatorNaming(table)) @@ -390,7 +390,7 @@ class Databases(object): if conf.getComments: _ = queries[Backend.getIdentifiedDbms()].table_comment if hasattr(_, "query"): - if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): + if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY): query = _.query % (unsafeSQLIdentificatorNaming(db.upper()), unsafeSQLIdentificatorNaming(table.upper())) else: query = _.query % (unsafeSQLIdentificatorNaming(db), unsafeSQLIdentificatorNaming(table)) @@ -450,7 +450,7 @@ class Databases(object): raise SqlmapNoneDataException(errMsg) elif conf.db is not None: - if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB, DBMS.H2): + if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.DERBY): conf.db = conf.db.upper() if ',' in conf.db: @@ -461,7 +461,7 @@ class Databases(object): conf.db = safeSQLIdentificatorNaming(conf.db) if conf.col: - if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): + if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY): conf.col = conf.col.upper() colList = conf.col.split(',') @@ -477,7 +477,7 @@ class Databases(object): colList = [_ for _ in colList if _] if conf.tbl: - if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB, DBMS.H2): + if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.DERBY): conf.tbl = conf.tbl.upper() tblList = conf.tbl.split(',') @@ -585,7 +585,7 @@ class Databases(object): query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db)) query += condQuery - elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): + elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY): query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl.upper()), unsafeSQLIdentificatorNaming(conf.db.upper())) query += condQuery @@ -661,7 +661,7 @@ class Databases(object): if conf.getComments: _ = queries[Backend.getIdentifiedDbms()].column_comment if hasattr(_, "query"): - if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): + if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY): query = _.query % (unsafeSQLIdentificatorNaming(conf.db.upper()), unsafeSQLIdentificatorNaming(tbl.upper()), unsafeSQLIdentificatorNaming(name.upper())) else: query = _.query % (unsafeSQLIdentificatorNaming(conf.db), unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(name)) @@ -727,7 +727,7 @@ class Databases(object): query = rootQuery.blind.count % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db)) query += condQuery - elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): + elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY): query = rootQuery.blind.count % (unsafeSQLIdentificatorNaming(tbl.upper()), unsafeSQLIdentificatorNaming(conf.db.upper())) query += condQuery @@ -801,7 +801,7 @@ class Databases(object): elif Backend.isDbms(DBMS.MONETDB): query = safeStringFormat(rootQuery.blind.query, (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db), index)) field = None - elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): + elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY): query = rootQuery.blind.query % (unsafeSQLIdentificatorNaming(tbl.upper()), unsafeSQLIdentificatorNaming(conf.db.upper())) query += condQuery field = None @@ -825,7 +825,7 @@ class Databases(object): if conf.getComments: _ = queries[Backend.getIdentifiedDbms()].column_comment if hasattr(_, "query"): - if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): + if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY): query = _.query % (unsafeSQLIdentificatorNaming(conf.db.upper()), unsafeSQLIdentificatorNaming(tbl.upper()), unsafeSQLIdentificatorNaming(column.upper())) else: query = _.query % (unsafeSQLIdentificatorNaming(conf.db), unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(column)) @@ -842,7 +842,7 @@ class Databases(object): if not onlyColNames: 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): + elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY): query = rootQuery.blind.query2 % (unsafeSQLIdentificatorNaming(tbl.upper()), column, unsafeSQLIdentificatorNaming(conf.db.upper())) elif Backend.isDbms(DBMS.MSSQL): query = rootQuery.blind.query2 % (conf.db, conf.db, conf.db, conf.db, column, conf.db, conf.db, conf.db, unsafeSQLIdentificatorNaming(tbl).split(".")[-1]) diff --git a/plugins/generic/entries.py b/plugins/generic/entries.py index 7c978a3ba..ad0ae9003 100644 --- a/plugins/generic/entries.py +++ b/plugins/generic/entries.py @@ -70,7 +70,7 @@ class Entries(object): conf.db = self.getCurrentDb() elif conf.db is not None: - if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB, DBMS.H2): + if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.DERBY): conf.db = conf.db.upper() if ',' in conf.db: @@ -86,7 +86,7 @@ class Entries(object): conf.db = safeSQLIdentificatorNaming(conf.db) if conf.tbl: - if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB, DBMS.H2): + if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.DERBY): conf.tbl = conf.tbl.upper() tblList = conf.tbl.split(',') @@ -176,7 +176,7 @@ class Entries(object): entries = [] query = None - if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): + if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY): 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): query = rootQuery.inband.query % (colString, tbl) @@ -285,7 +285,7 @@ class Entries(object): infoMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db) logger.info(infoMsg) - if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): + if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY): 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): query = rootQuery.blind.count % tbl @@ -407,7 +407,7 @@ class Entries(object): 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): + elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY): 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.isDbms(DBMS.SQLITE): query = rootQuery.blind.query % (agent.preprocessField(tbl, column), tbl, index) diff --git a/plugins/generic/search.py b/plugins/generic/search.py index c2a680afa..8da8c6786 100644 --- a/plugins/generic/search.py +++ b/plugins/generic/search.py @@ -63,7 +63,7 @@ class Search(object): values = [] db = safeSQLIdentificatorNaming(db) - if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB, DBMS.H2): + if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.DERBY): db = db.upper() infoMsg = "searching database" @@ -170,7 +170,7 @@ class Search(object): values = [] tbl = safeSQLIdentificatorNaming(tbl, True) - if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.FIREBIRD, DBMS.HSQLDB, DBMS.H2): + if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.FIREBIRD, DBMS.HSQLDB, DBMS.H2, DBMS.DERBY): tbl = tbl.upper() conf.db = conf.db.upper() if conf.db else conf.db @@ -393,7 +393,7 @@ class Search(object): conf.db = origDb conf.tbl = origTbl - if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB, DBMS.H2): + if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.DERBY): column = column.upper() conf.db = conf.db.upper() if conf.db else conf.db conf.tbl = conf.tbl.upper() if conf.tbl else conf.tbl diff --git a/sqlmap.py b/sqlmap.py index 8269e665e..afa894791 100755 --- a/sqlmap.py +++ b/sqlmap.py @@ -351,6 +351,11 @@ def main(): logger.critical(errMsg) raise SystemExit + elif all(_ in excMsg for _ in ("drda", "to_bytes")): + errMsg = "wrong initialization of drda detected (using Python3 syntax)" + logger.critical(errMsg) + raise SystemExit + elif all(_ in excMsg for _ in ("window = tkinter.Tk()",)): errMsg = "there has been a problem in initialization of GUI interface " errMsg += "('%s')" % excMsg.strip().split('\n')[-1]