Skip to content

Commit 60b642e

Browse files
committed
Adding support for Mckoi
1 parent 20700fd commit 60b642e

File tree

25 files changed

+462
-50
lines changed

25 files changed

+462
-50
lines changed

data/xml/errors.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,4 +196,10 @@
196196
<error regexp="org\.jkiss\.dbeaver\.ext\.vertica"/>
197197
<error regexp="com\.vertica\.dsi\.dataengine"/>
198198
</dbms>
199+
200+
<!-- Mckoi -->
201+
<dbms value="Mckoi">
202+
<error regexp="com\.mckoi\.JDBCDriver"/>
203+
<error regexp="com\.mckoi\.database\.jdbc"/>
204+
</dbms>
199205
</root>

data/xml/queries.xml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,4 +1088,46 @@
10881088
<blind query="SELECT DISTINCT(table_schema) FROM v_catalog.columns WHERE %s ORDER BY 1" query2="SELECT DISTINCT(table_name) FROM v_catalog.columns WHERE table_schema='%s'" count="SELECT COUNT(DISTINCT(table_schema)) FROM v_catalog.columns WHERE %s" count2="SELECT COUNT(DISTINCT(table_name)) FROM v_catalog.columns WHERE table_schema='%s'" condition="column_name" condition2="table_schema" condition3="table_name"/>
10891089
</search_column>
10901090
</dbms>
1091+
1092+
<!-- Mckoi -->
1093+
<!-- NOTE: DBMS with minimalistic set of (restricted) features -->
1094+
<dbms value="Mckoi">
1095+
<cast query="CONCAT('',%s)"/>
1096+
<length query="LENGTH(%s)"/>
1097+
<isnull query="IF(%s IS NULL,' ', %s)"/>
1098+
<delimiter query="||"/>
1099+
<limit/>
1100+
<limitregexp/>
1101+
<limitgroupstart/>
1102+
<limitgroupstop/>
1103+
<limitstring/>
1104+
<order query="ORDER BY %s ASC"/>
1105+
<count query="COUNT(%s)"/>
1106+
<comment query=";"/>
1107+
<substring query="SUBSTRING((%s),%d,%d)"/>
1108+
<concatenate query="%s||%s"/>
1109+
<case query="SELECT (IF(%s,1,0))"/>
1110+
<!-- NOTE: other way around does not work -->
1111+
<inference query="'%c'&lt;SUBSTRING((%s),%d,1)"/>
1112+
<banner/>
1113+
<current_user/>
1114+
<current_db/>
1115+
<hostname/>
1116+
<table_comment/>
1117+
<column_comment/>
1118+
<is_dba/>
1119+
<dbs/>
1120+
<tables/>
1121+
<dump_table>
1122+
<inband query="SELECT %s FROM %s"/>
1123+
<blind query="SELECT MIN(%s) FROM %s WHERE CONCAT('',%s)>'%s'" query2="SELECT MAX(%s) FROM %s WHERE CONCAT('',%s) LIKE '%s'" count="SELECT COUNT(*) FROM %s" count2="SELECT COUNT(DISTINCT(%s)) FROM %s"/>
1124+
</dump_table>
1125+
<users/>
1126+
<privileges/>
1127+
<roles/>
1128+
<statements/>
1129+
<search_db/>
1130+
<search_table/>
1131+
<search_column/>
1132+
</dbms>
10911133
</root>

lib/controller/checks.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -879,12 +879,12 @@ def heuristicCheckDbms(injection):
879879
kb.injection = injection
880880

881881
for dbms in getPublicTypeMembers(DBMS, True):
882-
randStr1, randStr2 = randomStr(), randomStr()
883-
Backend.forceDbms(dbms)
884-
885882
if conf.noEscape and dbms not in FROM_DUMMY_TABLE:
886883
continue
887884

885+
randStr1, randStr2 = randomStr(), randomStr()
886+
Backend.forceDbms(dbms)
887+
888888
if checkBooleanExpression("(SELECT '%s'%s)=%s%s%s" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), SINGLE_QUOTE_MARKER, randStr1, SINGLE_QUOTE_MARKER)):
889889
if not checkBooleanExpression("(SELECT '%s'%s)=%s%s%s" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), SINGLE_QUOTE_MARKER, randStr2, SINGLE_QUOTE_MARKER)):
890890
retVal = dbms

lib/controller/handler.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from lib.core.dicts import DBMS_DICT
1212
from lib.core.enums import DBMS
1313
from lib.core.exception import SqlmapConnectionException
14+
from lib.core.settings import MCKOI_ALIASES
1415
from lib.core.settings import MSSQL_ALIASES
1516
from lib.core.settings import MYSQL_ALIASES
1617
from lib.core.settings import ORACLE_ALIASES
@@ -29,6 +30,8 @@
2930
from lib.core.settings import VERTICA_ALIASES
3031
from lib.utils.sqlalchemy import SQLAlchemy
3132

33+
from plugins.dbms.mckoi import MckoiMap
34+
from plugins.dbms.mckoi.connector import Connector as MckoiConn
3235
from plugins.dbms.mssqlserver import MSSQLServerMap
3336
from plugins.dbms.mssqlserver.connector import Connector as MSSQLServerConn
3437
from plugins.dbms.mysql import MySQLMap
@@ -85,6 +88,7 @@ def setHandler():
8588
(DBMS.MONETDB, MONETDB_ALIASES, MonetDBMap, MonetDBConn),
8689
(DBMS.DERBY, DERBY_ALIASES, DerbyMap, DerbyConn),
8790
(DBMS.VERTICA, VERTICA_ALIASES, VerticaMap, VerticaConn),
91+
(DBMS.MCKOI, MCKOI_ALIASES, MckoiMap, MckoiConn),
8892
]
8993

9094
_ = 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: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
from lib.core.settings import DEFAULT_COOKIE_DELIMITER
4848
from lib.core.settings import DEFAULT_GET_POST_DELIMITER
4949
from lib.core.settings import GENERIC_SQL_COMMENT
50+
from lib.core.settings import GENERIC_SQL_COMMENT_MARKER
5051
from lib.core.settings import INFERENCE_MARKER
5152
from lib.core.settings import NULL
5253
from lib.core.settings import PAYLOAD_DELIMITER
@@ -297,8 +298,8 @@ def suffixQuery(self, expression, comment=None, suffix=None, where=None, trimEmp
297298
where = getTechniqueData().where if where is None else where
298299
comment = getTechniqueData().comment if comment is None else comment
299300

300-
if Backend.getIdentifiedDbms() == DBMS.ACCESS and any((comment or "").startswith(_) for _ in ("--", "[GENERIC_SQL_COMMENT]")):
301-
comment = queries[DBMS.ACCESS].comment.query
301+
if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI) and any((comment or "").startswith(_) for _ in ("--", GENERIC_SQL_COMMENT_MARKER)):
302+
comment = queries[Backend.getIdentifiedDbms()].comment.query
302303

303304
if comment is not None:
304305
expression += comment
@@ -454,7 +455,7 @@ def nullAndCastField(self, field):
454455
else:
455456
if not (Backend.isDbms(DBMS.SQLITE) and not isDBMSVersionAtLeast('3')):
456457
nulledCastedField = rootQuery.cast.query % field
457-
if Backend.getIdentifiedDbms() in (DBMS.ACCESS,):
458+
if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI):
458459
nulledCastedField = rootQuery.isnull.query % (nulledCastedField, nulledCastedField)
459460
else:
460461
nulledCastedField = rootQuery.isnull.query % nulledCastedField
@@ -656,7 +657,7 @@ def concatQuery(self, query, unpack=True):
656657
elif fieldsNoSelect:
657658
concatenatedQuery = "CONCAT('%s',%s,'%s')" % (kb.chars.start, concatenatedQuery, kb.chars.stop)
658659

659-
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE, DBMS.DB2, DBMS.FIREBIRD, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.DERBY, DBMS.VERTICA):
660+
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):
660661
if fieldsExists:
661662
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1)
662663
concatenatedQuery += "||'%s'" % kb.chars.stop
@@ -1058,12 +1059,15 @@ def limitQuery(self, num, query, field=None, uniqueField=None):
10581059
def forgeQueryOutputLength(self, expression):
10591060
lengthQuery = queries[Backend.getIdentifiedDbms()].length.query
10601061
select = re.search(r"\ASELECT\s+", expression, re.I)
1062+
selectFrom = re.search(r"\ASELECT\s+(.+)\s+FROM\s+(.+)", expression, re.I)
10611063
selectTopExpr = re.search(r"\ASELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM", expression, re.I)
10621064
selectMinMaxExpr = re.search(r"\ASELECT\s+(MIN|MAX)\(.+?\)\s+FROM", expression, re.I)
10631065

10641066
_, _, _, _, _, _, fieldsStr, _ = self.getFields(expression)
10651067

1066-
if selectTopExpr or selectMinMaxExpr:
1068+
if Backend.getIdentifiedDbms() in (DBMS.MCKOI,) and selectFrom:
1069+
lengthExpr = "SELECT %s FROM %s" % (lengthQuery % selectFrom.group(1), selectFrom.group(2))
1070+
elif selectTopExpr or selectMinMaxExpr:
10671071
lengthExpr = lengthQuery % ("(%s)" % expression)
10681072
elif select:
10691073
lengthExpr = expression.replace(fieldsStr, lengthQuery % fieldsStr, 1)

lib/core/common.py

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

40704070
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ACCESS, DBMS.SQLITE): # Note: in SQLite double-quotes are treated as string if column/identifier is non-existent (e.g. SELECT "foobar" FROM users)
40714071
retVal = "`%s`" % retVal
4072-
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.INFORMIX, DBMS.MONETDB, DBMS.VERTICA):
4072+
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.INFORMIX, DBMS.MONETDB, DBMS.VERTICA, DBMS.MCKOI):
40734073
retVal = "\"%s\"" % retVal
40744074
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE,):
40754075
retVal = "\"%s\"" % retVal.upper()
@@ -4107,7 +4107,7 @@ def unsafeSQLIdentificatorNaming(name):
41074107
if isinstance(name, six.string_types):
41084108
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ACCESS, DBMS.SQLITE):
41094109
retVal = name.replace("`", "")
4110-
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.INFORMIX, DBMS.HSQLDB, DBMS.MONETDB, DBMS.VERTICA):
4110+
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.INFORMIX, DBMS.HSQLDB, DBMS.MONETDB, DBMS.VERTICA, DBMS.MCKOI):
41114111
retVal = name.replace("\"", "")
41124112
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE,):
41134113
retVal = name.replace("\"", "").upper()

lib/core/dicts.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from lib.core.settings import HSQLDB_ALIASES
1919
from lib.core.settings import INFORMIX_ALIASES
2020
from lib.core.settings import MAXDB_ALIASES
21+
from lib.core.settings import MCKOI_ALIASES
2122
from lib.core.settings import MONETDB_ALIASES
2223
from lib.core.settings import MSSQL_ALIASES
2324
from lib.core.settings import MYSQL_ALIASES
@@ -204,6 +205,7 @@
204205
DBMS.MONETDB: (MONETDB_ALIASES, "pymonetdb", "https://github.com/gijzelaerr/pymonetdb", "monetdb"),
205206
DBMS.DERBY: (DERBY_ALIASES, "pydrda", "https://github.com/nakagami/pydrda/", None),
206207
DBMS.VERTICA: (VERTICA_ALIASES, "vertica-python", "https://github.com/vertica/vertica-python", "vertica+vertica_python"),
208+
DBMS.MCKOI: (MCKOI_ALIASES, None, None, None),
207209
}
208210

209211
FROM_DUMMY_TABLE = {

lib/core/enums.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class DBMS(object):
4848
MONETDB = "MonetDB"
4949
DERBY = "Apache Derby"
5050
VERTICA = "Vertica"
51+
MCKOI = "Mckoi"
5152

5253
class DBMS_DIRECTORY_NAME(object):
5354
ACCESS = "access"
@@ -66,6 +67,7 @@ class DBMS_DIRECTORY_NAME(object):
6667
MONETDB = "monetdb"
6768
DERBY = "derby"
6869
VERTICA = "vertica"
70+
MCKOI = "mckoi"
6971

7072
class FORK(object):
7173
MARIADB = "MariaDB"

lib/core/settings.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from thirdparty.six import unichr as _unichr
1919

2020
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
21-
VERSION = "1.4.1.35"
21+
VERSION = "1.4.1.36"
2222
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
2323
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
2424
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
@@ -75,6 +75,7 @@
7575
SLEEP_TIME_MARKER = "[SLEEPTIME]"
7676
INFERENCE_MARKER = "[INFERENCE]"
7777
SINGLE_QUOTE_MARKER = "[SINGLE_QUOTE]"
78+
GENERIC_SQL_COMMENT_MARKER = "[GENERIC_SQL_COMMENT]"
7879

7980
PAYLOAD_DELIMITER = "__PAYLOAD_DELIMITER__"
8081
CHAR_INFERENCE_MARK = "%c"
@@ -261,6 +262,7 @@
261262
MONETDB_SYSTEM_DBS = ("tmp", "json", "profiler")
262263
DERBY_SYSTEM_DBS = ("NULLID", "SQLJ", "SYS", "SYSCAT", "SYSCS_DIAG", "SYSCS_UTIL", "SYSFUN", "SYSIBM", "SYSPROC", "SYSSTAT")
263264
VERTICA_SYSTEM_DBS = ("v_catalog", "v_internal", "v_monitor",)
265+
MCKOI_SYSTEM_DBS = ("",)
264266

265267
MSSQL_ALIASES = ("microsoft sql server", "mssqlserver", "mssql", "ms")
266268
MYSQL_ALIASES = ("mysql", "my") + ("mariadb", "maria", "memsql")
@@ -278,13 +280,16 @@
278280
MONETDB_ALIASES = ("monet", "monetdb",)
279281
DERBY_ALIASES = ("derby", "apache derby",)
280282
VERTICA_ALIASES = ("vertica",)
283+
MCKOI_ALIASES = ("mckoi",)
284+
285+
UPPER_CASE_IDENTIFIERS = {DBMS.ORACLE, DBMS.DB2, DBMS.FIREBIRD, DBMS.HSQLDB, DBMS.MAXDB, DBMS.H2, DBMS.DERBY}
281286

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

284-
SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES + SQLITE_ALIASES + ACCESS_ALIASES + FIREBIRD_ALIASES + MAXDB_ALIASES + SYBASE_ALIASES + DB2_ALIASES + HSQLDB_ALIASES + H2_ALIASES + INFORMIX_ALIASES + MONETDB_ALIASES + DERBY_ALIASES + VERTICA_ALIASES
289+
SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES + SQLITE_ALIASES + ACCESS_ALIASES + FIREBIRD_ALIASES + MAXDB_ALIASES + SYBASE_ALIASES + DB2_ALIASES + HSQLDB_ALIASES + H2_ALIASES + INFORMIX_ALIASES + MONETDB_ALIASES + DERBY_ALIASES + VERTICA_ALIASES + MCKOI_ALIASES
285290
SUPPORTED_OS = ("linux", "windows")
286291

287-
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))
292+
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))
288293

289294
USER_AGENT_ALIASES = ("ua", "useragent", "user-agent")
290295
REFERER_ALIASES = ("ref", "referer", "referrer")
@@ -293,6 +298,7 @@
293298
# Default schemas to use (when unable to enumerate)
294299
H2_DEFAULT_SCHEMA = HSQLDB_DEFAULT_SCHEMA = "PUBLIC"
295300
VERTICA_DEFAULT_SCHEMA = "public"
301+
MCKOI_DEFAULT_SCHEMA = "APP"
296302

297303
# Names that can't be used to name files on Windows OS
298304
WINDOWS_RESERVED_NAMES = ("CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9")

lib/request/inject.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ def getValue(expression, blind=True, union=True, error=True, time=True, fromUser
496496
if not any((kb.testMode, conf.dummy, conf.offline)) and value is None and Backend.getDbms() and conf.dbmsHandler and not conf.noCast and not conf.hexConvert:
497497
warnMsg = "in case of continuous data retrieval problems you are advised to try "
498498
warnMsg += "a switch '--no-cast' "
499-
warnMsg += "or switch '--hex'" if Backend.getIdentifiedDbms() not in (DBMS.ACCESS, DBMS.FIREBIRD) else ""
499+
warnMsg += "or switch '--hex'" if Backend.getIdentifiedDbms() not in (DBMS.ACCESS, DBMS.FIREBIRD, DBMS.MONETDB, DBMS.MCKOI) else ""
500500
singleTimeWarnMessage(warnMsg)
501501

502502
# Dirty patch (safe-encoded unicode characters)

0 commit comments

Comments
 (0)