def _resumeDBMS(): """ Resume stored DBMS information from HashDB """ value = hashDBRetrieve(HASHDB_KEYS.DBMS) if not value: if conf.offline: errMsg = "unable to continue in offline mode " errMsg += "because of lack of usable " errMsg += "session data" raise SqlmapNoneDataException(errMsg) else: return dbms = value.lower() dbmsVersion = [UNKNOWN_DBMS_VERSION] _ = "(%s)" % ("|".join([alias for alias in SUPPORTED_DBMS])) _ = re.search(r"\A%s (.*)" % _, dbms, re.I) if _: dbms = _.group(1).lower() dbmsVersion = [_.group(2)] if conf.dbms: check = True for aliases, _, _, _ in DBMS_DICT.values(): if conf.dbms.lower() in aliases and dbms not in aliases: check = False break if not check: message = "you provided '%s' as a back-end DBMS, " % conf.dbms message += "but from a past scan information on the target URL " message += "sqlmap assumes the back-end DBMS is '%s'. " % dbms message += "Do you really want to force the back-end " message += "DBMS value? [y/N] " if not readInput(message, default='N', boolean=True): conf.dbms = None Backend.setDbms(dbms) Backend.setVersionList(dbmsVersion) else: infoMsg = "resuming back-end DBMS '%s' " % dbms logger.info(infoMsg) Backend.setDbms(dbms) Backend.setVersionList(dbmsVersion)
def _resumeDBMS(): """ Resume stored DBMS information from HashDB """ value = hashDBRetrieve(HASHDB_KEYS.DBMS) if not value: return dbms = value.lower() dbmsVersion = [UNKNOWN_DBMS_VERSION] _ = "(%s)" % ("|".join([alias for alias in SUPPORTED_DBMS])) _ = re.search("%s ([\d\.]+)" % _, dbms, re.I) if _: dbms = _.group(1).lower() dbmsVersion = [_.group(2)] if conf.dbms: check = True for aliases, _, _, _ in DBMS_DICT.values(): if conf.dbms.lower() in aliases and dbms not in aliases: check = False break if not check: message = "you provided '%s' as a back-end DBMS, " % conf.dbms message += "but from a past scan information on the target URL " message += "sqlmap assumes the back-end DBMS is '%s'. " % dbms message += "Do you really want to force the back-end " message += "DBMS value? [y/N] " test = readInput(message, default="N") if not test or test[0] in ("n", "N"): conf.dbms = None Backend.setDbms(dbms) Backend.setVersionList(dbmsVersion) else: infoMsg = "resuming back-end DBMS '%s' " % dbms logger.info(infoMsg) Backend.setDbms(dbms) Backend.setVersionList(dbmsVersion)
def checkDbms(self): """ References for fingerprint: * http://dev.mysql.com/doc/refman/5.0/en/news-5-0-x.html (up to 5.0.89) * http://dev.mysql.com/doc/refman/5.1/en/news-5-1-x.html (up to 5.1.42) * http://dev.mysql.com/doc/refman/5.4/en/news-5-4-x.html (up to 5.4.4) * http://dev.mysql.com/doc/refman/5.5/en/news-5-5-x.html (up to 5.5.0) * http://dev.mysql.com/doc/refman/6.0/en/news-6-0-x.html (manual has been withdrawn) """ if not conf.extensiveFp and (Backend.isDbmsWithin(MYSQL_ALIASES) \ or conf.dbms in MYSQL_ALIASES) and Backend.getVersion() and \ Backend.getVersion() != UNKNOWN_DBMS_VERSION: v = Backend.getVersion().replace(">", "") v = v.replace("=", "") v = v.replace(" ", "") Backend.setVersion(v) setDbms("%s %s" % (DBMS.MYSQL, Backend.getVersion())) if Backend.isVersionGreaterOrEqualThan("5"): kb.data.has_information_schema = True self.getBanner() return True infoMsg = "testing %s" % DBMS.MYSQL logger.info(infoMsg) result = inject.checkBooleanExpression("QUARTER(NULL) IS NULL") if result: infoMsg = "confirming %s" % DBMS.MYSQL logger.info(infoMsg) result = inject.checkBooleanExpression("USER() LIKE USER()") if not result: warnMsg = "the back-end DBMS is not %s" % DBMS.MYSQL logger.warn(warnMsg) return False # reading information_schema on some platforms is causing annoying timeout exits # Reference: http://bugs.mysql.com/bug.php?id=15855 # Determine if it is MySQL >= 5.0.0 if inject.checkBooleanExpression( "ISNULL(TIMESTAMPADD(MINUTE,[RANDNUM],0))"): kb.data.has_information_schema = True Backend.setVersion(">= 5.0.0") setDbms("%s 5" % DBMS.MYSQL) self.getBanner() if not conf.extensiveFp: return True infoMsg = "actively fingerprinting %s" % DBMS.MYSQL logger.info(infoMsg) # Check if it is MySQL >= 5.5.0 if inject.checkBooleanExpression("TO_SECONDS(950501)>0"): Backend.setVersion(">= 5.5.0") # Check if it is MySQL >= 5.1.2 and < 5.5.0 elif inject.checkBooleanExpression( "@@table_open_cache=@@table_open_cache"): if inject.checkBooleanExpression( "[RANDNUM]=(SELECT [RANDNUM] FROM information_schema.GLOBAL_STATUS LIMIT 0, 1)" ): Backend.setVersionList([">= 5.1.12", "< 5.5.0"]) elif inject.checkBooleanExpression( "[RANDNUM]=(SELECT [RANDNUM] FROM information_schema.PROCESSLIST LIMIT 0, 1)" ): Backend.setVersionList([">= 5.1.7", "< 5.1.12"]) elif inject.checkBooleanExpression( "[RANDNUM]=(SELECT [RANDNUM] FROM information_schema.PARTITIONS LIMIT 0, 1)" ): Backend.setVersion("= 5.1.6") elif inject.checkBooleanExpression( "[RANDNUM]=(SELECT [RANDNUM] FROM information_schema.PLUGINS LIMIT 0, 1)" ): Backend.setVersionList([">= 5.1.5", "< 5.1.6"]) else: Backend.setVersionList([">= 5.1.2", "< 5.1.5"]) # Check if it is MySQL >= 5.0.0 and < 5.1.2 elif inject.checkBooleanExpression("@@hostname=@@hostname"): Backend.setVersionList([">= 5.0.38", "< 5.1.2"]) elif inject.checkBooleanExpression( "@@character_set_filesystem=@@character_set_filesystem" ): Backend.setVersionList([">= 5.0.19", "< 5.0.38"]) elif not inject.checkBooleanExpression( "[RANDNUM]=(SELECT [RANDNUM] FROM DUAL WHERE [RANDNUM1]!=[RANDNUM2])" ): Backend.setVersionList([">= 5.0.11", "< 5.0.19"]) elif inject.checkBooleanExpression( "@@div_precision_increment=@@div_precision_increment"): Backend.setVersionList([">= 5.0.6", "< 5.0.11"]) elif inject.checkBooleanExpression( "@@automatic_sp_privileges=@@automatic_sp_privileges"): Backend.setVersionList([">= 5.0.3", "< 5.0.6"]) else: Backend.setVersionList([">= 5.0.0", "< 5.0.3"]) elif inject.checkBooleanExpression("DATABASE() LIKE SCHEMA()"): Backend.setVersion(">= 5.0.2") setDbms("%s 5" % DBMS.MYSQL) self.getBanner() elif inject.checkBooleanExpression( "STRCMP(LOWER(CURRENT_USER()), UPPER(CURRENT_USER()))=0"): Backend.setVersion("< 5.0.0") setDbms("%s 4" % DBMS.MYSQL) self.getBanner() if not conf.extensiveFp: return True # Check which version of MySQL < 5.0.0 it is if inject.checkBooleanExpression( "3=(SELECT COERCIBILITY(USER()))"): Backend.setVersionList([">= 4.1.11", "< 5.0.0"]) elif inject.checkBooleanExpression( "2=(SELECT COERCIBILITY(USER()))"): Backend.setVersionList([">= 4.1.1", "< 4.1.11"]) elif inject.checkBooleanExpression( "CURRENT_USER()=CURRENT_USER()"): Backend.setVersionList([">= 4.0.6", "< 4.1.1"]) if inject.checkBooleanExpression( "'utf8'=(SELECT CHARSET(CURRENT_USER()))"): Backend.setVersion("= 4.1.0") else: Backend.setVersionList([">= 4.0.6", "< 4.1.0"]) else: Backend.setVersionList([">= 4.0.0", "< 4.0.6"]) else: Backend.setVersion("< 4.0.0") setDbms("%s 3" % DBMS.MYSQL) self.getBanner() return True else: warnMsg = "the back-end DBMS is not %s" % DBMS.MYSQL logger.warn(warnMsg) return False
def checkDbms(self): """ References for fingerprint: * https://www.postgresql.org/docs/current/static/release.html """ if not conf.extensiveFp and Backend.isDbmsWithin(PGSQL_ALIASES): setDbms(DBMS.PGSQL) self.getBanner() return True infoMsg = "testing %s" % DBMS.PGSQL logger.info(infoMsg) # NOTE: Vertica works too without the CONVERT_TO() result = inject.checkBooleanExpression( "CONVERT_TO('[RANDSTR]', QUOTE_IDENT(NULL)) IS NULL") if result: infoMsg = "confirming %s" % DBMS.PGSQL logger.info(infoMsg) result = inject.checkBooleanExpression( "COALESCE([RANDNUM], NULL)=[RANDNUM]") if not result: warnMsg = "the back-end DBMS is not %s" % DBMS.PGSQL logger.warn(warnMsg) return False setDbms(DBMS.PGSQL) self.getBanner() if not conf.extensiveFp: return True infoMsg = "actively fingerprinting %s" % DBMS.PGSQL logger.info(infoMsg) if inject.checkBooleanExpression("SINH(0)=0"): Backend.setVersion(">= 12.0") elif inject.checkBooleanExpression("SHA256(NULL) IS NULL"): Backend.setVersion(">= 11.0") elif inject.checkBooleanExpression("XMLTABLE(NULL) IS NULL"): Backend.setVersionList([">= 10.0", "< 11.0"]) elif inject.checkBooleanExpression("SIND(0)=0"): Backend.setVersionList([">= 9.6.0", "< 10.0"]) elif inject.checkBooleanExpression("TO_JSONB(1) IS NOT NULL"): Backend.setVersionList([">= 9.5.0", "< 9.6.0"]) elif inject.checkBooleanExpression("JSON_TYPEOF(NULL) IS NULL"): Backend.setVersionList([">= 9.4.0", "< 9.5.0"]) elif inject.checkBooleanExpression( "ARRAY_REPLACE(NULL,1,1) IS NULL"): Backend.setVersionList([">= 9.3.0", "< 9.4.0"]) elif inject.checkBooleanExpression("ROW_TO_JSON(NULL) IS NULL"): Backend.setVersionList([">= 9.2.0", "< 9.3.0"]) elif inject.checkBooleanExpression("REVERSE('sqlmap')='pamlqs'"): Backend.setVersionList([">= 9.1.0", "< 9.2.0"]) elif inject.checkBooleanExpression("LENGTH(TO_CHAR(1,'EEEE'))>0"): Backend.setVersionList([">= 9.0.0", "< 9.1.0"]) elif inject.checkBooleanExpression("2=(SELECT DIV(6,3))"): Backend.setVersionList([">= 8.4.0", "< 9.0.0"]) elif inject.checkBooleanExpression( "EXTRACT(ISODOW FROM CURRENT_TIMESTAMP)<8"): Backend.setVersionList([">= 8.3.0", "< 8.4.0"]) elif inject.checkBooleanExpression( "ISFINITE(TRANSACTION_TIMESTAMP())"): Backend.setVersionList([">= 8.2.0", "< 8.3.0"]) elif inject.checkBooleanExpression("9=(SELECT GREATEST(5,9,1))"): Backend.setVersionList([">= 8.1.0", "< 8.2.0"]) elif inject.checkBooleanExpression( "3=(SELECT WIDTH_BUCKET(5.35,0.024,10.06,5))"): Backend.setVersionList([">= 8.0.0", "< 8.1.0"]) elif inject.checkBooleanExpression( "'d'=(SELECT SUBSTR(MD5('sqlmap'),1,1))"): Backend.setVersionList([">= 7.4.0", "< 8.0.0"]) elif inject.checkBooleanExpression( "'p'=(SELECT SUBSTR(CURRENT_SCHEMA(),1,1))"): Backend.setVersionList([">= 7.3.0", "< 7.4.0"]) elif inject.checkBooleanExpression("8=(SELECT BIT_LENGTH(1))"): Backend.setVersionList([">= 7.2.0", "< 7.3.0"]) elif inject.checkBooleanExpression( "'a'=(SELECT SUBSTR(QUOTE_LITERAL('a'),2,1))"): Backend.setVersionList([">= 7.1.0", "< 7.2.0"]) elif inject.checkBooleanExpression("8=(SELECT POW(2,3))"): Backend.setVersionList([">= 7.0.0", "< 7.1.0"]) elif inject.checkBooleanExpression("'a'=(SELECT MAX('a'))"): Backend.setVersionList([">= 6.5.0", "< 6.5.3"]) elif inject.checkBooleanExpression("VERSION()=VERSION()"): Backend.setVersionList([">= 6.4.0", "< 6.5.0"]) elif inject.checkBooleanExpression( "2=(SELECT SUBSTR(CURRENT_DATE,1,1))"): Backend.setVersionList([">= 6.3.0", "< 6.4.0"]) elif inject.checkBooleanExpression( "'s'=(SELECT SUBSTRING('sqlmap',1,1))"): Backend.setVersionList([">= 6.2.0", "< 6.3.0"]) else: Backend.setVersion("< 6.2.0") return True else: warnMsg = "the back-end DBMS is not %s" % DBMS.PGSQL logger.warn(warnMsg) return False
def checkDbms(self): """ References for fingerprint: DATABASE_VERSION() version 2.2.6 added two-arg REPLACE functio REPLACE('a','a') compared to REPLACE('a','a','d') version 2.2.5 added SYSTIMESTAMP function version 2.2.3 added REGEXPR_SUBSTRING and REGEXPR_SUBSTRING_ARRAY functions version 2.2.0 added support for ROWNUM() function version 2.1.0 added MEDIAN aggregate function version < 2.0.1 added support for datetime ROUND and TRUNC functions version 2.0.0 added VALUES support version 1.8.0.4 Added org.hsqldbdb.Library function, getDatabaseFullProductVersion to return the full version string, including the 4th digit (e.g 1.8.0.4). version 1.7.2 CASE statements added and INFORMATION_SCHEMA """ if not conf.extensiveFp and Backend.isDbmsWithin(HSQLDB_ALIASES): setDbms("%s %s" % (DBMS.HSQLDB, Backend.getVersion())) if Backend.isVersionGreaterOrEqualThan("1.7.2"): kb.data.has_information_schema = True self.getBanner() return True infoMsg = "testing %s" % DBMS.HSQLDB logger.info(infoMsg) result = inject.checkBooleanExpression("CASEWHEN(1=1,1,0)=1") if result: infoMsg = "confirming %s" % DBMS.HSQLDB logger.info(infoMsg) result = inject.checkBooleanExpression("ROUNDMAGIC(PI())>=3") if not result: warnMsg = "the back-end DBMS is not %s" % DBMS.HSQLDB logger.warn(warnMsg) return False else: result = inject.checkBooleanExpression("ZERO() IS 0") # Note: check for H2 DBMS (sharing majority of same functions) if result: warnMsg = "the back-end DBMS is not %s" % DBMS.HSQLDB logger.warn(warnMsg) return False kb.data.has_information_schema = True Backend.setVersion(">= 1.7.2") setDbms("%s 1.7.2" % DBMS.HSQLDB) banner = self.getBanner() if banner: Backend.setVersion("= %s" % banner) else: if inject.checkBooleanExpression("(SELECT [RANDNUM] FROM (VALUES(0)))=[RANDNUM]"): Backend.setVersionList([">= 2.0.0", "< 2.3.0"]) else: banner = unArrayizeValue(inject.getValue("\"org.hsqldbdb.Library.getDatabaseFullProductVersion\"()", safeCharEncode=True)) if banner: Backend.setVersion("= %s" % banner) else: Backend.setVersionList([">= 1.7.2", "< 1.8.0"]) return True else: warnMsg = "the back-end DBMS is not %s" % DBMS.HSQLDB logger.warn(warnMsg) dbgMsg = "...or version is < 1.7.2" logger.debug(dbgMsg) return False
def checkDbms(self): """ References for fingerprint: DATABASE_VERSION() version 2.2.6 added two-arg REPLACE functio REPLACE('a','a') compared to REPLACE('a','a','d') version 2.2.5 added SYSTIMESTAMP function version 2.2.3 added REGEXPR_SUBSTRING and REGEXPR_SUBSTRING_ARRAY functions version 2.2.0 added support for ROWNUM() function version 2.1.0 added MEDIAN aggregate function version < 2.0.1 added support for datetime ROUND and TRUNC functions version 2.0.0 added VALUES support version 1.8.0.4 Added org.hsqldbdb.Library function, getDatabaseFullProductVersion to return the full version string, including the 4th digit (e.g 1.8.0.4). version 1.7.2 CASE statements added and INFORMATION_SCHEMA """ if not conf.extensiveFp and Backend.isDbmsWithin(HSQLDB_ALIASES): setDbms("%s %s" % (DBMS.HSQLDB, Backend.getVersion())) if Backend.isVersionGreaterOrEqualThan("1.7.2"): kb.data.has_information_schema = True self.getBanner() return True infoMsg = "testing %s" % DBMS.HSQLDB logger.info(infoMsg) result = inject.checkBooleanExpression("CASEWHEN(1=1,1,0)=1") if result: infoMsg = "confirming %s" % DBMS.HSQLDB logger.info(infoMsg) result = inject.checkBooleanExpression("ROUNDMAGIC(PI())>=3") if not result: warnMsg = "the back-end DBMS is not %s" % DBMS.HSQLDB logger.warn(warnMsg) return False else: kb.data.has_information_schema = True Backend.setVersion(">= 1.7.2") setDbms("%s 1.7.2" % DBMS.HSQLDB) banner = self.getBanner() if banner: Backend.setVersion("= %s" % banner) else: if inject.checkBooleanExpression("(SELECT [RANDNUM] FROM (VALUES(0)))=[RANDNUM]"): Backend.setVersionList([">= 2.0.0", "< 2.3.0"]) else: banner = unArrayizeValue(inject.getValue("\"org.hsqldbdb.Library.getDatabaseFullProductVersion\"()", safeCharEncode=True)) if banner: Backend.setVersion("= %s" % banner) else: Backend.setVersionList([">= 1.7.2", "< 1.8.0"]) return True else: warnMsg = "the back-end DBMS is not %s or version is < 1.7.2" % DBMS.HSQLDB logger.warn(warnMsg) return False
def checkDbms(self): """ References for fingerprint: * http://www.postgresql.org/docs/9.1/interactive/release.html (up to 9.1.3) """ if not conf.extensiveFp and (Backend.isDbmsWithin(PGSQL_ALIASES) or conf.dbms in PGSQL_ALIASES): setDbms(DBMS.PGSQL) self.getBanner() return True infoMsg = "testing %s" % DBMS.PGSQL logger.info(infoMsg) randInt = getUnicode(randomInt(1)) result = inject.checkBooleanExpression("%s::int=%s" % (randInt, randInt)) if result: infoMsg = "confirming %s" % DBMS.PGSQL logger.info(infoMsg) result = inject.checkBooleanExpression("COALESCE(%s, NULL)=%s" % (randInt, randInt)) if not result: warnMsg = "the back-end DBMS is not %s" % DBMS.PGSQL logger.warn(warnMsg) return False setDbms(DBMS.PGSQL) self.getBanner() if not conf.extensiveFp: return True infoMsg = "actively fingerprinting %s" % DBMS.PGSQL logger.info(infoMsg) if inject.checkBooleanExpression("REVERSE('sqlmap')='pamlqs'"): Backend.setVersion(">= 9.1.0") elif inject.checkBooleanExpression("LENGTH(TO_CHAR(1, 'EEEE'))>0"): Backend.setVersionList([">= 9.0.0", "< 9.1.0"]) elif inject.checkBooleanExpression("2=(SELECT DIV(6, 3))"): Backend.setVersionList([">= 8.4.0", "< 9.0.0"]) elif inject.checkBooleanExpression( "EXTRACT(ISODOW FROM CURRENT_TIMESTAMP)<8"): Backend.setVersionList([">= 8.3.0", "< 8.4.0"]) elif inject.checkBooleanExpression( "ISFINITE(TRANSACTION_TIMESTAMP())"): Backend.setVersionList([">= 8.2.0", "< 8.3.0"]) elif inject.checkBooleanExpression("9=(SELECT GREATEST(5, 9, 1))"): Backend.setVersionList([">= 8.1.0", "< 8.2.0"]) elif inject.checkBooleanExpression( "3=(SELECT WIDTH_BUCKET(5.35, 0.024, 10.06, 5))"): Backend.setVersionList([">= 8.0.0", "< 8.1.0"]) elif inject.checkBooleanExpression( "'d'=(SELECT SUBSTR(MD5('sqlmap'), 1, 1))"): Backend.setVersionList([">= 7.4.0", "< 8.0.0"]) elif inject.checkBooleanExpression( "'p'=(SELECT SUBSTR(CURRENT_SCHEMA(), 1, 1))"): Backend.setVersionList([">= 7.3.0", "< 7.4.0"]) elif inject.checkBooleanExpression("8=(SELECT BIT_LENGTH(1))"): Backend.setVersionList([">= 7.2.0", "< 7.3.0"]) elif inject.checkBooleanExpression( "'a'=(SELECT SUBSTR(QUOTE_LITERAL('a'), 2, 1))"): Backend.setVersionList([">= 7.1.0", "< 7.2.0"]) elif inject.checkBooleanExpression("8=(SELECT POW(2, 3))"): Backend.setVersionList([">= 7.0.0", "< 7.1.0"]) elif inject.checkBooleanExpression("'a'=(SELECT MAX('a'))"): Backend.setVersionList([">= 6.5.0", "< 6.5.3"]) elif inject.checkBooleanExpression("VERSION()=VERSION()"): Backend.setVersionList([">= 6.4.0", "< 6.5.0"]) elif inject.checkBooleanExpression( "2=(SELECT SUBSTR(CURRENT_DATE, 1, 1))"): Backend.setVersionList([">= 6.3.0", "< 6.4.0"]) elif inject.checkBooleanExpression( "'s'=(SELECT SUBSTRING('sqlmap', 1, 1))"): Backend.setVersionList([">= 6.2.0", "< 6.3.0"]) else: Backend.setVersion("< 6.2.0") return True else: warnMsg = "the back-end DBMS is not %s" % DBMS.PGSQL logger.warn(warnMsg) return False
def checkDbms(self): """ References for fingerprint: * http://dev.mysql.com/doc/refman/5.0/en/news-5-0-x.html (up to 5.0.89) * http://dev.mysql.com/doc/refman/5.1/en/news-5-1-x.html (up to 5.1.42) * http://dev.mysql.com/doc/refman/5.4/en/news-5-4-x.html (up to 5.4.4) * http://dev.mysql.com/doc/refman/5.5/en/news-5-5-x.html (up to 5.5.0) * http://dev.mysql.com/doc/refman/6.0/en/news-6-0-x.html (manual has been withdrawn) """ if not conf.extensiveFp and (Backend.isDbmsWithin(MYSQL_ALIASES) \ or conf.dbms in MYSQL_ALIASES) and Backend.getVersion() and \ Backend.getVersion() != UNKNOWN_DBMS_VERSION: v = Backend.getVersion().replace(">", "") v = v.replace("=", "") v = v.replace(" ", "") Backend.setVersion(v) setDbms("%s %s" % (DBMS.MYSQL, Backend.getVersion())) if Backend.isVersionGreaterOrEqualThan("5"): kb.data.has_information_schema = True self.getBanner() return True infoMsg = "testing %s" % DBMS.MYSQL logger.info(infoMsg) randInt = getUnicode(randomInt(1)) result = inject.checkBooleanExpression("CONNECTION_ID()=CONNECTION_ID()") if result: infoMsg = "confirming %s" % DBMS.MYSQL logger.info(infoMsg) result = inject.checkBooleanExpression("USER()=USER()") if not result: warnMsg = "the back-end DBMS is not %s" % DBMS.MYSQL logger.warn(warnMsg) return False # reading information_schema on some platforms is causing annoying timeout exits # Reference: http://bugs.mysql.com/bug.php?id=15855 # Determine if it is MySQL >= 5.0.0 if inject.checkBooleanExpression("ISNULL(TIMESTAMPADD(MINUTE,%s,%s))" % (randInt, randInt)): kb.data.has_information_schema = True Backend.setVersion(">= 5.0.0") setDbms("%s 5" % DBMS.MYSQL) self.getBanner() if not conf.extensiveFp: return True infoMsg = "actively fingerprinting %s" % DBMS.MYSQL logger.info(infoMsg) # Check if it is MySQL >= 5.5.0 if inject.checkBooleanExpression("TO_SECONDS(950501)>0"): Backend.setVersion(">= 5.5.0") # Check if it is MySQL >= 5.1.2 and < 5.5.0 elif inject.checkBooleanExpression("@@table_open_cache=@@table_open_cache"): if inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.GLOBAL_STATUS LIMIT 0, 1)" % (randInt, randInt)): Backend.setVersionList([">= 5.1.12", "< 5.5.0"]) elif inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.PROCESSLIST LIMIT 0, 1)" % (randInt,randInt)): Backend.setVersionList([">= 5.1.7", "< 5.1.12"]) elif inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.PARTITIONS LIMIT 0, 1)" % (randInt, randInt)): Backend.setVersion("= 5.1.6") elif inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.PLUGINS LIMIT 0, 1)" % (randInt, randInt)): Backend.setVersionList([">= 5.1.5", "< 5.1.6"]) else: Backend.setVersionList([">= 5.1.2", "< 5.1.5"]) # Check if it is MySQL >= 5.0.0 and < 5.1.2 elif inject.checkBooleanExpression("@@hostname=@@hostname"): Backend.setVersionList([">= 5.0.38", "< 5.1.2"]) elif inject.checkBooleanExpression("@@character_set_filesystem=@@character_set_filesystem"): Backend.setVersionList([">= 5.0.19", "< 5.0.38"]) elif not inject.checkBooleanExpression("%s=(SELECT %s FROM DUAL WHERE %s!=%s)" % (randInt, randInt, randInt, randInt)): Backend.setVersionList([">= 5.0.11", "< 5.0.19"]) elif inject.checkBooleanExpression("@@div_precision_increment=@@div_precision_increment"): Backend.setVersionList([">= 5.0.6", "< 5.0.11"]) elif inject.checkBooleanExpression("@@automatic_sp_privileges=@@automatic_sp_privileges"): Backend.setVersionList([">= 5.0.3", "< 5.0.6"]) else: Backend.setVersionList([">= 5.0.0", "< 5.0.3"]) # For cases when information_schema is missing elif inject.checkBooleanExpression("DATABASE() LIKE SCHEMA()"): Backend.setVersion(">= 5.0.2") setDbms("%s 5" % DBMS.MYSQL) self.getBanner() elif inject.checkBooleanExpression("STRCMP(LOWER(CURRENT_USER()), UPPER(CURRENT_USER()))=0"): Backend.setVersion("< 5.0.0") setDbms("%s 4" % DBMS.MYSQL) self.getBanner() if not conf.extensiveFp: return True # Check which version of MySQL < 5.0.0 it is if inject.checkBooleanExpression("3=(SELECT COERCIBILITY(USER()))"): Backend.setVersionList([">= 4.1.11", "< 5.0.0"]) elif inject.checkBooleanExpression("2=(SELECT COERCIBILITY(USER()))"): Backend.setVersionList([">= 4.1.1", "< 4.1.11"]) elif inject.checkBooleanExpression("CURRENT_USER()=CURRENT_USER()"): Backend.setVersionList([">= 4.0.6", "< 4.1.1"]) if inject.checkBooleanExpression("'utf8'=(SELECT CHARSET(CURRENT_USER()))"): Backend.setVersion("= 4.1.0") else: Backend.setVersionList([">= 4.0.6", "< 4.1.0"]) else: Backend.setVersionList([">= 4.0.0", "< 4.0.6"]) else: Backend.setVersion("< 4.0.0") setDbms("%s 3" % DBMS.MYSQL) self.getBanner() return True else: warnMsg = "the back-end DBMS is not %s" % DBMS.MYSQL logger.warn(warnMsg) return False
def checkDbms(self): """ References for fingerprint: * https://www.postgresql.org/docs/current/static/release.html """ if not conf.extensiveFp and Backend.isDbmsWithin(PGSQL_ALIASES): setDbms(DBMS.PGSQL) self.getBanner() return True infoMsg = "testing %s" % DBMS.PGSQL logger.info(infoMsg) result = inject.checkBooleanExpression("QUOTE_IDENT(NULL) IS NULL") if result: infoMsg = "confirming %s" % DBMS.PGSQL logger.info(infoMsg) result = inject.checkBooleanExpression("COALESCE([RANDNUM], NULL)=[RANDNUM]") if not result: warnMsg = "the back-end DBMS is not %s" % DBMS.PGSQL logger.warn(warnMsg) return False setDbms(DBMS.PGSQL) self.getBanner() if not conf.extensiveFp: return True infoMsg = "actively fingerprinting %s" % DBMS.PGSQL logger.info(infoMsg) if inject.checkBooleanExpression("SHA256(NULL) IS NULL"): Backend.setVersion(">= 11.0") elif inject.checkBooleanExpression("XMLTABLE(NULL) IS NULL"): Backend.setVersionList([">= 10.0", "< 11.0"]) elif inject.checkBooleanExpression("SIND(0)=0"): Backend.setVersionList([">= 9.6.0", "< 10.0"]) elif inject.checkBooleanExpression("TO_JSONB(1) IS NOT NULL"): Backend.setVersionList([">= 9.5.0", "< 9.6.0"]) elif inject.checkBooleanExpression("JSON_TYPEOF(NULL) IS NULL"): Backend.setVersionList([">= 9.4.0", "< 9.5.0"]) elif inject.checkBooleanExpression("ARRAY_REPLACE(NULL,1,1) IS NULL"): Backend.setVersionList([">= 9.3.0", "< 9.4.0"]) elif inject.checkBooleanExpression("ROW_TO_JSON(NULL) IS NULL"): Backend.setVersionList([">= 9.2.0", "< 9.3.0"]) elif inject.checkBooleanExpression("REVERSE('sqlmap')='pamlqs'"): Backend.setVersionList([">= 9.1.0", "< 9.2.0"]) elif inject.checkBooleanExpression("LENGTH(TO_CHAR(1,'EEEE'))>0"): Backend.setVersionList([">= 9.0.0", "< 9.1.0"]) elif inject.checkBooleanExpression("2=(SELECT DIV(6,3))"): Backend.setVersionList([">= 8.4.0", "< 9.0.0"]) elif inject.checkBooleanExpression("EXTRACT(ISODOW FROM CURRENT_TIMESTAMP)<8"): Backend.setVersionList([">= 8.3.0", "< 8.4.0"]) elif inject.checkBooleanExpression("ISFINITE(TRANSACTION_TIMESTAMP())"): Backend.setVersionList([">= 8.2.0", "< 8.3.0"]) elif inject.checkBooleanExpression("9=(SELECT GREATEST(5,9,1))"): Backend.setVersionList([">= 8.1.0", "< 8.2.0"]) elif inject.checkBooleanExpression("3=(SELECT WIDTH_BUCKET(5.35,0.024,10.06,5))"): Backend.setVersionList([">= 8.0.0", "< 8.1.0"]) elif inject.checkBooleanExpression("'d'=(SELECT SUBSTR(MD5('sqlmap'),1,1))"): Backend.setVersionList([">= 7.4.0", "< 8.0.0"]) elif inject.checkBooleanExpression("'p'=(SELECT SUBSTR(CURRENT_SCHEMA(),1,1))"): Backend.setVersionList([">= 7.3.0", "< 7.4.0"]) elif inject.checkBooleanExpression("8=(SELECT BIT_LENGTH(1))"): Backend.setVersionList([">= 7.2.0", "< 7.3.0"]) elif inject.checkBooleanExpression("'a'=(SELECT SUBSTR(QUOTE_LITERAL('a'),2,1))"): Backend.setVersionList([">= 7.1.0", "< 7.2.0"]) elif inject.checkBooleanExpression("8=(SELECT POW(2,3))"): Backend.setVersionList([">= 7.0.0", "< 7.1.0"]) elif inject.checkBooleanExpression("'a'=(SELECT MAX('a'))"): Backend.setVersionList([">= 6.5.0", "< 6.5.3"]) elif inject.checkBooleanExpression("VERSION()=VERSION()"): Backend.setVersionList([">= 6.4.0", "< 6.5.0"]) elif inject.checkBooleanExpression("2=(SELECT SUBSTR(CURRENT_DATE,1,1))"): Backend.setVersionList([">= 6.3.0", "< 6.4.0"]) elif inject.checkBooleanExpression("'s'=(SELECT SUBSTRING('sqlmap',1,1))"): Backend.setVersionList([">= 6.2.0", "< 6.3.0"]) else: Backend.setVersion("< 6.2.0") return True else: warnMsg = "the back-end DBMS is not %s" % DBMS.PGSQL logger.warn(warnMsg) return False
def checkDbms(self): """ References for fingerprint: * http://www.postgresql.org/docs/9.1/interactive/release.html (up to 9.1.3) """ if not conf.extensiveFp and (Backend.isDbmsWithin(PGSQL_ALIASES) or conf.dbms in PGSQL_ALIASES): setDbms(DBMS.PGSQL) self.getBanner() return True infoMsg = "testing %s" % DBMS.PGSQL logger.info(infoMsg) randInt = getUnicode(randomInt(1)) result = inject.checkBooleanExpression( "%s::int=%s" % (randInt, randInt)) if result: infoMsg = "confirming %s" % DBMS.PGSQL logger.info(infoMsg) result = inject.checkBooleanExpression( "COALESCE(%s, NULL)=%s" % (randInt, randInt)) if not result: warnMsg = "the back-end DBMS is not %s" % DBMS.PGSQL logger.warn(warnMsg) return False setDbms(DBMS.PGSQL) self.getBanner() if not conf.extensiveFp: return True infoMsg = "actively fingerprinting %s" % DBMS.PGSQL logger.info(infoMsg) if inject.checkBooleanExpression("REVERSE('sqlmap')='pamlqs'"): Backend.setVersion(">= 9.1.0") elif inject.checkBooleanExpression("LENGTH(TO_CHAR(1, 'EEEE'))>0"): Backend.setVersionList([">= 9.0.0", "< 9.1.0"]) elif inject.checkBooleanExpression("2=(SELECT DIV(6, 3))"): Backend.setVersionList([">= 8.4.0", "< 9.0.0"]) elif inject.checkBooleanExpression( "EXTRACT(ISODOW FROM CURRENT_TIMESTAMP)<8"): Backend.setVersionList([">= 8.3.0", "< 8.4.0"]) elif inject.checkBooleanExpression( "ISFINITE(TRANSACTION_TIMESTAMP())"): Backend.setVersionList([">= 8.2.0", "< 8.3.0"]) elif inject.checkBooleanExpression("9=(SELECT GREATEST(5, 9, 1))"): Backend.setVersionList([">= 8.1.0", "< 8.2.0"]) elif inject.checkBooleanExpression( "3=(SELECT WIDTH_BUCKET(5.35, 0.024, 10.06, 5))"): Backend.setVersionList([">= 8.0.0", "< 8.1.0"]) elif inject.checkBooleanExpression( "'d'=(SELECT SUBSTR(MD5('sqlmap'), 1, 1))"): Backend.setVersionList([">= 7.4.0", "< 8.0.0"]) elif inject.checkBooleanExpression( "'p'=(SELECT SUBSTR(CURRENT_SCHEMA(), 1, 1))"): Backend.setVersionList([">= 7.3.0", "< 7.4.0"]) elif inject.checkBooleanExpression("8=(SELECT BIT_LENGTH(1))"): Backend.setVersionList([">= 7.2.0", "< 7.3.0"]) elif inject.checkBooleanExpression( "'a'=(SELECT SUBSTR(QUOTE_LITERAL('a'), 2, 1))"): Backend.setVersionList([">= 7.1.0", "< 7.2.0"]) elif inject.checkBooleanExpression("8=(SELECT POW(2, 3))"): Backend.setVersionList([">= 7.0.0", "< 7.1.0"]) elif inject.checkBooleanExpression("'a'=(SELECT MAX('a'))"): Backend.setVersionList([">= 6.5.0", "< 6.5.3"]) elif inject.checkBooleanExpression("VERSION()=VERSION()"): Backend.setVersionList([">= 6.4.0", "< 6.5.0"]) elif inject.checkBooleanExpression( "2=(SELECT SUBSTR(CURRENT_DATE, 1, 1))"): Backend.setVersionList([">= 6.3.0", "< 6.4.0"]) elif inject.checkBooleanExpression( "'s'=(SELECT SUBSTRING('sqlmap', 1, 1))"): Backend.setVersionList([">= 6.2.0", "< 6.3.0"]) else: Backend.setVersion("< 6.2.0") return True else: warnMsg = "the back-end DBMS is not %s" % DBMS.PGSQL logger.warn(warnMsg) return False
def checkDbms(self): """ References for fingerprint: * http://dev.mysql.com/doc/refman/5.0/en/news-5-0-x.html (up to 5.0.89) * http://dev.mysql.com/doc/refman/5.1/en/news-5-1-x.html (up to 5.1.42) * http://dev.mysql.com/doc/refman/5.4/en/news-5-4-x.html (up to 5.4.4) * http://dev.mysql.com/doc/refman/5.5/en/news-5-5-x.html (up to 5.5.0) * http://dev.mysql.com/doc/refman/6.0/en/news-6-0-x.html (manual has been withdrawn) """ if not conf.extensiveFp and Backend.isDbmsWithin(SHELL_ALIASES): setDbms("%s %s" % (DBMS.SHELL, Backend.getVersion())) if Backend.isVersionGreaterOrEqualThan("5"): kb.data.has_information_schema = True self.getBanner() return True infoMsg = "testing %s command injection" % DBMS.SHELL logger.info(infoMsg) result = inject.checkBooleanExpression( '$(expr substr "$(id)" 1 1) = "u"') if result: infoMsg = "confirming %s command injection" % DBMS.SHELL logger.info(infoMsg) result = inject.checkBooleanExpression( '$(expr substr "$(pwd)" 1 1) = "/"') if not result: # Note: MemSQL doesn't support SESSION_USER() result = inject.checkBooleanExpression( "GEOGRAPHY_AREA(NULL) IS NULL") if result: hashDBWrite(HASHDB_KEYS.DBMS_FORK, FORK.MEMSQL) if not result: warnMsg = "the back-end DBMS is not %s" % DBMS.SHELL logger.warn(warnMsg) return False # reading information_schema on some platforms is causing annoying timeout exits # Reference: http://bugs.mysql.com/bug.python?id=15855 # Determine if it is MySQL >= 8.0.0 if inject.checkBooleanExpression( "version_compare(pythonversion(), \"7.0\") >= 0"): kb.data.has_information_schema = True Backend.setVersion(">= 7.0") setDbms("%s 7" % DBMS.SHELL) self.getBanner() # Determine if it is MySQL >= 5.0.0 elif inject.checkBooleanExpression( "ISNULL(TIMESTAMPADD(MINUTE,[RANDNUM],NULL))"): kb.data.has_information_schema = True Backend.setVersion(">= 5.0.0") setDbms("%s 5" % DBMS.SHELL) self.getBanner() if not conf.extensiveFp: return True infoMsg = "actively fingerprinting %s" % DBMS.SHELL logger.info(infoMsg) # Check if it is MySQL >= 5.7 if inject.checkBooleanExpression("ISNULL(JSON_QUOTE(NULL))"): Backend.setVersion(">= 5.7") # Check if it is MySQL >= 5.6 elif inject.checkBooleanExpression( "ISNULL(VALIDATE_PASSWORD_STRENGTH(NULL))"): Backend.setVersion(">= 5.6") # Check if it is MySQL >= 5.5 elif inject.checkBooleanExpression("TO_SECONDS(950501)>0"): Backend.setVersion(">= 5.5") # Check if it is MySQL >= 5.1.2 and < 5.5.0 elif inject.checkBooleanExpression( "@@table_open_cache=@@table_open_cache"): if inject.checkBooleanExpression( "[RANDNUM]=(SELECT [RANDNUM] FROM information_schema.GLOBAL_STATUS LIMIT 0, 1)" ): Backend.setVersionList([">= 5.1.12", "< 5.5.0"]) elif inject.checkBooleanExpression( "[RANDNUM]=(SELECT [RANDNUM] FROM information_schema.PROCESSLIST LIMIT 0, 1)" ): Backend.setVersionList([">= 5.1.7", "< 5.1.12"]) elif inject.checkBooleanExpression( "[RANDNUM]=(SELECT [RANDNUM] FROM information_schema.PARTITIONS LIMIT 0, 1)" ): Backend.setVersion("= 5.1.6") elif inject.checkBooleanExpression( "[RANDNUM]=(SELECT [RANDNUM] FROM information_schema.PLUGINS LIMIT 0, 1)" ): Backend.setVersionList([">= 5.1.5", "< 5.1.6"]) else: Backend.setVersionList([">= 5.1.2", "< 5.1.5"]) # Check if it is MySQL >= 5.0.0 and < 5.1.2 elif inject.checkBooleanExpression("@@hostname=@@hostname"): Backend.setVersionList([">= 5.0.38", "< 5.1.2"]) elif inject.checkBooleanExpression( "@@character_set_filesystem=@@character_set_filesystem" ): Backend.setVersionList([">= 5.0.19", "< 5.0.38"]) elif not inject.checkBooleanExpression( "[RANDNUM]=(SELECT [RANDNUM] FROM DUAL WHERE [RANDNUM1]!=[RANDNUM2])" ): Backend.setVersionList([">= 5.0.11", "< 5.0.19"]) elif inject.checkBooleanExpression( "@@div_precision_increment=@@div_precision_increment"): Backend.setVersionList([">= 5.0.6", "< 5.0.11"]) elif inject.checkBooleanExpression( "@@automatic_sp_privileges=@@automatic_sp_privileges"): Backend.setVersionList([">= 5.0.3", "< 5.0.6"]) else: Backend.setVersionList([">= 5.0.0", "< 5.0.3"]) elif inject.checkBooleanExpression("DATABASE() LIKE SCHEMA()"): Backend.setVersion(">= 5.0.2") setDbms("%s 5" % DBMS.SHELL) self.getBanner() elif inject.checkBooleanExpression( "STRCMP(LOWER(CURRENT_USER()), UPPER(CURRENT_USER()))=0"): Backend.setVersion("< 5.0.0") setDbms("%s 4" % DBMS.SHELL) self.getBanner() if not conf.extensiveFp: return True # Check which version of MySQL < 5.0.0 it is if inject.checkBooleanExpression( "3=(SELECT COERCIBILITY(USER()))"): Backend.setVersionList([">= 4.1.11", "< 5.0.0"]) elif inject.checkBooleanExpression( "2=(SELECT COERCIBILITY(USER()))"): Backend.setVersionList([">= 4.1.1", "< 4.1.11"]) elif inject.checkBooleanExpression( "CURRENT_USER()=CURRENT_USER()"): Backend.setVersionList([">= 4.0.6", "< 4.1.1"]) if inject.checkBooleanExpression( "'utf8'=(SELECT CHARSET(CURRENT_USER()))"): Backend.setVersion("= 4.1.0") else: Backend.setVersionList([">= 4.0.6", "< 4.1.0"]) else: Backend.setVersionList([">= 4.0.0", "< 4.0.6"]) else: Backend.setVersion("< 4.0.0") setDbms("%s 3" % DBMS.SHELL) self.getBanner() return True else: warnMsg = "the back-end DBMS is not %s" % DBMS.SHELL logger.warn(warnMsg) return False
def resumeConfKb(expression, url, value): if expression == "Injection data" and url == conf.url: injection = base64unpickle(value[:-1]) logMsg = "resuming injection data from session file" logger.info(logMsg) if injection.place in conf.paramDict and \ injection.parameter in conf.paramDict[injection.place]: if not conf.tech or intersect(conf.tech, injection.data.keys()): if intersect(conf.tech, injection.data.keys()): injection.data = dict( filter(lambda (key, item): key in conf.tech, injection.data.items())) if injection not in kb.injections: kb.injections.append(injection) else: warnMsg = "there is an injection in %s parameter '%s' " % ( injection.place, injection.parameter) warnMsg += "but you did not provided it this time" logger.warn(warnMsg) elif expression == "Dynamic markings" and url == conf.url: kb.dynamicMarkings = base64unpickle(value[:-1]) logMsg = "resuming dynamic markings from session file" logger.info(logMsg) elif expression == "DBMS" and url == conf.url: dbms = unSafeFormatString(value[:-1]) dbms = dbms.lower() dbmsVersion = [UNKNOWN_DBMS_VERSION] logMsg = "resuming back-end DBMS '%s' " % dbms logMsg += "from session file" logger.info(logMsg) firstRegExp = "(%s)" % ("|".join([alias for alias in SUPPORTED_DBMS])) dbmsRegExp = re.search("%s ([\d\.]+)" % firstRegExp, dbms) if dbmsRegExp: dbms = dbmsRegExp.group(1) dbmsVersion = [dbmsRegExp.group(2)] if conf.dbms and conf.dbms.lower() != dbms: message = "you provided '%s' as back-end DBMS, " % conf.dbms message += "but from a past scan information on the target URL " message += "sqlmap assumes the back-end DBMS is %s. " % dbms message += "Do you really want to force the back-end " message += "DBMS value? [y/N] " test = readInput(message, default="N") if not test or test[0] in ("n", "N"): Backend.setDbms(dbms) Backend.setVersionList(dbmsVersion) else: Backend.setDbms(dbms) Backend.setVersionList(dbmsVersion) elif expression == "OS" and url == conf.url: os = unSafeFormatString(value[:-1]) if os and os != 'None': logMsg = "resuming back-end DBMS operating system '%s' " % os logMsg += "from session file" logger.info(logMsg) if conf.os and conf.os.lower() != os.lower(): message = "you provided '%s' as back-end DBMS operating " % conf.os message += "system, but from a past scan information on the " message += "target URL sqlmap assumes the back-end DBMS " message += "operating system is %s. " % os message += "Do you really want to force the back-end DBMS " message += "OS value? [y/N] " test = readInput(message, default="N") if not test or test[0] in ("n", "N"): conf.os = os else: conf.os = os elif expression == "Remote temp path" and url == conf.url: conf.tmpPath = unSafeFormatString(value[:-1]) logMsg = "resuming remote absolute path of temporary " logMsg += "files directory '%s' from session file" % conf.tmpPath logger.info(logMsg) elif expression == "TABLE_EXISTS" and url == conf.url: table = unSafeFormatString(value[:-1]) split = '..' if Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) else '.' if split in table: db, table = table.split(split) else: db = "%s%s" % (Backend.getIdentifiedDbms(), METADB_SUFFIX) logMsg = "resuming brute forced table name " logMsg += "'%s' from session file" % table logger.info(logMsg) kb.brute.tables.append((db, table)) elif expression == "COLUMN_EXISTS" and url == conf.url: table, column = unSafeFormatString(value[:-1]).split('|') colName, colType = column.split(' ') split = '..' if Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) else '.' if split in table: db, table = table.split(split) else: db = "%s%s" % (Backend.getIdentifiedDbms(), METADB_SUFFIX) logMsg = "resuming brute forced column name " logMsg += "'%s' for table '%s' from session file" % (colName, table) logger.info(logMsg) kb.brute.columns.append((db, table, colName, colType))
def resumeConfKb(expression, url, value): if expression == "Injection data" and url == conf.url: try: injection = base64unpickle(value[:-1]) except AttributeError: warnMsg = "there were some changes in data model " warnMsg += "preventing normal resume of previously stored " warnMsg += "injection data. please use the --flush-session " warnMsg += "to have it fixed" singleTimeWarnMessage(warnMsg) return infoMsg = "resuming injection data from session file" logger.info(infoMsg) if injection.place in conf.paramDict and \ injection.parameter in conf.paramDict[injection.place]: if not conf.tech or intersect(conf.tech, injection.data.keys()): if intersect(conf.tech, injection.data.keys()): injection.data = dict(filter(lambda (key, item): key in conf.tech, injection.data.items())) if injection not in kb.injections: kb.injections.append(injection) else: warnMsg = "there is an injection in %s parameter '%s' " % (injection.place, injection.parameter) warnMsg += "but you did not provided it this time" logger.warn(warnMsg) elif expression == "Dynamic markings" and url == conf.url: kb.dynamicMarkings = base64unpickle(value[:-1]) infoMsg = "resuming dynamic markings from session file" logger.info(infoMsg) elif expression == "DBMS" and url == conf.url: dbms = unSafeFormatString(value[:-1]) dbms = dbms.lower() dbmsVersion = [UNKNOWN_DBMS_VERSION] infoMsg = "resuming back-end DBMS '%s' " % dbms infoMsg += "from session file" logger.info(infoMsg) firstRegExp = "(%s)" % ("|".join([alias for alias in SUPPORTED_DBMS])) dbmsRegExp = re.search("%s ([\d\.]+)" % firstRegExp, dbms) if dbmsRegExp: dbms = dbmsRegExp.group(1) dbmsVersion = [ dbmsRegExp.group(2) ] if conf.dbms and conf.dbms.lower() != dbms: message = "you provided '%s' as back-end DBMS, " % conf.dbms message += "but from a past scan information on the target URL " message += "sqlmap assumes the back-end DBMS is %s. " % dbms message += "Do you really want to force the back-end " message += "DBMS value? [y/N] " test = readInput(message, default="N") if not test or test[0] in ("n", "N"): conf.dbms = None Backend.setDbms(dbms) Backend.setVersionList(dbmsVersion) else: Backend.setDbms(dbms) Backend.setVersionList(dbmsVersion) elif expression == "OS" and url == conf.url: os = unSafeFormatString(value[:-1]) if os and os != 'None': infoMsg = "resuming back-end DBMS operating system '%s' " % os infoMsg += "from session file" logger.info(infoMsg) if conf.os and conf.os.lower() != os.lower(): message = "you provided '%s' as back-end DBMS operating " % conf.os message += "system, but from a past scan information on the " message += "target URL sqlmap assumes the back-end DBMS " message += "operating system is %s. " % os message += "Do you really want to force the back-end DBMS " message += "OS value? [y/N] " test = readInput(message, default="N") if not test or test[0] in ("n", "N"): conf.os = os else: conf.os = os Backend.setOs(conf.os) elif expression == "Remote temp path" and url == conf.url and conf.tmpPath is None: conf.tmpPath = unSafeFormatString(value[:-1]) infoMsg = "resuming remote absolute path of temporary " infoMsg += "files directory '%s' from session file" % conf.tmpPath logger.info(infoMsg) elif conf.freshQueries: pass elif expression == "TABLE_EXISTS" and url == conf.url: table = unSafeFormatString(value[:-1]) split = '..' if Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) else '.' if split in table: db, table = table.split(split) else: db = "%s%s" % (Backend.getIdentifiedDbms(), METADB_SUFFIX) infoMsg = "resuming brute forced table name " infoMsg += "'%s' from session file" % table logger.info(infoMsg) kb.brute.tables.append((db, table)) elif expression == "COLUMN_EXISTS" and url == conf.url: table, column = unSafeFormatString(value[:-1]).split('|') colName, colType = column.split(' ') split = '..' if Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) else '.' if split in table: db, table = table.split(split) else: db = "%s%s" % (Backend.getIdentifiedDbms(), METADB_SUFFIX) infoMsg = "resuming brute forced column name " infoMsg += "'%s' for table '%s' from session file" % (colName, table) logger.info(infoMsg) kb.brute.columns.append((db, table, colName, colType)) elif expression == "xp_cmdshell availability" and url == conf.url: kb.xpCmdshellAvailable = True if unSafeFormatString(value[:-1]).lower() == "true" else False infoMsg = "resuming xp_cmdshell availability" logger.info(infoMsg)
def checkDbms(self): """ References for fingerprint: * http://dev.mysql.com/doc/refman/5.0/en/news-5-0-x.html (up to 5.0.89) * http://dev.mysql.com/doc/refman/5.1/en/news-5-1-x.html (up to 5.1.42) * http://dev.mysql.com/doc/refman/5.4/en/news-5-4-x.html (up to 5.4.4) * http://dev.mysql.com/doc/refman/5.5/en/news-5-5-x.html (up to 5.5.0) * http://dev.mysql.com/doc/refman/6.0/en/news-6-0-x.html (manual has been withdrawn) """ if not conf.extensiveFp and Backend.isDbmsWithin(MYSQL_ALIASES): setDbms("%s %s" % (DBMS.MYSQL, Backend.getVersion())) if Backend.isVersionGreaterOrEqualThan("5"): kb.data.has_information_schema = True self.getBanner() return True infoMsg = "testing %s" % DBMS.MYSQL logger.info(infoMsg) result = inject.checkBooleanExpression("QUARTER(NULL) IS NULL") if result: infoMsg = "confirming %s" % DBMS.MYSQL logger.info(infoMsg) result = inject.checkBooleanExpression("SESSION_USER() LIKE USER()") if not result: warnMsg = "the back-end DBMS is not %s" % DBMS.MYSQL logger.warn(warnMsg) return False if hashDBRetrieve(HASHDB_KEYS.DBMS_FORK) is None: hashDBWrite(HASHDB_KEYS.DBMS_FORK, inject.checkBooleanExpression("VERSION() LIKE '%MariaDB%'") and "MariaDB" or "") # reading information_schema on some platforms is causing annoying timeout exits # Reference: http://bugs.mysql.com/bug.php?id=15855 # Determine if it is MySQL >= 5.0.0 if inject.checkBooleanExpression("ISNULL(TIMESTAMPADD(MINUTE,[RANDNUM],NULL))"): kb.data.has_information_schema = True Backend.setVersion(">= 5.0.0") setDbms("%s 5" % DBMS.MYSQL) self.getBanner() if not conf.extensiveFp: return True infoMsg = "actively fingerprinting %s" % DBMS.MYSQL logger.info(infoMsg) # Check if it is MySQL >= 5.5.0 if inject.checkBooleanExpression("TO_SECONDS(950501)>0"): Backend.setVersion(">= 5.5.0") # Check if it is MySQL >= 5.1.2 and < 5.5.0 elif inject.checkBooleanExpression("@@table_open_cache=@@table_open_cache"): if inject.checkBooleanExpression("[RANDNUM]=(SELECT [RANDNUM] FROM information_schema.GLOBAL_STATUS LIMIT 0, 1)"): Backend.setVersionList([">= 5.1.12", "< 5.5.0"]) elif inject.checkBooleanExpression("[RANDNUM]=(SELECT [RANDNUM] FROM information_schema.PROCESSLIST LIMIT 0, 1)"): Backend.setVersionList([">= 5.1.7", "< 5.1.12"]) elif inject.checkBooleanExpression("[RANDNUM]=(SELECT [RANDNUM] FROM information_schema.PARTITIONS LIMIT 0, 1)"): Backend.setVersion("= 5.1.6") elif inject.checkBooleanExpression("[RANDNUM]=(SELECT [RANDNUM] FROM information_schema.PLUGINS LIMIT 0, 1)"): Backend.setVersionList([">= 5.1.5", "< 5.1.6"]) else: Backend.setVersionList([">= 5.1.2", "< 5.1.5"]) # Check if it is MySQL >= 5.0.0 and < 5.1.2 elif inject.checkBooleanExpression("@@hostname=@@hostname"): Backend.setVersionList([">= 5.0.38", "< 5.1.2"]) elif inject.checkBooleanExpression("@@character_set_filesystem=@@character_set_filesystem"): Backend.setVersionList([">= 5.0.19", "< 5.0.38"]) elif not inject.checkBooleanExpression("[RANDNUM]=(SELECT [RANDNUM] FROM DUAL WHERE [RANDNUM1]!=[RANDNUM2])"): Backend.setVersionList([">= 5.0.11", "< 5.0.19"]) elif inject.checkBooleanExpression("@@div_precision_increment=@@div_precision_increment"): Backend.setVersionList([">= 5.0.6", "< 5.0.11"]) elif inject.checkBooleanExpression("@@automatic_sp_privileges=@@automatic_sp_privileges"): Backend.setVersionList([">= 5.0.3", "< 5.0.6"]) else: Backend.setVersionList([">= 5.0.0", "< 5.0.3"]) elif inject.checkBooleanExpression("DATABASE() LIKE SCHEMA()"): Backend.setVersion(">= 5.0.2") setDbms("%s 5" % DBMS.MYSQL) self.getBanner() elif inject.checkBooleanExpression("STRCMP(LOWER(CURRENT_USER()), UPPER(CURRENT_USER()))=0"): Backend.setVersion("< 5.0.0") setDbms("%s 4" % DBMS.MYSQL) self.getBanner() if not conf.extensiveFp: return True # Check which version of MySQL < 5.0.0 it is if inject.checkBooleanExpression("3=(SELECT COERCIBILITY(USER()))"): Backend.setVersionList([">= 4.1.11", "< 5.0.0"]) elif inject.checkBooleanExpression("2=(SELECT COERCIBILITY(USER()))"): Backend.setVersionList([">= 4.1.1", "< 4.1.11"]) elif inject.checkBooleanExpression("CURRENT_USER()=CURRENT_USER()"): Backend.setVersionList([">= 4.0.6", "< 4.1.1"]) if inject.checkBooleanExpression("'utf8'=(SELECT CHARSET(CURRENT_USER()))"): Backend.setVersion("= 4.1.0") else: Backend.setVersionList([">= 4.0.6", "< 4.1.0"]) else: Backend.setVersionList([">= 4.0.0", "< 4.0.6"]) else: Backend.setVersion("< 4.0.0") setDbms("%s 3" % DBMS.MYSQL) self.getBanner() return True else: warnMsg = "the back-end DBMS is not %s" % DBMS.MYSQL logger.warn(warnMsg) return False