mirror of
				https://github.com/sqlmapproject/sqlmap.git
				synced 2025-11-04 09:57:38 +03:00 
			
		
		
		
	Couple of fixes for SAP MaxDB
This commit is contained in:
		
							parent
							
								
									176e89d978
								
							
						
					
					
						commit
						0605f14d87
					
				| 
						 | 
					@ -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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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/>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 |")),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 = {}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user