diff --git a/data/xml/errors.xml b/data/xml/errors.xml index 29bb39a2d..de6786dc9 100644 --- a/data/xml/errors.xml +++ b/data/xml/errors.xml @@ -223,4 +223,12 @@ + + + + + + + + diff --git a/data/xml/queries.xml b/data/xml/queries.xml index 75a6f4b53..ff824b87e 100644 --- a/data/xml/queries.xml +++ b/data/xml/queries.xml @@ -1665,4 +1665,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/controller/handler.py b/lib/controller/handler.py index a54a13140..79364c103 100644 --- a/lib/controller/handler.py +++ b/lib/controller/handler.py @@ -37,6 +37,7 @@ from lib.core.settings import RAIMA_ALIASES from lib.core.settings import SQLITE_ALIASES from lib.core.settings import SYBASE_ALIASES from lib.core.settings import VERTICA_ALIASES +from lib.core.settings import VIRTUOSO_ALIASES from lib.utils.sqlalchemy import SQLAlchemy from plugins.dbms.access.connector import Connector as AccessConn @@ -91,6 +92,8 @@ from plugins.dbms.sybase.connector import Connector as SybaseConn from plugins.dbms.sybase import SybaseMap from plugins.dbms.vertica.connector import Connector as VerticaConn from plugins.dbms.vertica import VerticaMap +from plugins.dbms.virtuoso.connector import Connector as VirtuosoConn +from plugins.dbms.virtuoso import VirtuosoMap def setHandler(): """ @@ -125,6 +128,7 @@ def setHandler(): (DBMS.EXTREMEDB, EXTREMEDB_ALIASES, ExtremeDBMap, ExtremeDBConn), (DBMS.FRONTBASE, FRONTBASE_ALIASES, FrontBaseMap, FrontBaseConn), (DBMS.RAIMA, RAIMA_ALIASES, RaimaMap, RaimaConn), + (DBMS.VIRTUOSO, VIRTUOSO_ALIASES, VirtuosoMap, VirtuosoConn), ] _ = 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 d0df1a1cc..82d78febf 100644 --- a/lib/core/agent.py +++ b/lib/core/agent.py @@ -699,7 +699,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, DBMS.EXTREMEDB, DBMS.FRONTBASE, DBMS.RAIMA): + 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, DBMS.FRONTBASE, DBMS.RAIMA, DBMS.VIRTUOSO): if fieldsExists: concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1) concatenatedQuery += "||'%s'" % kb.chars.stop @@ -1021,7 +1021,7 @@ class Agent(object): limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (1, num) limitedQuery += " %s" % limitStr - elif Backend.getIdentifiedDbms() in (DBMS.FRONTBASE,): + elif Backend.getIdentifiedDbms() in (DBMS.FRONTBASE, DBMS.VIRTUOSO): limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (num, 1) if query.startswith("SELECT "): limitedQuery = query.replace("SELECT ", "SELECT %s " % limitStr, 1) diff --git a/lib/core/common.py b/lib/core/common.py index aead6ab6c..91dd82df7 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -4200,7 +4200,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, DBMS.EXTREMEDB, DBMS.FRONTBASE, DBMS.RAIMA): + 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, DBMS.FRONTBASE, DBMS.RAIMA, DBMS.VIRTUOSO): retVal = "\"%s\"" % retVal elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.ALTIBASE, DBMS.MIMERSQL): retVal = "\"%s\"" % retVal.upper() @@ -4238,7 +4238,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, DBMS.EXTREMEDB, DBMS.FRONTBASE, DBMS.RAIMA): + 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, DBMS.FRONTBASE, DBMS.RAIMA, DBMS.VIRTUOSO): 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 27077f08f..89a9eee41 100644 --- a/lib/core/dicts.py +++ b/lib/core/dicts.py @@ -37,6 +37,7 @@ from lib.core.settings import RAIMA_ALIASES from lib.core.settings import SQLITE_ALIASES from lib.core.settings import SYBASE_ALIASES from lib.core.settings import VERTICA_ALIASES +from lib.core.settings import VIRTUOSO_ALIASES FIREBIRD_TYPES = { 261: "BLOB", @@ -246,6 +247,7 @@ DBMS_DICT = { DBMS.EXTREMEDB: (EXTREMEDB_ALIASES, None, None, None), DBMS.FRONTBASE: (FRONTBASE_ALIASES, None, None, None), DBMS.RAIMA: (RAIMA_ALIASES, None, None, None), + DBMS.VIRTUOSO: (VIRTUOSO_ALIASES, None, None, None), } # Reference: https://blog.jooq.org/tag/sysibm-sysdummy1/ @@ -283,6 +285,7 @@ HEURISTIC_NULL_EVAL = { DBMS.CACHE: "%SQLUPPER NULL", DBMS.EXTREMEDB: "NULLIFZERO(hashcode(NULL))", DBMS.RAIMA: "IF(ROWNUMBER()>0,CONVERT(NULL,TINYINT),NULL))", + DBMS.VIRTUOSO: "__MAX_NOTNULL(NULL)", } SQL_STATEMENTS = { diff --git a/lib/core/dump.py b/lib/core/dump.py index 89d4b0ac0..b21473a1a 100644 --- a/lib/core/dump.py +++ b/lib/core/dump.py @@ -166,7 +166,7 @@ class Dump(object): def currentDb(self, data): if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.VERTICA, DBMS.CRATEDB, DBMS.CACHE, DBMS.FRONTBASE): self.string("current database (equivalent to schema on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB) - elif Backend.getIdentifiedDbms() in (DBMS.ALTIBASE, DBMS.DB2, DBMS.MIMERSQL, DBMS.MAXDB): + elif Backend.getIdentifiedDbms() in (DBMS.ALTIBASE, DBMS.DB2, DBMS.MIMERSQL, DBMS.MAXDB, DBMS.VIRTUOSO): self.string("current database (equivalent to owner on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB) else: self.string("current database", data, content_type=CONTENT_TYPE.CURRENT_DB) diff --git a/lib/core/enums.py b/lib/core/enums.py index 9423c499f..e693b6e31 100644 --- a/lib/core/enums.py +++ b/lib/core/enums.py @@ -58,6 +58,7 @@ class DBMS(object): EXTREMEDB = "eXtremeDB" FRONTBASE = "FrontBase" RAIMA = "Raima Database Manager" + VIRTUOSO = "Virtuoso" class DBMS_DIRECTORY_NAME(object): ACCESS = "access" @@ -86,6 +87,7 @@ class DBMS_DIRECTORY_NAME(object): EXTREMEDB = "extremedb" FRONTBASE = "frontbase" RAIMA = "raima" + VIRTUOSO = "virtuoso" class FORK(object): MARIADB = "MariaDB" diff --git a/lib/core/settings.py b/lib/core/settings.py index 8211bd917..3d93b5a7f 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -283,6 +283,7 @@ CACHE_SYSTEM_DBS = ("%Dictionary", "INFORMATION_SCHEMA", "%SYS") EXTREMEDB_SYSTEM_DBS = ("",) FRONTBASE_SYSTEM_DBS = ("DEFINITION_SCHEMA", "INFORMATION_SCHEMA") RAIMA_SYSTEM_DBS = ("",) +VIRTUOSO_SYSTEM_DBS = ("",) # Note: () + () MSSQL_ALIASES = ("microsoft sql server", "mssqlserver", "mssql", "ms") @@ -311,13 +312,14 @@ CACHE_ALIASES = ("intersystems cache", "cachedb", "cache") EXTREMEDB_ALIASES = ("extremedb", "extreme") FRONTBASE_ALIASES = ("frontbase",) RAIMA_ALIASES = ("raima database manager", "raima", "raimadb", "raimadm", "rdm", "rds", "velocis") +VIRTUOSO_ALIASES = ("virtuoso", "openlink virtuoso") DBMS_DIRECTORY_DICT = dict((getattr(DBMS, _), getattr(DBMS_DIRECTORY_NAME, _)) for _ in dir(DBMS) if not _.startswith("_")) -SUPPORTED_DBMS = set(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 + RAIMA_ALIASES) +SUPPORTED_DBMS = set(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 + RAIMA_ALIASES + VIRTUOSO_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.EXTREMEDB, EXTREMEDB_ALIASES), (DBMS.FRONTBASE, FRONTBASE_ALIASES), (DBMS.RAIMA, RAIMA_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), (DBMS.FRONTBASE, FRONTBASE_ALIASES), (DBMS.RAIMA, RAIMA_ALIASES), (DBMS.VIRTUOSO, VIRTUOSO_ALIASES)) USER_AGENT_ALIASES = ("ua", "useragent", "user-agent") REFERER_ALIASES = ("ref", "referer", "referrer") diff --git a/plugins/dbms/virtuoso/__init__.py b/plugins/dbms/virtuoso/__init__.py new file mode 100644 index 000000000..7e7ae0677 --- /dev/null +++ b/plugins/dbms/virtuoso/__init__.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2021 sqlmap developers (http://sqlmap.org/) +See the file 'LICENSE' for copying permission +""" + +from lib.core.enums import DBMS +from lib.core.settings import VIRTUOSO_SYSTEM_DBS +from lib.core.unescaper import unescaper +from plugins.dbms.virtuoso.enumeration import Enumeration +from plugins.dbms.virtuoso.filesystem import Filesystem +from plugins.dbms.virtuoso.fingerprint import Fingerprint +from plugins.dbms.virtuoso.syntax import Syntax +from plugins.dbms.virtuoso.takeover import Takeover +from plugins.generic.misc import Miscellaneous + +class VirtuosoMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover): + """ + This class defines Virtuoso methods + """ + + def __init__(self): + self.excludeDbsList = VIRTUOSO_SYSTEM_DBS + + for cls in self.__class__.__bases__: + cls.__init__(self) + + unescaper[DBMS.VIRTUOSO] = Syntax.escape diff --git a/plugins/dbms/virtuoso/connector.py b/plugins/dbms/virtuoso/connector.py new file mode 100644 index 000000000..4724e7a78 --- /dev/null +++ b/plugins/dbms/virtuoso/connector.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2021 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 Virtuoso it is not (currently) possible to establish a " + errMsg += "direct connection" + raise SqlmapUnsupportedFeatureException(errMsg) diff --git a/plugins/dbms/virtuoso/enumeration.py b/plugins/dbms/virtuoso/enumeration.py new file mode 100644 index 000000000..1bce85ade --- /dev/null +++ b/plugins/dbms/virtuoso/enumeration.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2021 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 getPasswordHashes(self): + warnMsg = "on Virtuoso it is not possible to enumerate the user password hashes" + logger.warn(warnMsg) + + return {} + + def getPrivileges(self, *args, **kwargs): + warnMsg = "on Virtuoso it is not possible to enumerate the user privileges" + logger.warn(warnMsg) + + return {} + + def getRoles(self, *args, **kwargs): + warnMsg = "on Virtuoso it is not possible to enumerate the user roles" + logger.warn(warnMsg) + + return {} + + def searchDb(self): + warnMsg = "on Virtuoso it is not possible to search databases" + logger.warn(warnMsg) + + return [] + + def searchTable(self): + warnMsg = "on Virtuoso it is not possible to search tables" + logger.warn(warnMsg) + + return [] + + def searchColumn(self): + warnMsg = "on Virtuoso it is not possible to search columns" + logger.warn(warnMsg) + + return [] + + def search(self): + warnMsg = "on Virtuoso search option is not available" + logger.warn(warnMsg) + + def getStatements(self): + warnMsg = "on Virtuoso it is not possible to enumerate the SQL statements" + logger.warn(warnMsg) + + return [] diff --git a/plugins/dbms/virtuoso/filesystem.py b/plugins/dbms/virtuoso/filesystem.py new file mode 100644 index 000000000..1e4dd8aa1 --- /dev/null +++ b/plugins/dbms/virtuoso/filesystem.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2021 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 Virtuoso it is not possible to read files" + raise SqlmapUnsupportedFeatureException(errMsg) + + def writeFile(self, localFile, remoteFile, fileType=None, forceCheck=False): + errMsg = "on Virtuoso it is not possible to write files" + raise SqlmapUnsupportedFeatureException(errMsg) diff --git a/plugins/dbms/virtuoso/fingerprint.py b/plugins/dbms/virtuoso/fingerprint.py new file mode 100644 index 000000000..a88208588 --- /dev/null +++ b/plugins/dbms/virtuoso/fingerprint.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2021 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 VIRTUOSO_ALIASES +from lib.request import inject +from plugins.generic.fingerprint import Fingerprint as GenericFingerprint + +class Fingerprint(GenericFingerprint): + def __init__(self): + GenericFingerprint.__init__(self, DBMS.VIRTUOSO) + + 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.VIRTUOSO + 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(VIRTUOSO_ALIASES): + setDbms(DBMS.VIRTUOSO) + return True + + infoMsg = "testing %s" % DBMS.VIRTUOSO + logger.info(infoMsg) + + result = inject.checkBooleanExpression("GET_KEYWORD(NULL,NULL) IS NULL") + + if result: + infoMsg = "confirming %s" % DBMS.VIRTUOSO + logger.info(infoMsg) + + result = inject.checkBooleanExpression("RDF_NOW_IMPL() IS NOT NULL") + + if not result: + warnMsg = "the back-end DBMS is not %s" % DBMS.VIRTUOSO + logger.warn(warnMsg) + + return False + + setDbms(DBMS.VIRTUOSO) + + return True + else: + warnMsg = "the back-end DBMS is not %s" % DBMS.VIRTUOSO + logger.warn(warnMsg) + + return False diff --git a/plugins/dbms/virtuoso/syntax.py b/plugins/dbms/virtuoso/syntax.py new file mode 100644 index 000000000..f59b9cb9c --- /dev/null +++ b/plugins/dbms/virtuoso/syntax.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2021 sqlmap developers (http://sqlmap.org/) +See the file 'LICENSE' for copying permission +""" + +from lib.core.convert import getOrds +from plugins.generic.syntax import Syntax as GenericSyntax + +class Syntax(GenericSyntax): + @staticmethod + def escape(expression, quote=True): + """ + >>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") == "SELECT CHR(97)||CHR(98)||CHR(99)||CHR(100)||CHR(101)||CHR(102)||CHR(103)||CHR(104) FROM foobar" + True + """ + + def escaper(value): + return "||".join("CHR(%d)" % _ for _ in getOrds(value)) + + return Syntax._escape(expression, quote, escaper) diff --git a/plugins/dbms/virtuoso/takeover.py b/plugins/dbms/virtuoso/takeover.py new file mode 100644 index 000000000..1ddcd068a --- /dev/null +++ b/plugins/dbms/virtuoso/takeover.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2006-2021 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 Virtuoso it is not possible to execute commands" + raise SqlmapUnsupportedFeatureException(errMsg) + + def osShell(self): + errMsg = "on Virtuoso it is not possible to execute commands" + raise SqlmapUnsupportedFeatureException(errMsg) + + def osPwn(self): + errMsg = "on Virtuoso it is not possible to establish an " + errMsg += "out-of-band connection" + raise SqlmapUnsupportedFeatureException(errMsg) + + def osSmb(self): + errMsg = "on Virtuoso 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 58ee2fb00..02a6d2fd2 100644 --- a/plugins/generic/databases.py +++ b/plugins/generic/databases.py @@ -398,7 +398,7 @@ class Databases(object): 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 - elif Backend.getIdentifiedDbms() in (DBMS.HSQLDB, DBMS.INFORMIX, DBMS.FRONTBASE): + elif Backend.getIdentifiedDbms() in (DBMS.HSQLDB, DBMS.INFORMIX, DBMS.FRONTBASE, DBMS.VIRTUOSO): query = rootQuery.blind.query % (index, unsafeSQLIdentificatorNaming(db)) else: query = rootQuery.blind.query % (unsafeSQLIdentificatorNaming(db), index) @@ -614,7 +614,7 @@ class Databases(object): condQueryStr = "%%s%s" % colCondParam condQuery = " AND (%s)" % " OR ".join(condQueryStr % (condition, unsafeSQLIdentificatorNaming(col)) for col in sorted(colList)) - if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CUBRID, DBMS.CACHE, DBMS.FRONTBASE): + if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CUBRID, DBMS.CACHE, DBMS.FRONTBASE, DBMS.VIRTUOSO): query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db)) query += condQuery @@ -750,7 +750,7 @@ class Databases(object): condQueryStr = "%%s%s" % colCondParam condQuery = " AND (%s)" % " OR ".join(condQueryStr % (condition, unsafeSQLIdentificatorNaming(col)) for col in sorted(colList)) - if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CUBRID, DBMS.CACHE, DBMS.FRONTBASE): + if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CUBRID, DBMS.CACHE, DBMS.FRONTBASE, DBMS.VIRTUOSO): query = rootQuery.blind.count % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db)) query += condQuery @@ -819,7 +819,7 @@ class Databases(object): continue for index in getLimitRange(count): - if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CUBRID, DBMS.CACHE, DBMS.FRONTBASE): + if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CUBRID, DBMS.CACHE, DBMS.FRONTBASE, DBMS.VIRTUOSO): query = rootQuery.blind.query % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db)) query += condQuery field = None @@ -873,7 +873,7 @@ class Databases(object): singleTimeWarnMessage(warnMsg) if not onlyColNames: - if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CACHE, DBMS.FRONTBASE): + if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CACHE, DBMS.FRONTBASE, DBMS.VIRTUOSO): query = rootQuery.blind.query2 % (unsafeSQLIdentificatorNaming(tbl), column, unsafeSQLIdentificatorNaming(conf.db)) elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE, DBMS.MIMERSQL): query = rootQuery.blind.query2 % (unsafeSQLIdentificatorNaming(tbl.upper()), column, unsafeSQLIdentificatorNaming(conf.db.upper())) diff --git a/plugins/generic/entries.py b/plugins/generic/entries.py index 3cb50a0fd..1ab3ce7e4 100644 --- a/plugins/generic/entries.py +++ b/plugins/generic/entries.py @@ -239,7 +239,7 @@ class Entries(object): entries = BigArray(_zip(*[entries[colName] for colName in colList])) else: query = rootQuery.inband.query % (colString, conf.db, tbl) - elif Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CACHE): + elif Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CACHE, DBMS.VIRTUOSO): query = rootQuery.inband.query % (colString, conf.db, tbl, prioritySortColumns(colList)[0]) else: query = rootQuery.inband.query % (colString, conf.db, tbl) @@ -418,7 +418,7 @@ class Entries(object): 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) - elif Backend.isDbms(DBMS.INFORMIX): + elif Backend.getIdentifiedDbms() in (DBMS.INFORMIX, DBMS.VIRTUOSO): query = rootQuery.blind.query % (index, agent.preprocessField(tbl, column), conf.db, tbl, sorted(colList, key=len)[0]) elif Backend.isDbms(DBMS.FRONTBASE): query = rootQuery.blind.query % (index, agent.preprocessField(tbl, column), conf.db, tbl) diff --git a/plugins/generic/users.py b/plugins/generic/users.py index e21cfe4c1..a8fa76ee4 100644 --- a/plugins/generic/users.py +++ b/plugins/generic/users.py @@ -276,7 +276,7 @@ class Users(object): if user in retrievedUsers: continue - if Backend.isDbms(DBMS.INFORMIX): + if Backend.getIdentifiedDbms() in (DBMS.INFORMIX, DBMS.VIRTUOSO): count = 1 else: infoMsg = "fetching number of password hashes " @@ -322,7 +322,7 @@ class Users(object): if fallback: query = query.replace("master.dbo.fn_varbintohexstr", "sys.fn_sqlvarbasetostr") - elif Backend.isDbms(DBMS.INFORMIX): + elif Backend.getIdentifiedDbms() in (DBMS.INFORMIX, DBMS.VIRTUOSO): query = rootQuery.blind.query % (user,) elif Backend.isDbms(DBMS.HSQLDB):