From 775e0df04b05e88368a56720c2106d5e71de7c94 Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Wed, 5 Dec 2012 10:45:17 +0100 Subject: [PATCH] Update for an Issue #278 --- extra/shutils/_sqlmap.py | 2 +- lib/controller/controller.py | 2 +- lib/core/defaults.py | 2 +- lib/core/enums.py | 4 +++- lib/core/threads.py | 2 +- lib/request/inject.py | 6 +++--- lib/takeover/xp_cmdshell.py | 2 +- lib/techniques/error/use.py | 8 ++++---- plugins/dbms/mssqlserver/enumeration.py | 6 +++--- plugins/dbms/oracle/enumeration.py | 2 +- plugins/dbms/sybase/enumeration.py | 8 ++++---- plugins/generic/databases.py | 8 ++++---- plugins/generic/entries.py | 2 +- plugins/generic/search.py | 6 +++--- plugins/generic/users.py | 6 +++--- sqlmap.conf | 4 ++-- xml/payloads.xml | 19 ++++++++++--------- 17 files changed, 46 insertions(+), 43 deletions(-) diff --git a/extra/shutils/_sqlmap.py b/extra/shutils/_sqlmap.py index a5f7625f9..f7fb88d3b 100644 --- a/extra/shutils/_sqlmap.py +++ b/extra/shutils/_sqlmap.py @@ -68,7 +68,7 @@ _arguments -C -s \ '(--code)'--code=-'[HTTP code to match when query is evaluated to True]' \ '(--text-only)'--text-only'[Compare pages based only on the textual content]' \ '(--titles)'--titles'[Compare pages based only on their titles]' \ - '(--technique)'--technique=-'[SQL injection techniques to test for (default "BEUST")]:TECH:->list-techniques' \ + '(--technique)'--technique=-'[SQL injection techniques to test for (default "BEUSTQ")]:TECH:->list-techniques' \ '(--time-sec)'--time-sec=-'[Seconds to delay the DBMS response (default 5)]:TIMESEC' \ '(--union-cols)'--union-cols=-'[Range of columns to test for UNION query SQL injection]:UCOLS' \ '(--union-char)'--union-char=-'[Character to use for bruteforcing number of columns]:UCHAR' \ diff --git a/lib/controller/controller.py b/lib/controller/controller.py index 3fe3cbefa..2a971f38a 100644 --- a/lib/controller/controller.py +++ b/lib/controller/controller.py @@ -138,7 +138,7 @@ def __formatInjection(inj): title = title.replace("columns", "column") elif comment: vector = "%s%s" % (vector, comment) - data += " Type: %s\n" % (PAYLOAD.SQLINJECTION[stype] if "inline" not in title else "inline query") + data += " Type: %s\n" % PAYLOAD.SQLINJECTION[stype] data += " Title: %s\n" % title data += " Payload: %s\n" % agent.adjustLateValues(sdata.payload) data += " Vector: %s\n\n" % vector if conf.verbose > 1 else "\n" diff --git a/lib/core/defaults.py b/lib/core/defaults.py index 039a176e7..f9b79ba54 100644 --- a/lib/core/defaults.py +++ b/lib/core/defaults.py @@ -21,7 +21,7 @@ _defaults = { "level": 1, "risk": 1, "dumpFormat": "CSV", - "tech": "BEUST", + "tech": "BEUSTQ", "torType": "HTTP" } diff --git a/lib/core/enums.py b/lib/core/enums.py index 8299f1536..62cbbceda 100644 --- a/lib/core/enums.py +++ b/lib/core/enums.py @@ -177,7 +177,8 @@ class PAYLOAD: 2: "error-based", 3: "UNION query", 4: "stacked queries", - 5: "AND/OR time-based blind" + 5: "AND/OR time-based blind", + 6: "inline query" } PARAMETER = { @@ -219,6 +220,7 @@ class PAYLOAD: UNION = 3 STACKED = 4 TIME = 5 + QUERY = 6 class WHERE: ORIGINAL = 1 diff --git a/lib/core/threads.py b/lib/core/threads.py index e5b449d00..88a35109a 100644 --- a/lib/core/threads.py +++ b/lib/core/threads.py @@ -105,7 +105,7 @@ def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardExceptio kb.threadContinue = True kb.threadException = False - if threadChoice and numThreads == 1 and any(map(lambda x: x in kb.injection.data, [PAYLOAD.TECHNIQUE.BOOLEAN, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.UNION])): + if threadChoice and numThreads == 1 and any(map(lambda _: _ in kb.injection.data, (PAYLOAD.TECHNIQUE.BOOLEAN, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY, PAYLOAD.TECHNIQUE.UNION))): while True: message = "please enter number of threads? [Enter for %d (current)] " % numThreads choice = readInput(message, default=str(numThreads)) diff --git a/lib/request/inject.py b/lib/request/inject.py index 691626b18..80a150f5f 100644 --- a/lib/request/inject.py +++ b/lib/request/inject.py @@ -407,14 +407,14 @@ def getValue(expression, blind=True, union=True, error=True, time=True, fromUser count += 1 found = (value is not None) or (value is None and expectingNone) or count >= MAX_TECHNIQUES_PER_VALUE - if error and isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) and not found: - kb.technique = PAYLOAD.TECHNIQUE.ERROR + if error and any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) and not found: + kb.technique = PAYLOAD.TECHNIQUE.ERROR if isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) else PAYLOAD.TECHNIQUE.QUERY value = errorUse(forgeCaseExpression if expected == EXPECTED.BOOL else query, dump) count += 1 found = (value is not None) or (value is None and expectingNone) or count >= MAX_TECHNIQUES_PER_VALUE if found and conf.dnsName: - _ = "".join(filter(None, (key if isTechniqueAvailable(value) else None for key, value in {"E":PAYLOAD.TECHNIQUE.ERROR, "U":PAYLOAD.TECHNIQUE.UNION}.items()))) + _ = "".join(filter(None, (key if isTechniqueAvailable(value) else None for key, value in {"E":PAYLOAD.TECHNIQUE.ERROR, "Q":PAYLOAD.TECHNIQUE.QUERY, "U":PAYLOAD.TECHNIQUE.UNION}.items()))) warnMsg = "option '--dns-domain' will be ignored " warnMsg += "as faster techniques are usable " warnMsg += "(%s) " % _ diff --git a/lib/takeover/xp_cmdshell.py b/lib/takeover/xp_cmdshell.py index 6b2f1c9a3..d7b024b66 100644 --- a/lib/takeover/xp_cmdshell.py +++ b/lib/takeover/xp_cmdshell.py @@ -209,7 +209,7 @@ class xp_cmdshell: query = "SELECT %s FROM %s" % (self.tblField, self.cmdTblName) - if conf.direct or any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)): + if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: output = inject.getValue(query, resumeValue=False, blind=False, time=False) else: output = [] diff --git a/lib/techniques/error/use.py b/lib/techniques/error/use.py index 063a18b34..8a7cd61a1 100644 --- a/lib/techniques/error/use.py +++ b/lib/techniques/error/use.py @@ -83,7 +83,7 @@ def __oneShotErrorUse(expression, field=None): nulledCastedField = queries[Backend.getIdentifiedDbms()].substring.query % (nulledCastedField, offset, chunk_length) # Forge the error-based SQL injection request - vector = kb.injection.data[PAYLOAD.TECHNIQUE.ERROR].vector + vector = kb.injection.data[kb.technique].vector query = agent.prefixQuery(vector) query = agent.suffixQuery(query) injExpression = expression.replace(field, nulledCastedField, 1) if field else expression @@ -94,7 +94,7 @@ def __oneShotErrorUse(expression, field=None): # Perform the request page, headers = Request.queryPage(payload, content=True) - incrementCounter(PAYLOAD.TECHNIQUE.ERROR) + incrementCounter(kb.technique) # Parse the returned page to get the exact error-based # SQL injection output @@ -227,7 +227,7 @@ def errorUse(expression, dump=False): SQL injection vulnerability on the affected parameter. """ - initTechnique(PAYLOAD.TECHNIQUE.ERROR) + initTechnique(kb.technique) abortedFlag = False count = None @@ -416,7 +416,7 @@ def errorUse(expression, dump=False): duration = calculateDeltaSeconds(start) if not kb.bruteMode: - debugMsg = "performed %d queries in %d seconds" % (kb.counters[PAYLOAD.TECHNIQUE.ERROR], duration) + debugMsg = "performed %d queries in %d seconds" % (kb.counters[kb.technique], duration) logger.debug(debugMsg) return outputs diff --git a/plugins/dbms/mssqlserver/enumeration.py b/plugins/dbms/mssqlserver/enumeration.py index 385a3f29b..5d5e2e96c 100644 --- a/plugins/dbms/mssqlserver/enumeration.py +++ b/plugins/dbms/mssqlserver/enumeration.py @@ -86,7 +86,7 @@ class Enumeration(GenericEnumeration): rootQuery = queries[Backend.getIdentifiedDbms()].tables - if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: + if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: for db in dbs: if conf.excludeSysDbs and db in self.excludeDbsList: infoMsg = "skipping system database '%s'" % db @@ -196,7 +196,7 @@ class Enumeration(GenericEnumeration): continue - if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: + if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: query = rootQuery.inband.query.replace("%s", db) query += tblQuery values = inject.getValue(query, blind=False, time=False) @@ -317,7 +317,7 @@ class Enumeration(GenericEnumeration): if conf.excludeSysDbs and db in self.excludeDbsList: continue - if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: + if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: query = rootQuery.inband.query % (db, db, db, db, db, db) query += " AND %s" % colQuery.replace("[DB]", db) query += whereTblsQuery.replace("[DB]", db) diff --git a/plugins/dbms/oracle/enumeration.py b/plugins/dbms/oracle/enumeration.py index ea0d061d8..da95f1828 100644 --- a/plugins/dbms/oracle/enumeration.py +++ b/plugins/dbms/oracle/enumeration.py @@ -41,7 +41,7 @@ class Enumeration(GenericEnumeration): # Set containing the list of DBMS administrators areAdmins = set() - if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: + if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: if query2: query = rootQuery.inband.query2 condition = rootQuery.inband.condition2 diff --git a/plugins/dbms/sybase/enumeration.py b/plugins/dbms/sybase/enumeration.py index 146415c21..b97c3b126 100644 --- a/plugins/dbms/sybase/enumeration.py +++ b/plugins/dbms/sybase/enumeration.py @@ -36,7 +36,7 @@ class Enumeration(GenericEnumeration): randStr = randomStr() query = rootQuery.inband.query - if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: + if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: blinds = (False, True) else: blinds = (True,) @@ -90,7 +90,7 @@ class Enumeration(GenericEnumeration): randStr = randomStr() query = rootQuery.inband.query - if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: + if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: blinds = [False, True] else: blinds = [True] @@ -130,7 +130,7 @@ class Enumeration(GenericEnumeration): infoMsg += "%s: %s" % ("s" if len(dbs) > 1 else "", ", ".join(db if isinstance(db, basestring) else db[0] for db in sorted(dbs))) logger.info(infoMsg) - if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: + if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: blinds = [False, True] else: blinds = [True] @@ -204,7 +204,7 @@ class Enumeration(GenericEnumeration): rootQuery = queries[Backend.getIdentifiedDbms()].columns - if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: + if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: blinds = [False, True] else: blinds = [True] diff --git a/plugins/generic/databases.py b/plugins/generic/databases.py index 5f2aef7b1..b256ec182 100644 --- a/plugins/generic/databases.py +++ b/plugins/generic/databases.py @@ -98,7 +98,7 @@ class Databases: rootQuery = queries[Backend.getIdentifiedDbms()].dbs - if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: + if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: if Backend.isDbms(DBMS.MYSQL) and not kb.data.has_information_schema: query = rootQuery.inband.query2 else: @@ -138,7 +138,7 @@ class Databases: kb.data.cachedDbs.append(safeSQLIdentificatorNaming(db)) if not kb.data.cachedDbs and Backend.isDbms(DBMS.MSSQL): - if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: + if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: blinds = (False, True) else: blinds = (True,) @@ -249,7 +249,7 @@ class Databases: rootQuery = queries[Backend.getIdentifiedDbms()].tables - if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: + if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: query = rootQuery.inband.query condition = rootQuery.inband.condition if 'condition' in rootQuery.inband else None @@ -473,7 +473,7 @@ class Databases: rootQuery = queries[Backend.getIdentifiedDbms()].columns condition = rootQuery.blind.condition if 'condition' in rootQuery.blind else None - if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: + if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: for tbl in tblList: if conf.db is not None and len(kb.data.cachedColumns) > 0 \ and conf.db in kb.data.cachedColumns and tbl in \ diff --git a/plugins/generic/entries.py b/plugins/generic/entries.py index 6e6ee076d..3869188cc 100644 --- a/plugins/generic/entries.py +++ b/plugins/generic/entries.py @@ -134,7 +134,7 @@ class Entries: entriesCount = 0 - if any([isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION), isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR), conf.direct]): + if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: entries = [] query = None diff --git a/plugins/generic/search.py b/plugins/generic/search.py index c26894476..8e1fc2523 100644 --- a/plugins/generic/search.py +++ b/plugins/generic/search.py @@ -74,7 +74,7 @@ class Search: dbQuery = "%s%s" % (dbCond, dbCondParam) dbQuery = dbQuery % unsafeSQLIdentificatorNaming(db) - if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: + if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: if Backend.isDbms(DBMS.MYSQL) and not kb.data.has_information_schema: query = rootQuery.inband.query2 else: @@ -186,7 +186,7 @@ class Search: tblQuery = "%s%s" % (tblCond, tblCondParam) tblQuery = tblQuery % tbl - if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: + if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: query = rootQuery.inband.query query += tblQuery query += whereDbsQuery @@ -370,7 +370,7 @@ class Search: colQuery = "%s%s" % (colCond, colCondParam) colQuery = colQuery % unsafeSQLIdentificatorNaming(column) - if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: + if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: if not all((conf.db, conf.tbl)): # Enumerate tables containing the column provided if # either of database(s) or table(s) is not provided diff --git a/plugins/generic/users.py b/plugins/generic/users.py index c68bcbe36..3f1d109bb 100644 --- a/plugins/generic/users.py +++ b/plugins/generic/users.py @@ -93,7 +93,7 @@ class Users: condition = (Backend.isDbms(DBMS.MSSQL) and Backend.isVersionWithin(("2005", "2008"))) condition |= (Backend.isDbms(DBMS.MYSQL) and not kb.data.has_information_schema) - if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: + if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: if condition: query = rootQuery.inband.query2 else: @@ -167,7 +167,7 @@ class Users: users = filter(None, users) - if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: + if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: if Backend.isDbms(DBMS.MSSQL) and Backend.isVersionWithin(("2005", "2008")): query = rootQuery.inband.query2 else: @@ -347,7 +347,7 @@ class Users: # Set containing the list of DBMS administrators areAdmins = set() - if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: + if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: if Backend.isDbms(DBMS.MYSQL) and not kb.data.has_information_schema: query = rootQuery.inband.query2 condition = rootQuery.inband.condition2 diff --git a/sqlmap.conf b/sqlmap.conf index b0ade0f5c..a81ed2f8b 100644 --- a/sqlmap.conf +++ b/sqlmap.conf @@ -288,8 +288,8 @@ titles = False # T: Time-based blind SQL injection # Example: ES (means test for error-based and stacked queries SQL # injection types only) -# Default: BEUST (means test for all SQL injection types - recommended) -tech = BEUST +# Default: BEUSTQ (means test for all SQL injection types - recommended) +tech = BEUSTQ # Seconds to delay the response from the DBMS. # Valid: integer diff --git a/xml/payloads.xml b/xml/payloads.xml index f5a671d34..c78de0ef9 100644 --- a/xml/payloads.xml +++ b/xml/payloads.xml @@ -73,10 +73,11 @@ Tag: Valid values: 0: Heuristic check to parse response errors 1: Boolean-based blind SQL injection - 2: Error-based/Inline queries SQL injection + 2: Error-based queries SQL injection 3: UNION query SQL injection 4: Stacked queries SQL injection 5: Time-based blind SQL injection + 6: Inline queries SQL injection Sub-tag: From which level check for this test. @@ -1883,8 +1884,8 @@ Formats: MySQL inline queries - 2 - 5 + 6 + 2 1 1,2,3,8 3 @@ -1902,8 +1903,8 @@ Formats: PostgreSQL inline queries - 2 - 5 + 6 + 2 1 1,2,3,8 3 @@ -1921,8 +1922,8 @@ Formats: Microsoft SQL Server/Sybase inline queries - 2 - 5 + 6 + 2 1 1,2,3,8 3 @@ -1942,8 +1943,8 @@ Formats: Oracle inline queries - 2 - 5 + 6 + 2 1 1,2,3,8 3