(expression, unpack=True, dump=False)
return value
This function tests for an union SQL injection on the target
    URL then call its subsidiary function to effectively perform an
    union SQL injection on the affected URL
This function tests for an union SQL injection on the target
    URL then call its subsidiary function to effectively perform an
    union SQL injection on the affected URL
This function tests for an union SQL injection on the target URL then call its subsidiary function to effectively perform an union SQL injection on the affected URL
def unionUse(expression, unpack=True, dump=False):
    """
    This function tests for an union SQL injection on the target
    URL then call its subsidiary function to effectively perform an
    union SQL injection on the affected URL
    """

    initTechnique(PAYLOAD.TECHNIQUE.UNION)

    abortedFlag = False
    count = None
    origExpr = expression
    startLimit = 0
    stopLimit = None
    value = None

    width = getConsoleWidth()
    start = time.time()

    _, _, _, _, _, expressionFieldsList, expressionFields, _ = agent.getFields(origExpr)

    # Set kb.partRun in case the engine is called from the API
    kb.partRun = getPartRun(alias=False) if hasattr(conf, "api") else None

    if expressionFieldsList and len(expressionFieldsList) > 1 and "ORDER BY" in expression.upper():
        # Removed ORDER BY clause because UNION does not play well with it
        expression = re.sub("\s*ORDER BY\s+[\w,]+", "", expression, re.I)
        debugMsg = "stripping ORDER BY clause from statement because "
        debugMsg += "it does not play well with UNION query SQL injection"
        singleTimeDebugMessage(debugMsg)

    # We have to check if the SQL query might return multiple entries
    # if the technique is partial UNION query and in such case forge the
    # SQL limiting the query output one entry at a time
    # NOTE: we assume that only queries that get data from a table can
    # return multiple entries
    if (kb.injection.data[PAYLOAD.TECHNIQUE.UNION].where == PAYLOAD.WHERE.NEGATIVE or \
       kb.forcePartialUnion or \
       (dump and (conf.limitStart or conf.limitStop)) or "LIMIT " in expression.upper()) and \
       " FROM " in expression.upper() and ((Backend.getIdentifiedDbms() \
       not in FROM_DUMMY_TABLE) or (Backend.getIdentifiedDbms() in FROM_DUMMY_TABLE \
       and not expression.upper().endswith(FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()]))) \
       and not re.search(SQL_SCALAR_REGEX, expression, re.I):
        expression, limitCond, topLimit, startLimit, stopLimit = agent.limitCondition(expression, dump)

        if limitCond:
            # Count the number of SQL query entries output
            countedExpression = expression.replace(expressionFields, queries[Backend.getIdentifiedDbms()].count.query % ('*' if len(expressionFieldsList) > 1 else expressionFields), 1)

            if " ORDER BY " in countedExpression.upper():
                _ = countedExpression.upper().rindex(" ORDER BY ")
                countedExpression = countedExpression[:_]

            output = _oneShotUnionUse(countedExpression, unpack)
            count = unArrayizeValue(parseUnionPage(output))

            if isNumPosStrValue(count):
                if isinstance(stopLimit, int) and stopLimit > 0:
                    stopLimit = min(int(count), int(stopLimit))
                else:
                    stopLimit = int(count)

                    infoMsg = "the SQL query used returns "
                    infoMsg += "%d entries" % stopLimit
                    logger.info(infoMsg)

            elif count and (not isinstance(count, basestring) or not count.isdigit()):
                warnMsg = "it was not possible to count the number "
                warnMsg += "of entries for the SQL query provided. "
                warnMsg += "sqlmap will assume that it returns only "
                warnMsg += "one entry"
                logger.warn(warnMsg)

                stopLimit = 1

            elif (not count or int(count) == 0):
                if not count:
                    warnMsg = "the SQL query provided does not "
                    warnMsg += "return any output"
                    logger.warn(warnMsg)
                else:
                    value = []  # for empty tables
                return value

            threadData = getCurrentThreadData()
            threadData.shared.limits = iter(xrange(startLimit, stopLimit))
            numThreads = min(conf.threads, (stopLimit - startLimit))
            threadData.shared.value = BigArray()
            threadData.shared.buffered = []
            threadData.shared.counter = 0
            threadData.shared.lastFlushed = startLimit - 1
            threadData.shared.showEta = conf.eta and (stopLimit - startLimit) > 1

            if threadData.shared.showEta:
                threadData.shared.progress = ProgressBar(maxValue=(stopLimit - startLimit))

            if stopLimit > TURN_OFF_RESUME_INFO_LIMIT:
                kb.suppressResumeInfo = True
                debugMsg = "suppressing possible resume console info because of "
                debugMsg += "large number of rows. It might take too long"
                logger.debug(debugMsg)

            try:
                def unionThread():
                    threadData = getCurrentThreadData()

                    while kb.threadContinue:
                        with kb.locks.limit:
                            try:
                                valueStart = time.time()
                                threadData.shared.counter += 1
                                num = threadData.shared.limits.next()
                            except StopIteration:
                                break

                        if Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
                            field = expressionFieldsList[0]
                        elif Backend.isDbms(DBMS.ORACLE):
                            field = expressionFieldsList
                        else:
                            field = None

                        limitedExpr = agent.limitQuery(num, expression, field)
                        output = _oneShotUnionUse(limitedExpr, unpack, True)

                        if not kb.threadContinue:
                            break

                        if output:
                            with kb.locks.value:
                                if all(map(lambda _: _ in output, (kb.chars.start, kb.chars.stop))):
                                    items = parseUnionPage(output)

                                    if threadData.shared.showEta:
                                        threadData.shared.progress.progress(time.time() - valueStart, threadData.shared.counter)
                                    if isListLike(items):
                                        # in case that we requested N columns and we get M!=N then we have to filter a bit
                                        if len(items) > 1 and len(expressionFieldsList) > 1:
                                            items = [item for item in items if isListLike(item) and len(item) == len(expressionFieldsList)]
                                        items = [_ for _ in flattenValue(items)]
                                        if len(items) > len(expressionFieldsList):
                                            filtered = OrderedDict()
                                            for item in items:
                                                key = re.sub(r"[^A-Za-z0-9]", "", item).lower()
                                                if key not in filtered or re.search(r"[^A-Za-z0-9]", item):
                                                    filtered[key] = item
                                            items = filtered.values()
                                        items = [items]
                                    index = None
                                    for index in xrange(len(threadData.shared.buffered)):
                                        if threadData.shared.buffered[index][0] >= num:
                                            break
                                    threadData.shared.buffered.insert(index or 0, (num, items))
                                else:
                                    index = None
                                    if threadData.shared.showEta:
                                        threadData.shared.progress.progress(time.time() - valueStart, threadData.shared.counter)
                                    for index in xrange(len(threadData.shared.buffered)):
                                        if threadData.shared.buffered[index][0] >= num:
                                            break
                                    threadData.shared.buffered.insert(index or 0, (num, None))

                                    items = output.replace(kb.chars.start, "").replace(kb.chars.stop, "").split(kb.chars.delimiter)

                                while threadData.shared.buffered and (threadData.shared.lastFlushed + 1 >= threadData.shared.buffered[0][0] or len(threadData.shared.buffered) > MAX_BUFFERED_PARTIAL_UNION_LENGTH):
                                    threadData.shared.lastFlushed, _ = threadData.shared.buffered[0]
                                    if not isNoneValue(_):
                                        threadData.shared.value.extend(arrayizeValue(_))
                                    del threadData.shared.buffered[0]

                            if conf.verbose == 1 and not (threadData.resumed and kb.suppressResumeInfo) and not threadData.shared.showEta:
                                status = "[%s] [INFO] %s: %s" % (time.strftime("%X"), "resumed" if threadData.resumed else "retrieved", safecharencode(",".join("\"%s\"" % _ for _ in flattenValue(arrayizeValue(items))) if not isinstance(items, basestring) else items))

                                if len(status) > width:
                                    status = "%s..." % status[:width - 3]

                                dataToStdout("%s\n" % status, True)

                runThreads(numThreads, unionThread)

                if conf.verbose == 1:
                    clearConsoleLine(True)

            except KeyboardInterrupt:
                abortedFlag = True

                warnMsg = "user aborted during enumeration. sqlmap "
                warnMsg += "will display partial output"
                logger.warn(warnMsg)

            finally:
                for _ in sorted(threadData.shared.buffered):
                    if not isNoneValue(_[1]):
                        threadData.shared.value.extend(arrayizeValue(_[1]))
                value = threadData.shared.value
                kb.suppressResumeInfo = False

    if not value and not abortedFlag:
        output = _oneShotUnionUse(expression, unpack)
        value = parseUnionPage(output)

    duration = calculateDeltaSeconds(start)

    if not kb.bruteMode:
        debugMsg = "performed %d queries in %.2f seconds" % (kb.counters[PAYLOAD.TECHNIQUE.UNION], duration)
        logger.debug(debugMsg)

    return value
def unionUse ( expression , unpack = True , dump = False ) : initTechnique ( PAYLOAD . TECHNIQUE . UNION ) abortedFlag = False count = None origExpr = expression startLimit = 0 stopLimit = None value = None width = getConsoleWidth ( ) start = time . time ( ) _ , _ , _ , _ , _ , expressionFieldsList , expressionFields , _ = agent . getFields ( origExpr ) # Set kb.partRun in case the engine is called from the API kb . partRun = getPartRun ( alias = False ) if hasattr ( conf , "api" ) else None if expressionFieldsList and len ( expressionFieldsList ) > 1 and "ORDER BY" in expression . upper ( ) : # Removed ORDER BY clause because UNION does not play well with it expression = re . sub ( "\s*ORDER BY\s+[\w,]+" , "" , expression , re . I ) debugMsg = "stripping ORDER BY clause from statement because " debugMsg += "it does not play well with UNION query SQL injection" singleTimeDebugMessage ( debugMsg ) # We have to check if the SQL query might return multiple entries # if the technique is partial UNION query and in such case forge the # SQL limiting the query output one entry at a time # NOTE: we assume that only queries that get data from a table can # return multiple entries if ( kb . injection . data [ PAYLOAD . TECHNIQUE . UNION ] . where == PAYLOAD . WHERE . NEGATIVE or kb . forcePartialUnion or ( dump and ( conf . limitStart or conf . limitStop ) ) or "LIMIT " in expression . upper ( ) ) and " FROM " in expression . upper ( ) and ( ( Backend . getIdentifiedDbms ( ) not in FROM_DUMMY_TABLE ) or ( Backend . getIdentifiedDbms ( ) in FROM_DUMMY_TABLE and not expression . upper ( ) . endswith ( FROM_DUMMY_TABLE [ Backend . getIdentifiedDbms ( ) ] ) ) ) and not re . search ( SQL_SCALAR_REGEX , expression , re . I ) : expression , limitCond , topLimit , startLimit , stopLimit = agent . limitCondition ( expression , dump ) if limitCond : # Count the number of SQL query entries output countedExpression = expression . replace ( expressionFields , queries [ Backend . getIdentifiedDbms ( ) ] . count . query % ( '*' if len ( expressionFieldsList ) > 1 else expressionFields ) , 1 ) if " ORDER BY " in countedExpression . upper ( ) : _ = countedExpression . upper ( ) . rindex ( " ORDER BY " ) countedExpression = countedExpression [ : _ ] output = _oneShotUnionUse ( countedExpression , unpack ) count = unArrayizeValue ( parseUnionPage ( output ) ) if isNumPosStrValue ( count ) : if isinstance ( stopLimit , int ) and stopLimit > 0 : stopLimit = min ( int ( count ) , int ( stopLimit ) ) else : stopLimit = int ( count ) infoMsg = "the SQL query used returns " infoMsg += "%d entries" % stopLimit logger . info ( infoMsg ) elif count and ( not isinstance ( count , basestring ) or not count . isdigit ( ) ) : warnMsg = "it was not possible to count the number " warnMsg += "of entries for the SQL query provided. " warnMsg += "sqlmap will assume that it returns only " warnMsg += "one entry" logger . warn ( warnMsg ) stopLimit = 1 elif ( not count or int ( count ) == 0 ) : if not count : warnMsg = "the SQL query provided does not " warnMsg += "return any output" logger . warn ( warnMsg ) else : value = [ ] # for empty tables return value threadData = getCurrentThreadData ( ) threadData . shared . limits = iter ( xrange ( startLimit , stopLimit ) ) numThreads = min ( conf . threads , ( stopLimit - startLimit ) ) threadData . shared . value = BigArray ( ) threadData . shared . buffered = [ ] threadData . shared . counter = 0 threadData . shared . lastFlushed = startLimit - 1 threadData . shared . showEta = conf . eta and ( stopLimit - startLimit ) > 1 if threadData . shared . showEta : threadData . shared . progress = ProgressBar ( maxValue = ( stopLimit - startLimit ) ) if stopLimit > TURN_OFF_RESUME_INFO_LIMIT : kb . suppressResumeInfo = True debugMsg = "suppressing possible resume console info because of " debugMsg += "large number of rows. It might take too long" logger . debug ( debugMsg ) try : def unionThread ( ) : threadData = getCurrentThreadData ( ) while kb . threadContinue : with kb . locks . limit : try : valueStart = time . time ( ) threadData . shared . counter += 1 num = threadData . shared . limits . next ( ) except StopIteration : break if Backend . getIdentifiedDbms ( ) in ( DBMS . MSSQL , DBMS . SYBASE ) : field = expressionFieldsList [ 0 ] elif Backend . isDbms ( DBMS . ORACLE ) : field = expressionFieldsList else : field = None limitedExpr = agent . limitQuery ( num , expression , field ) output = _oneShotUnionUse ( limitedExpr , unpack , True ) if not kb . threadContinue : break if output : with kb . locks . value : if all ( map ( lambda _ : _ in output , ( kb . chars . start , kb . chars . stop ) ) ) : items = parseUnionPage ( output ) if threadData . shared . showEta : threadData . shared . progress . progress ( time . time ( ) - valueStart , threadData . shared . counter ) if isListLike ( items ) : # in case that we requested N columns and we get M!=N then we have to filter a bit if len ( items ) > 1 and len ( expressionFieldsList ) > 1 : items = [ item for item in items if isListLike ( item ) and len ( item ) == len ( expressionFieldsList ) ] items = [ _ for _ in flattenValue ( items ) ] if len ( items ) > len ( expressionFieldsList ) : filtered = OrderedDict ( ) for item in items : key = re . sub ( r"[^A-Za-z0-9]" , "" , item ) . lower ( ) if key not in filtered or re . search ( r"[^A-Za-z0-9]" , item ) : filtered [ key ] = item items = filtered . values ( ) items = [ items ] index = None for index in xrange ( len ( threadData . shared . buffered ) ) : if threadData . shared . buffered [ index ] [ 0 ] >= num : break threadData . shared . buffered . insert ( index or 0 , ( num , items ) ) else : index = None if threadData . shared . showEta : threadData . shared . progress . progress ( time . time ( ) - valueStart , threadData . shared . counter ) for index in xrange ( len ( threadData . shared . buffered ) ) : if threadData . shared . buffered [ index ] [ 0 ] >= num : break threadData . shared . buffered . insert ( index or 0 , ( num , None ) ) items = output . replace ( kb . chars . start , "" ) . replace ( kb . chars . stop , "" ) . split ( kb . chars . delimiter ) while threadData . shared . buffered and ( threadData . shared . lastFlushed + 1 >= threadData . shared . buffered [ 0 ] [ 0 ] or len ( threadData . shared . buffered ) > MAX_BUFFERED_PARTIAL_UNION_LENGTH ) : threadData . shared . lastFlushed , _ = threadData . shared . buffered [ 0 ] if not isNoneValue ( _ ) : threadData . shared . value . extend ( arrayizeValue ( _ ) ) del threadData . shared . buffered [ 0 ] if conf . verbose == 1 and not ( threadData . resumed and kb . suppressResumeInfo ) and not threadData . shared . showEta : status = "[%s] [INFO] %s: %s" % ( time . strftime ( "%X" ) , "resumed" if threadData . resumed else "retrieved" , safecharencode ( "," . join ( "\"%s\"" % _ for _ in flattenValue ( arrayizeValue ( items ) ) ) if not isinstance ( items , basestring ) else items ) ) if len ( status ) > width : status = "%s..." % status [ : width - 3 ] dataToStdout ( "%s\n" % status , True ) runThreads ( numThreads , unionThread ) if conf . verbose == 1 : clearConsoleLine ( True ) except KeyboardInterrupt : abortedFlag = True warnMsg = "user aborted during enumeration. sqlmap " warnMsg += "will display partial output" logger . warn ( warnMsg ) finally : for _ in sorted ( threadData . shared . buffered ) : if not isNoneValue ( _ [ 1 ] ) : threadData . shared . value . extend ( arrayizeValue ( _ [ 1 ] ) ) value = threadData . shared . value kb . suppressResumeInfo = False if not value and not abortedFlag : output = _oneShotUnionUse ( expression , unpack ) value = parseUnionPage ( output ) duration = calculateDeltaSeconds ( start ) if not kb . bruteMode : debugMsg = "performed %d queries in %.2f seconds" % ( kb . counters [ PAYLOAD . TECHNIQUE . UNION ] , duration ) logger . debug ( debugMsg ) return value