Skip to content

Commit a6262a3

Browse files
committed
Adding support for Virtuoso DBMS
1 parent 1f33b16 commit a6262a3

File tree

19 files changed

+343
-16
lines changed

19 files changed

+343
-16
lines changed

data/xml/errors.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,4 +223,12 @@
223223
<error regexp="-10048: Syntax error"/>
224224
<error regexp="rdmStmtPrepare\(.+?\) returned"/>
225225
</dbms>
226+
227+
<dbms value="Virtuoso">
228+
<error regexp="SQ074: Line \d+:"/>
229+
<error regexp="SR185: Undefined procedure"/>
230+
<error regexp="SQ200: No table "/>
231+
<error regexp="Virtuoso S0002 Error"/>
232+
<error regexp="\[(Virtuoso Driver|Virtuoso iODBC Driver)\]\[Virtuoso Server\]"/>
233+
</dbms>
226234
</root>

data/xml/queries.xml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1665,4 +1665,55 @@
16651665
<search_table/>
16661666
<search_column/>
16671667
</dbms>
1668+
1669+
<dbms value="Virtuoso">
1670+
<cast query="CAST(%s AS NCHAR)"/>
1671+
<length query="LENGTH(%s)"/>
1672+
<isnull query="__MAX_NOTNULL(%s,' ')"/>
1673+
<delimiter query="||"/>
1674+
<limit query="TOP (%d,%d)"/>
1675+
<limitregexp query="\s+TOP\s*\(([\d]+)\s*\,\s*([\d]+)\)" query2="\s+TOP\s+([\d]+)"/>
1676+
<limitgroupstart query="1"/>
1677+
<limitgroupstop query="2"/>
1678+
<limitstring query=" TOP "/>
1679+
<order query="ORDER BY %s ASC"/>
1680+
<count query="COUNT(%s)"/>
1681+
<comment query="-- -" query2="/*"/>
1682+
<concatenate query="%s||%s"/>
1683+
<case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>
1684+
<inference query="ASCII(SUBSTRING((%s),%d,1))>%d"/>
1685+
<banner query="sys_stat('st_dbms_name')||' - '||sys_stat('st_dbms_ver')"/>
1686+
<current_user query="USERNAME()"/>
1687+
<current_db query="UPPER(USERNAME())"/>
1688+
<hostname query="sys_stat('st_host_name')"/>
1689+
<table_comment/>
1690+
<column_comment/>
1691+
<is_dba query="USERNAME()='dba'"/>
1692+
<dbs>
1693+
<inband query="SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA"/>
1694+
<blind query="SELECT DISTINCT TOP (%d,1) schema_name FROM INFORMATION_SCHEMA.SCHEMATA ORDER BY 1" count="SELECT COUNT(DISTINCT(schema_name)) FROM INFORMATION_SCHEMA.SCHEMATA"/>
1695+
</dbs>
1696+
<tables>
1697+
<inband query="SELECT table_schema,table_name FROM INFORMATION_SCHEMA.TABLES" condition="table_schema"/>
1698+
<blind query="SELECT TOP (%d,1) table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='%s' ORDER BY 1" count="SELECT COUNT(table_name) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='%s'"/>
1699+
</tables>
1700+
<columns>
1701+
<inband query="SELECT column_name,data_type FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='%s' AND table_schema='%s'" condition="column_name"/>
1702+
<blind query="SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='%s' AND table_schema='%s'" query2="SELECT data_type FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='%s' AND column_name='%s' AND table_schema='%s'" count="SELECT COUNT(column_name) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='%s' AND table_schema='%s'" condition="column_name"/>
1703+
</columns>
1704+
<dump_table>
1705+
<inband query="SELECT %s FROM %s.%s ORDER BY %s"/>
1706+
<blind query="SELECT TOP (%d,1) %s FROM %s.%s ORDER BY %s" count="SELECT COUNT(*) FROM %s.%s"/>
1707+
</dump_table>
1708+
<users>
1709+
<inband query="SELECT u_name FROM SYS_USERS WHERE U_IS_ROLE=0 ORDER BY 1"/>
1710+
<blind query="SELECT TOP (%d,1) u_name FROM SYS_USERS WHERE U_IS_ROLE=0 ORDER BY 1" count="SELECT COUNT(DISTINCT(u_name)) FROM SYS_USERS"/>
1711+
</users>
1712+
<privileges/>
1713+
<roles/>
1714+
<statements/>
1715+
<search_db/>
1716+
<search_table/>
1717+
<search_column/>
1718+
</dbms>
16681719
</root>

lib/controller/handler.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
from lib.core.settings import SQLITE_ALIASES
3838
from lib.core.settings import SYBASE_ALIASES
3939
from lib.core.settings import VERTICA_ALIASES
40+
from lib.core.settings import VIRTUOSO_ALIASES
4041
from lib.utils.sqlalchemy import SQLAlchemy
4142

4243
from plugins.dbms.access.connector import Connector as AccessConn
@@ -91,6 +92,8 @@
9192
from plugins.dbms.sybase import SybaseMap
9293
from plugins.dbms.vertica.connector import Connector as VerticaConn
9394
from plugins.dbms.vertica import VerticaMap
95+
from plugins.dbms.virtuoso.connector import Connector as VirtuosoConn
96+
from plugins.dbms.virtuoso import VirtuosoMap
9497

9598
def setHandler():
9699
"""
@@ -125,6 +128,7 @@ def setHandler():
125128
(DBMS.EXTREMEDB, EXTREMEDB_ALIASES, ExtremeDBMap, ExtremeDBConn),
126129
(DBMS.FRONTBASE, FRONTBASE_ALIASES, FrontBaseMap, FrontBaseConn),
127130
(DBMS.RAIMA, RAIMA_ALIASES, RaimaMap, RaimaConn),
131+
(DBMS.VIRTUOSO, VIRTUOSO_ALIASES, VirtuosoMap, VirtuosoConn),
128132
]
129133

130134
_ = max(_ if (conf.get("dbms") or Backend.getIdentifiedDbms() or kb.heuristicExtendedDbms or "").lower() in _[1] else () for _ in items)

lib/core/agent.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ def concatQuery(self, query, unpack=True):
699699
elif fieldsNoSelect:
700700
concatenatedQuery = "CONCAT('%s',%s,'%s')" % (kb.chars.start, concatenatedQuery, kb.chars.stop)
701701

702-
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):
702+
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):
703703
if fieldsExists:
704704
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1)
705705
concatenatedQuery += "||'%s'" % kb.chars.stop
@@ -1021,7 +1021,7 @@ def limitQuery(self, num, query, field=None, uniqueField=None):
10211021
limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (1, num)
10221022
limitedQuery += " %s" % limitStr
10231023

1024-
elif Backend.getIdentifiedDbms() in (DBMS.FRONTBASE,):
1024+
elif Backend.getIdentifiedDbms() in (DBMS.FRONTBASE, DBMS.VIRTUOSO):
10251025
limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (num, 1)
10261026
if query.startswith("SELECT "):
10271027
limitedQuery = query.replace("SELECT ", "SELECT %s " % limitStr, 1)

lib/core/common.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4200,7 +4200,7 @@ def safeSQLIdentificatorNaming(name, isTable=False):
42004200

42014201
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)
42024202
retVal = "`%s`" % retVal
4203-
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):
4203+
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):
42044204
retVal = "\"%s\"" % retVal
42054205
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.ALTIBASE, DBMS.MIMERSQL):
42064206
retVal = "\"%s\"" % retVal.upper()
@@ -4238,7 +4238,7 @@ def unsafeSQLIdentificatorNaming(name):
42384238
if isinstance(name, six.string_types):
42394239
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ACCESS, DBMS.CUBRID, DBMS.SQLITE):
42404240
retVal = name.replace("`", "")
4241-
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):
4241+
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):
42424242
retVal = name.replace("\"", "")
42434243
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.ALTIBASE, DBMS.MIMERSQL):
42444244
retVal = name.replace("\"", "").upper()

lib/core/dicts.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
from lib.core.settings import SQLITE_ALIASES
3838
from lib.core.settings import SYBASE_ALIASES
3939
from lib.core.settings import VERTICA_ALIASES
40+
from lib.core.settings import VIRTUOSO_ALIASES
4041

4142
FIREBIRD_TYPES = {
4243
261: "BLOB",
@@ -246,6 +247,7 @@
246247
DBMS.EXTREMEDB: (EXTREMEDB_ALIASES, None, None, None),
247248
DBMS.FRONTBASE: (FRONTBASE_ALIASES, None, None, None),
248249
DBMS.RAIMA: (RAIMA_ALIASES, None, None, None),
250+
DBMS.VIRTUOSO: (VIRTUOSO_ALIASES, None, None, None),
249251
}
250252

251253
# Reference: https://blog.jooq.org/tag/sysibm-sysdummy1/
@@ -283,6 +285,7 @@
283285
DBMS.CACHE: "%SQLUPPER NULL",
284286
DBMS.EXTREMEDB: "NULLIFZERO(hashcode(NULL))",
285287
DBMS.RAIMA: "IF(ROWNUMBER()>0,CONVERT(NULL,TINYINT),NULL))",
288+
DBMS.VIRTUOSO: "__MAX_NOTNULL(NULL)",
286289
}
287290

288291
SQL_STATEMENTS = {

lib/core/dump.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ def currentUser(self, data):
166166
def currentDb(self, data):
167167
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.VERTICA, DBMS.CRATEDB, DBMS.CACHE, DBMS.FRONTBASE):
168168
self.string("current database (equivalent to schema on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB)
169-
elif Backend.getIdentifiedDbms() in (DBMS.ALTIBASE, DBMS.DB2, DBMS.MIMERSQL, DBMS.MAXDB):
169+
elif Backend.getIdentifiedDbms() in (DBMS.ALTIBASE, DBMS.DB2, DBMS.MIMERSQL, DBMS.MAXDB, DBMS.VIRTUOSO):
170170
self.string("current database (equivalent to owner on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB)
171171
else:
172172
self.string("current database", data, content_type=CONTENT_TYPE.CURRENT_DB)

lib/core/enums.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class DBMS(object):
5858
EXTREMEDB = "eXtremeDB"
5959
FRONTBASE = "FrontBase"
6060
RAIMA = "Raima Database Manager"
61+
VIRTUOSO = "Virtuoso"
6162

6263
class DBMS_DIRECTORY_NAME(object):
6364
ACCESS = "access"
@@ -86,6 +87,7 @@ class DBMS_DIRECTORY_NAME(object):
8687
EXTREMEDB = "extremedb"
8788
FRONTBASE = "frontbase"
8889
RAIMA = "raima"
90+
VIRTUOSO = "virtuoso"
8991

9092
class FORK(object):
9193
MARIADB = "MariaDB"

lib/core/settings.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@
283283
EXTREMEDB_SYSTEM_DBS = ("",)
284284
FRONTBASE_SYSTEM_DBS = ("DEFINITION_SCHEMA", "INFORMATION_SCHEMA")
285285
RAIMA_SYSTEM_DBS = ("",)
286+
VIRTUOSO_SYSTEM_DBS = ("",)
286287

287288
# Note: (<regular>) + (<forks>)
288289
MSSQL_ALIASES = ("microsoft sql server", "mssqlserver", "mssql", "ms")
@@ -311,13 +312,14 @@
311312
EXTREMEDB_ALIASES = ("extremedb", "extreme")
312313
FRONTBASE_ALIASES = ("frontbase",)
313314
RAIMA_ALIASES = ("raima database manager", "raima", "raimadb", "raimadm", "rdm", "rds", "velocis")
315+
VIRTUOSO_ALIASES = ("virtuoso", "openlink virtuoso")
314316

315317
DBMS_DIRECTORY_DICT = dict((getattr(DBMS, _), getattr(DBMS_DIRECTORY_NAME, _)) for _ in dir(DBMS) if not _.startswith("_"))
316318

317-
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)
319+
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)
318320
SUPPORTED_OS = ("linux", "windows")
319321

320-
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))
322+
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))
321323

322324
USER_AGENT_ALIASES = ("ua", "useragent", "user-agent")
323325
REFERER_ALIASES = ("ref", "referer", "referrer")

plugins/dbms/virtuoso/__init__.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/usr/bin/env python
2+
3+
"""
4+
Copyright (c) 2006-2021 sqlmap developers (http://sqlmap.org/)
5+
See the file 'LICENSE' for copying permission
6+
"""
7+
8+
from lib.core.enums import DBMS
9+
from lib.core.settings import VIRTUOSO_SYSTEM_DBS
10+
from lib.core.unescaper import unescaper
11+
from plugins.dbms.virtuoso.enumeration import Enumeration
12+
from plugins.dbms.virtuoso.filesystem import Filesystem
13+
from plugins.dbms.virtuoso.fingerprint import Fingerprint
14+
from plugins.dbms.virtuoso.syntax import Syntax
15+
from plugins.dbms.virtuoso.takeover import Takeover
16+
from plugins.generic.misc import Miscellaneous
17+
18+
class VirtuosoMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
19+
"""
20+
This class defines Virtuoso methods
21+
"""
22+
23+
def __init__(self):
24+
self.excludeDbsList = VIRTUOSO_SYSTEM_DBS
25+
26+
for cls in self.__class__.__bases__:
27+
cls.__init__(self)
28+
29+
unescaper[DBMS.VIRTUOSO] = Syntax.escape

0 commit comments

Comments
 (0)