Major bug fix to properly process custom queries (--sql-query/--sql-shell) when technique in use is error-based.

Alignment of SQL statement payload packing/unpacking between all of the techniques.
Minor bug fix to use the proper charset (2, numbers) when dealing with COUNT() in custom queries too.
Minor code cleanup.
This commit is contained in:
Bernardo Damele 2011-01-18 23:02:11 +00:00
parent 81be23976e
commit daebb0010b
9 changed files with 486 additions and 260 deletions

View File

@ -27,7 +27,7 @@ from lib.core.enums import DBMS
from lib.core.enums import PAYLOAD from lib.core.enums import PAYLOAD
from lib.core.enums import PLACE from lib.core.enums import PLACE
from lib.core.exception import sqlmapNoneDataException from lib.core.exception import sqlmapNoneDataException
from lib.core.settings import INBAND_FROM_TABLE from lib.core.settings import FROM_TABLE
from lib.core.settings import PAYLOAD_DELIMITER from lib.core.settings import PAYLOAD_DELIMITER
class Agent: class Agent:
@ -366,7 +366,7 @@ class Agent:
elif fieldsNoSelect: elif fieldsNoSelect:
fieldsToCastStr = fieldsNoSelect fieldsToCastStr = fieldsNoSelect
if re.search("\A\w+\(.*\)", fieldsToCastStr, re.I): #function if re.search("\A\w+\(.*\)", fieldsToCastStr, re.I): # Function
fieldsToCastList = [fieldsToCastStr] fieldsToCastList = [fieldsToCastStr]
else: else:
fieldsToCastList = fieldsToCastStr.replace(", ", ",") fieldsToCastList = fieldsToCastStr.replace(", ", ",")
@ -380,7 +380,7 @@ class Agent:
if getIdentifiedDBMS() == DBMS.MYSQL: if getIdentifiedDBMS() == DBMS.MYSQL:
concatenatedQuery = "CONCAT(%s,%s)" % (query1, query2) concatenatedQuery = "CONCAT(%s,%s)" % (query1, query2)
elif getIdentifiedDBMS() in ( DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE ): elif getIdentifiedDBMS() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE):
concatenatedQuery = "%s||%s" % (query1, query2) concatenatedQuery = "%s||%s" % (query1, query2)
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE): elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
@ -438,7 +438,7 @@ class Agent:
elif fieldsNoSelect: elif fieldsNoSelect:
concatenatedQuery = "CONCAT('%s',%s,'%s')" % (kb.misc.start, concatenatedQuery, kb.misc.stop) concatenatedQuery = "CONCAT('%s',%s,'%s')" % (kb.misc.start, concatenatedQuery, kb.misc.stop)
elif getIdentifiedDBMS() in ( DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE ): elif getIdentifiedDBMS() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE):
if fieldsExists: if fieldsExists:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.misc.start, 1) concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.misc.start, 1)
concatenatedQuery += "||'%s'" % kb.misc.stop concatenatedQuery += "||'%s'" % kb.misc.stop
@ -451,7 +451,7 @@ class Agent:
elif fieldsNoSelect: elif fieldsNoSelect:
concatenatedQuery = "'%s'||%s||'%s'" % (kb.misc.start, concatenatedQuery, kb.misc.stop) concatenatedQuery = "'%s'||%s||'%s'" % (kb.misc.start, concatenatedQuery, kb.misc.stop)
if getIdentifiedDBMS() == DBMS.ORACLE and " FROM " not in concatenatedQuery and ( fieldsSelect or fieldsNoSelect ): if getIdentifiedDBMS() == DBMS.ORACLE and " FROM " not in concatenatedQuery and (fieldsSelect or fieldsNoSelect):
concatenatedQuery += " FROM DUAL" concatenatedQuery += " FROM DUAL"
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE): elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
@ -520,8 +520,8 @@ class Agent:
intoRegExp = intoRegExp.group(1) intoRegExp = intoRegExp.group(1)
query = query[:query.index(intoRegExp)] query = query[:query.index(intoRegExp)]
if getIdentifiedDBMS() in INBAND_FROM_TABLE and inbandQuery.endswith(INBAND_FROM_TABLE[getIdentifiedDBMS()]): if getIdentifiedDBMS() in FROM_TABLE and inbandQuery.endswith(FROM_TABLE[getIdentifiedDBMS()]):
inbandQuery = inbandQuery[:-len(INBAND_FROM_TABLE[getIdentifiedDBMS()])] inbandQuery = inbandQuery[:-len(FROM_TABLE[getIdentifiedDBMS()])]
for element in range(count): for element in range(count):
if element > 0: if element > 0:
@ -540,9 +540,9 @@ class Agent:
conditionIndex = query.index(" FROM ") conditionIndex = query.index(" FROM ")
inbandQuery += query[conditionIndex:] inbandQuery += query[conditionIndex:]
if getIdentifiedDBMS() in INBAND_FROM_TABLE: if getIdentifiedDBMS() in FROM_TABLE:
if " FROM " not in inbandQuery: if " FROM " not in inbandQuery:
inbandQuery += INBAND_FROM_TABLE[getIdentifiedDBMS()] inbandQuery += FROM_TABLE[getIdentifiedDBMS()]
if intoRegExp: if intoRegExp:
inbandQuery += intoRegExp inbandQuery += intoRegExp
@ -559,8 +559,8 @@ class Agent:
else: else:
inbandQuery += char inbandQuery += char
if getIdentifiedDBMS() in INBAND_FROM_TABLE: if getIdentifiedDBMS() in FROM_TABLE:
inbandQuery += INBAND_FROM_TABLE[getIdentifiedDBMS()] inbandQuery += FROM_TABLE[getIdentifiedDBMS()]
inbandQuery = self.suffixQuery(inbandQuery, comment, suffix) inbandQuery = self.suffixQuery(inbandQuery, comment, suffix)
@ -595,7 +595,7 @@ class Agent:
fromFrom = limitedQuery[fromIndex+1:] fromFrom = limitedQuery[fromIndex+1:]
orderBy = False orderBy = False
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE ): if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE):
limitStr = queries[getIdentifiedDBMS()].limit.query % (num, 1) limitStr = queries[getIdentifiedDBMS()].limit.query % (num, 1)
limitedQuery += " %s" % limitStr limitedQuery += " %s" % limitStr

View File

@ -132,7 +132,12 @@ SYBASE_ALIASES = [ "sybase", "sybase sql server" ]
SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES + SQLITE_ALIASES + ACCESS_ALIASES + FIREBIRD_ALIASES + MAXDB_ALIASES + SYBASE_ALIASES SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES + SQLITE_ALIASES + ACCESS_ALIASES + FIREBIRD_ALIASES + MAXDB_ALIASES + SYBASE_ALIASES
SUPPORTED_OS = ( "linux", "windows" ) SUPPORTED_OS = ( "linux", "windows" )
INBAND_FROM_TABLE = {DBMS.ORACLE: " FROM DUAL", DBMS.ACCESS: " FROM MSysObjects", DBMS.FIREBIRD: " FROM RDB$DATABASE", DBMS.MAXDB: " FROM VERSIONS"} FROM_TABLE = {
DBMS.ORACLE: " FROM DUAL",
DBMS.ACCESS: " FROM MSysObjects",
DBMS.FIREBIRD: " FROM RDB$DATABASE",
DBMS.MAXDB: " FROM VERSIONS"
}
SQL_STATEMENTS = { SQL_STATEMENTS = {
"SQL SELECT statement": ( "SQL SELECT statement": (

View File

@ -18,6 +18,7 @@ from lib.core.common import expandAsteriskForColumns
from lib.core.common import getIdentifiedDBMS from lib.core.common import getIdentifiedDBMS
from lib.core.common import getPublicTypeMembers from lib.core.common import getPublicTypeMembers
from lib.core.common import initTechnique from lib.core.common import initTechnique
from lib.core.common import isNumPosStrValue
from lib.core.common import isTechniqueAvailable from lib.core.common import isTechniqueAvailable
from lib.core.common import parseUnionPage from lib.core.common import parseUnionPage
from lib.core.common import popValue from lib.core.common import popValue
@ -34,6 +35,8 @@ from lib.core.enums import DBMS
from lib.core.enums import EXPECTED from lib.core.enums import EXPECTED
from lib.core.enums import PAYLOAD from lib.core.enums import PAYLOAD
from lib.core.exception import sqlmapNotVulnerableException from lib.core.exception import sqlmapNotVulnerableException
from lib.core.exception import sqlmapUserQuitException
from lib.core.settings import FROM_TABLE
from lib.core.settings import MIN_TIME_RESPONSES from lib.core.settings import MIN_TIME_RESPONSES
from lib.core.settings import MAX_TECHNIQUES_PER_VALUE from lib.core.settings import MAX_TECHNIQUES_PER_VALUE
from lib.core.threads import getCurrentThreadData from lib.core.threads import getCurrentThreadData
@ -51,7 +54,7 @@ def __goInference(payload, expression, charsetType=None, firstChar=None, lastCha
timeBasedCompare = (kb.technique in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED)) timeBasedCompare = (kb.technique in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED))
if ( conf.eta or conf.threads > 1 ) and getIdentifiedDBMS() and not timeBasedCompare: if (conf.eta or conf.threads > 1) and getIdentifiedDBMS() and not timeBasedCompare:
_, length, _ = queryOutputLength(expression, payload) _, length, _ = queryOutputLength(expression, payload)
else: else:
length = None length = None
@ -87,7 +90,7 @@ def __goInferenceFields(expression, expressionFields, expressionFieldsList, payl
if resumeValue: if resumeValue:
output = resume(expressionReplaced, payload) output = resume(expressionReplaced, payload)
if not output or ( expected == EXPECTED.INT and not output.isdigit() ): if not output or (expected == EXPECTED.INT and not output.isdigit()):
if output: if output:
warnMsg = "expected value type %s, resumed '%s', " % (expected, output) warnMsg = "expected value type %s, resumed '%s', " % (expected, output)
warnMsg += "sqlmap is going to retrieve the value again" warnMsg += "sqlmap is going to retrieve the value again"
@ -102,31 +105,6 @@ def __goInferenceFields(expression, expressionFields, expressionFieldsList, payl
return outputs return outputs
def __goBooleanProxy(expression, resumeValue=True):
"""
Retrieve the output of a boolean based SQL query
"""
initTechnique(kb.technique)
vector = kb.injection.data[kb.technique].vector
vector = vector.replace("[INFERENCE]", expression)
vector = agent.cleanupPayload(vector)
query = agent.prefixQuery(vector)
query = agent.suffixQuery(query)
payload = agent.payload(newValue=query)
timeBasedCompare = kb.technique in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED)
if resumeValue:
output = resume(expression, payload)
else:
output = None
if not output:
output = Request.queryPage(payload, timeBasedCompare=timeBasedCompare, raise404=False)
return output
def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, resumeValue=True, unpack=True, charsetType=None, firstChar=None, lastChar=None): def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, resumeValue=True, unpack=True, charsetType=None, firstChar=None, lastChar=None):
""" """
Retrieve the output of a SQL query characted by character taking Retrieve the output of a SQL query characted by character taking
@ -153,7 +131,7 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
else: else:
output = None output = None
if output and ( expected is None or ( expected == EXPECTED.INT and output.isdigit() ) ): if output and (expected is None or (expected == EXPECTED.INT and output.isdigit())):
return output return output
if not unpack: if not unpack:
@ -178,12 +156,12 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
# forge the SQL limiting the query output one entry per time # forge the SQL limiting the query output one entry per time
# NOTE: I assume that only queries that get data from a table # NOTE: I assume that only queries that get data from a table
# can return multiple entries # can return multiple entries
if fromUser and " FROM " in expression: if fromUser and " FROM " in expression.upper() and ((getIdentifiedDBMS() not in FROM_TABLE) or (getIdentifiedDBMS() in FROM_TABLE and not expression.upper().endswith(FROM_TABLE[getIdentifiedDBMS()]))):
limitRegExp = re.search(queries[getIdentifiedDBMS()].limitregexp.query, expression, re.I) limitRegExp = re.search(queries[getIdentifiedDBMS()].limitregexp.query, expression, re.I)
topLimit = re.search("TOP\s+([\d]+)\s+", expression, re.I) topLimit = re.search("TOP\s+([\d]+)\s+", expression, re.I)
if limitRegExp or ( getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit ): if limitRegExp or (getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit):
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ): if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL):
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query
@ -222,7 +200,7 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
# From now on we need only the expression until the " LIMIT " # From now on we need only the expression until the " LIMIT "
# (or similar, depending on the back-end DBMS) word # (or similar, depending on the back-end DBMS) word
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ): if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL):
stopLimit += startLimit stopLimit += startLimit
untilLimitChar = expression.index(queries[getIdentifiedDBMS()].limitstring.query) untilLimitChar = expression.index(queries[getIdentifiedDBMS()].limitstring.query)
expression = expression[:untilLimitChar] expression = expression[:untilLimitChar]
@ -231,16 +209,12 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
stopLimit += startLimit stopLimit += startLimit
if not stopLimit or stopLimit <= 1: if not stopLimit or stopLimit <= 1:
if getIdentifiedDBMS() == DBMS.ORACLE and expression.endswith("FROM DUAL"): if getIdentifiedDBMS() in FROM_TABLE and expression.upper().endswith(FROM_TABLE[getIdentifiedDBMS()]):
test = "n" test = False
elif batch:
test = "y"
else: else:
message = "can the SQL query provided return " test = True
message += "multiple entries? [Y/n] "
test = readInput(message, default="Y")
if not test or test[0] in ("y", "Y"): if test:
# Count the number of SQL query entries output # Count the number of SQL query entries output
countFirstField = queries[getIdentifiedDBMS()].count.query % expressionFieldsList[0] countFirstField = queries[getIdentifiedDBMS()].count.query % expressionFieldsList[0]
countedExpression = expression.replace(expressionFields, countFirstField, 1) countedExpression = expression.replace(expressionFields, countFirstField, 1)
@ -254,16 +228,16 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
if not stopLimit: if not stopLimit:
if not count or not count.isdigit(): if not count or not count.isdigit():
count = __goInference(payload, countedExpression, charsetType, firstChar, lastChar) count = __goInference(payload, countedExpression, 2, firstChar, lastChar)
if count and count.isdigit() and int(count) > 0: if isNumPosStrValue(count):
count = int(count) count = int(count)
if batch: if batch:
stopLimit = count stopLimit = count
else: else:
message = "the SQL query provided can return " message = "the SQL query provided can return "
message += "up to %d entries. How many " % count message += "%d entries. How many " % count
message += "entries do you want to retrieve?\n" message += "entries do you want to retrieve?\n"
message += "[a] All (default)\n[#] Specific number\n" message += "[a] All (default)\n[#] Specific number\n"
message += "[q] Quit" message += "[q] Quit"
@ -273,7 +247,7 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
stopLimit = count stopLimit = count
elif test[0] in ("q", "Q"): elif test[0] in ("q", "Q"):
return "Quit" raise sqlmapUserQuitException
elif test.isdigit() and int(test) > 0 and int(test) <= count: elif test.isdigit() and int(test) > 0 and int(test) <= count:
stopLimit = int(test) stopLimit = int(test)
@ -283,11 +257,11 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
logger.info(infoMsg) logger.info(infoMsg)
elif test[0] in ("#", "s", "S"): elif test[0] in ("#", "s", "S"):
message = "How many? " message = "how many? "
stopLimit = readInput(message, default="10") stopLimit = readInput(message, default="10")
if not stopLimit.isdigit(): if not stopLimit.isdigit():
errMsg = "Invalid choice" errMsg = "invalid choice"
logger.error(errMsg) logger.error(errMsg)
return None return None
@ -296,7 +270,7 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
stopLimit = int(stopLimit) stopLimit = int(stopLimit)
else: else:
errMsg = "Invalid choice" errMsg = "invalid choice"
logger.error(errMsg) logger.error(errMsg)
return None return None
@ -310,39 +284,68 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
stopLimit = 1 stopLimit = 1
elif ( not count or int(count) == 0 ): elif (not count or int(count) == 0):
warnMsg = "the SQL query provided does not " warnMsg = "the SQL query provided does not "
warnMsg += "return any output" warnMsg += "return any output"
logger.warn(warnMsg) logger.warn(warnMsg)
return None return None
elif ( not count or int(count) == 0 ) and ( not stopLimit or stopLimit == 0 ): elif (not count or int(count) == 0) and (not stopLimit or stopLimit == 0):
warnMsg = "the SQL query provided does not " warnMsg = "the SQL query provided does not "
warnMsg += "return any output" warnMsg += "return any output"
logger.warn(warnMsg) logger.warn(warnMsg)
return None return None
try:
for num in xrange(startLimit, stopLimit): for num in xrange(startLimit, stopLimit):
output = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, num, resumeValue=resumeValue, charsetType=charsetType, firstChar=firstChar, lastChar=lastChar) output = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, num, resumeValue=resumeValue, charsetType=charsetType, firstChar=firstChar, lastChar=lastChar)
outputs.append(output) outputs.append(output)
except KeyboardInterrupt:
print
warnMsg = "Ctrl+C detected in dumping phase"
logger.warn(warnMsg)
return outputs return outputs
elif getIdentifiedDBMS() == DBMS.ORACLE and expression.startswith("SELECT ") and " FROM " not in expression: elif getIdentifiedDBMS() in FROM_TABLE and expression.upper().startswith("SELECT ") and " FROM " not in expression.upper():
expression = "%s FROM DUAL" % expression expression += FROM_TABLE[getIdentifiedDBMS()]
outputs = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, resumeValue=resumeValue, charsetType=charsetType, firstChar=firstChar, lastChar=lastChar) outputs = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, resumeValue=resumeValue, charsetType=charsetType, firstChar=firstChar, lastChar=lastChar)
returnValue = ", ".join([output for output in outputs]) returnValue = ", ".join([output for output in outputs])
else: else:
returnValue = __goInference(payload, expression, charsetType, firstChar, lastChar) returnValue = __goInference(payload, expression, charsetType, firstChar, lastChar)
return returnValue return returnValue
def __goError(expression, resumeValue=True): def __goBooleanProxy(expression, resumeValue=True):
"""
Retrieve the output of a boolean based SQL query
"""
initTechnique(kb.technique)
vector = kb.injection.data[kb.technique].vector
vector = vector.replace("[INFERENCE]", expression)
vector = agent.cleanupPayload(vector)
query = agent.prefixQuery(vector)
query = agent.suffixQuery(query)
payload = agent.payload(newValue=query)
timeBasedCompare = kb.technique in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED)
if resumeValue:
output = resume(expression, payload)
else:
output = None
if not output:
output = Request.queryPage(payload, timeBasedCompare=timeBasedCompare, raise404=False)
return output
def __goError(expression, expected=None, resumeValue=True, dump=False):
""" """
Retrieve the output of a SQL query taking advantage of an error-based Retrieve the output of a SQL query taking advantage of an error-based
SQL injection vulnerability on the affected parameter. SQL injection vulnerability on the affected parameter.
@ -357,8 +360,7 @@ def __goError(expression, resumeValue=True):
result = resume(expression, None) result = resume(expression, None)
if not result: if not result:
result = errorUse(expression) result = errorUse(expression, expected, resumeValue, dump)
dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.url, kb.injection.place, conf.parameters[kb.injection.place], expression, replaceNewlineTabs(result)))
return result return result
@ -375,7 +377,7 @@ def __goInband(expression, expected=None, sort=True, resumeValue=True, unpack=Tr
if resumeValue: if resumeValue:
output = resume(expression, None) output = resume(expression, None)
if not output or ( expected == EXPECTED.INT and not output.isdigit() ): if not output or (expected == EXPECTED.INT and not output.isdigit()):
partial = True partial = True
if not output: if not output:
@ -405,8 +407,10 @@ def getValue(expression, blind=True, inband=True, error=True, time=True, fromUse
query = expandAsteriskForColumns(query) query = expandAsteriskForColumns(query)
value = None value = None
found = False found = False
if query and not 'COUNT(*)' in query: if query and not 'COUNT(*)' in query:
query = query.replace("DISTINCT ", "") query = query.replace("DISTINCT ", "")
count = 0 count = 0
if expected == EXPECTED.BOOL: if expected == EXPECTED.BOOL:
@ -432,9 +436,9 @@ def getValue(expression, blind=True, inband=True, error=True, time=True, fromUse
kb.technique = PAYLOAD.TECHNIQUE.ERROR kb.technique = PAYLOAD.TECHNIQUE.ERROR
if expected == EXPECTED.BOOL: if expected == EXPECTED.BOOL:
value = __goError(forgeCaseExpression, resumeValue) value = __goError(forgeCaseExpression, expected, resumeValue, dump)
else: else:
value = __goError(query, resumeValue) value = __goError(query, expected, resumeValue, dump)
count += 1 count += 1
found = (value is not None) or (value is None and expectingNone) or count >= MAX_TECHNIQUES_PER_VALUE found = (value is not None) or (value is None and expectingNone) or count >= MAX_TECHNIQUES_PER_VALUE

View File

@ -11,10 +11,12 @@ import re
import time import time
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import dataToStdout from lib.core.common import calculateDeltaSeconds
from lib.core.common import dataToSessionFile
from lib.core.common import extractRegexResult from lib.core.common import extractRegexResult
from lib.core.common import getIdentifiedDBMS from lib.core.common import getIdentifiedDBMS
from lib.core.common import initTechnique from lib.core.common import initTechnique
from lib.core.common import isNumPosStrValue
from lib.core.common import randomInt from lib.core.common import randomInt
from lib.core.common import replaceNewlineTabs from lib.core.common import replaceNewlineTabs
from lib.core.common import safeStringFormat from lib.core.common import safeStringFormat
@ -23,41 +25,249 @@ 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.enums import DBMS from lib.core.enums import DBMS
from lib.core.enums import EXPECTED
from lib.core.enums import PAYLOAD from lib.core.enums import PAYLOAD
from lib.core.settings import FROM_TABLE
from lib.core.unescaper import unescaper from lib.core.unescaper import unescaper
from lib.request.connect import Connect as Request from lib.request.connect import Connect as Request
from lib.utils.resume import resume
def errorUse(expression): reqCount = 0
"""
Retrieve the output of a SQL query taking advantage of an error SQL
injection vulnerability on the affected parameter.
"""
initTechnique(PAYLOAD.TECHNIQUE.ERROR) def __oneShotErrorUse(expression, field):
global reqCount
output = None check = "%s(?P<result>.*?)%s" % (kb.misc.start, kb.misc.stop)
nulledCastedField = agent.nullAndCastField(field)
if getIdentifiedDBMS() == DBMS.MYSQL:
# Fix for MySQL odd behaviour ('Subquery returns more than 1 row')
nulledCastedField = nulledCastedField.replace("AS CHAR)", "AS CHAR(100))")
# Forge the error-based SQL injection request
vector = agent.cleanupPayload(kb.injection.data[PAYLOAD.TECHNIQUE.ERROR].vector) vector = agent.cleanupPayload(kb.injection.data[PAYLOAD.TECHNIQUE.ERROR].vector)
query = unescaper.unescape(vector) query = unescaper.unescape(vector)
query = agent.prefixQuery(query) query = agent.prefixQuery(query)
query = agent.suffixQuery(query) query = agent.suffixQuery(query)
check = "%s(?P<result>.*?)%s" % (kb.misc.start, kb.misc.stop) injExpression = expression.replace(field, nulledCastedField, 1)
injExpression = unescaper.unescape(injExpression)
injExpression = query.replace("[QUERY]", injExpression)
payload = agent.payload(newValue=injExpression)
_, _, _, _, _, _, fieldToCastStr, _ = agent.getFields(expression) # Perform the request
nulledCastedField = agent.nullAndCastField(fieldToCastStr)
if getIdentifiedDBMS() == DBMS.MYSQL:
nulledCastedField = nulledCastedField.replace("AS CHAR)", "AS CHAR(100))") # fix for that 'Subquery returns more than 1 row'
expression = expression.replace(fieldToCastStr, nulledCastedField, 1)
expression = unescaper.unescape(expression)
expression = query.replace("[QUERY]", expression)
payload = agent.payload(newValue=expression)
page, _ = Request.queryPage(payload, content=True) page, _ = Request.queryPage(payload, content=True)
reqCount += 1
# Parse the returned page to get the exact error-based
# sql injection output
output = extractRegexResult(check, page, re.DOTALL | re.IGNORECASE) output = extractRegexResult(check, page, re.DOTALL | re.IGNORECASE)
dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.url, kb.injection.place, conf.parameters[kb.injection.place], expression, replaceNewlineTabs(output)))
return output
def __errorFields(expression, expressionFields, expressionFieldsList, expected=None, num=None, resumeValue=True):
outputs = []
origExpr = None
for field in expressionFieldsList:
output = None
if field.startswith("ROWNUM "):
continue
if isinstance(num, int):
origExpr = expression
expression = agent.limitQuery(num, expression, field)
if "ROWNUM" in expressionFieldsList:
expressionReplaced = expression
else:
expressionReplaced = expression.replace(expressionFields, field, 1)
if resumeValue:
output = resume(expressionReplaced, None)
if not output or (expected == EXPECTED.INT and not output.isdigit()):
if output:
warnMsg = "expected value type %s, resumed '%s', " % (expected, output)
warnMsg += "sqlmap is going to retrieve the value again"
logger.warn(warnMsg)
output = __oneShotErrorUse(expressionReplaced, field)
logger.info("retrieved: %s" % output)
if isinstance(num, int):
expression = origExpr
if output: if output:
output = output.replace(kb.misc.space, " ") output = output.replace(kb.misc.space, " ")
dataToStdout("[%s] [INFO] retrieved: %s\n" % (time.strftime("%X"), replaceNewlineTabs(output, stdout=True))) outputs.append(output)
return outputs
def errorUse(expression, expected=None, resumeValue=True, dump=False):
"""
Retrieve the output of a SQL query taking advantage of the error-based
SQL injection vulnerability on the affected parameter.
"""
initTechnique(PAYLOAD.TECHNIQUE.ERROR)
count = None
start = time.time()
startLimit = 0
stopLimit = None
outputs = []
test = None
untilLimitChar = None
untilOrderChar = None
global reqCount
reqCount = 0
if resumeValue:
output = resume(expression, None)
else:
output = None
if output and (expected is None or (expected == EXPECTED.INT and output.isdigit())):
return output return output
_, _, _, _, _, expressionFieldsList, expressionFields, _ = agent.getFields(expression)
# We have to check if the SQL query might return multiple entries
# and in such case forge the SQL limiting the query output one
# entry per time
# NOTE: I assume that only queries that get data from a table can
# return multiple entries
if " FROM " in expression.upper() and ((getIdentifiedDBMS() not in FROM_TABLE) or (getIdentifiedDBMS() in FROM_TABLE and not expression.upper().endswith(FROM_TABLE[getIdentifiedDBMS()]))) and "EXISTS(" not in expression.upper():
limitRegExp = re.search(queries[getIdentifiedDBMS()].limitregexp.query, expression, re.I)
topLimit = re.search("TOP\s+([\d]+)\s+", expression, re.I)
if limitRegExp or (getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit):
if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL):
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query
if limitGroupStart.isdigit():
startLimit = int(limitRegExp.group(int(limitGroupStart)))
stopLimit = limitRegExp.group(int(limitGroupStop))
limitCond = int(stopLimit) > 1
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
if limitRegExp:
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query
if limitGroupStart.isdigit():
startLimit = int(limitRegExp.group(int(limitGroupStart)))
stopLimit = limitRegExp.group(int(limitGroupStop))
limitCond = int(stopLimit) > 1
elif topLimit:
startLimit = 0
stopLimit = int(topLimit.group(1))
limitCond = int(stopLimit) > 1
elif getIdentifiedDBMS() == DBMS.ORACLE:
limitCond = False
else:
limitCond = True
# I assume that only queries NOT containing a "LIMIT #, 1"
# (or similar depending on the back-end DBMS) can return
# multiple entries
if limitCond:
if limitRegExp:
stopLimit = int(stopLimit)
# From now on we need only the expression until the " LIMIT "
# (or similar, depending on the back-end DBMS) word
if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL):
stopLimit += startLimit
untilLimitChar = expression.index(queries[getIdentifiedDBMS()].limitstring.query)
expression = expression[:untilLimitChar]
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
stopLimit += startLimit
elif dump:
if conf.limitStart:
startLimit = conf.limitStart
if conf.limitStop:
stopLimit = conf.limitStop
if not stopLimit or stopLimit <= 1:
if getIdentifiedDBMS() in FROM_TABLE and expression.upper().endswith(FROM_TABLE[getIdentifiedDBMS()]):
test = False
else:
test = True
if test:
# Count the number of SQL query entries output
countFirstField = queries[getIdentifiedDBMS()].count.query % expressionFieldsList[0]
countedExpression = expression.replace(expressionFields, countFirstField, 1)
if re.search(" ORDER BY ", expression, re.I):
untilOrderChar = countedExpression.index(" ORDER BY ")
countedExpression = countedExpression[:untilOrderChar]
if resumeValue:
count = resume(countedExpression, None)
if not stopLimit:
if not count or not count.isdigit():
count = __oneShotErrorUse(countedExpression, expressionFields)
if isNumPosStrValue(count):
stopLimit = int(count)
infoMsg = "the SQL query used returns "
infoMsg += "%d entries" % stopLimit
logger.info(infoMsg)
elif count and not count.isdigit():
warnMsg = "it was not possible to count the number "
warnMsg += "of entries for the used SQL query. "
warnMsg += "sqlmap will assume that it returns only "
warnMsg += "one entry"
logger.warn(warnMsg)
stopLimit = 1
elif (not count or int(count) == 0):
warnMsg = "the SQL query used does not "
warnMsg += "return any output"
logger.warn(warnMsg)
return None
elif (not count or int(count) == 0) and (not stopLimit or stopLimit == 0):
warnMsg = "the SQL query used does not "
warnMsg += "return any output"
logger.warn(warnMsg)
return None
try:
for num in xrange(startLimit, stopLimit):
output = __errorFields(expression, expressionFields, expressionFieldsList, expected, num, resumeValue)
outputs.append(output)
except KeyboardInterrupt:
print
warnMsg = "Ctrl+C detected in dumping phase"
logger.warn(warnMsg)
duration = calculateDeltaSeconds(start)
debugMsg = "performed %d queries in %d seconds" % (reqCount, duration)
logger.debug(debugMsg)
return outputs
else:
return __oneShotErrorUse(expression, expressionFields)
return outputs

View File

@ -22,7 +22,7 @@ from lib.core.data import logger
from lib.core.data import queries from lib.core.data import queries
from lib.core.enums import DBMS from lib.core.enums import DBMS
from lib.core.enums import PAYLOAD from lib.core.enums import PAYLOAD
from lib.core.settings import INBAND_FROM_TABLE from lib.core.settings import FROM_TABLE
from lib.core.unescaper import unescaper from lib.core.unescaper import unescaper
from lib.parse.html import htmlParser from lib.parse.html import htmlParser
from lib.request.connect import Connect as Request from lib.request.connect import Connect as Request
@ -98,14 +98,14 @@ def __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix
query = agent.prefixQuery("UNION ALL SELECT %s" % conf.uChar) query = agent.prefixQuery("UNION ALL SELECT %s" % conf.uChar)
for count in range(conf.uColsStart, conf.uColsStop+1): for count in range(conf.uColsStart, conf.uColsStop+1):
if getIdentifiedDBMS() in INBAND_FROM_TABLE and query.endswith(INBAND_FROM_TABLE[getIdentifiedDBMS()]): if getIdentifiedDBMS() in FROM_TABLE and query.endswith(FROM_TABLE[getIdentifiedDBMS()]):
query = query[:-len(INBAND_FROM_TABLE[getIdentifiedDBMS()])] query = query[:-len(FROM_TABLE[getIdentifiedDBMS()])]
if count: if count:
query += ", %s" % conf.uChar query += ", %s" % conf.uChar
if getIdentifiedDBMS() in INBAND_FROM_TABLE: if getIdentifiedDBMS() in FROM_TABLE:
query += INBAND_FROM_TABLE[getIdentifiedDBMS()] query += FROM_TABLE[getIdentifiedDBMS()]
status = "%d/%d" % (count, conf.uColsStop) status = "%d/%d" % (count, conf.uColsStop)
debugMsg = "testing %s columns (%d%%)" % (status, round(100.0*count/conf.uColsStop)) debugMsg = "testing %s columns (%d%%)" % (status, round(100.0*count/conf.uColsStop))

View File

@ -17,6 +17,7 @@ from lib.core.common import dataToStdout
from lib.core.common import getIdentifiedDBMS from lib.core.common import getIdentifiedDBMS
from lib.core.common import getUnicode from lib.core.common import getUnicode
from lib.core.common import initTechnique from lib.core.common import initTechnique
from lib.core.common import isNumPosStrValue
from lib.core.common import parseUnionPage from lib.core.common import parseUnionPage
from lib.core.data import conf from lib.core.data import conf
from lib.core.data import kb from lib.core.data import kb
@ -25,7 +26,7 @@ from lib.core.data import queries
from lib.core.enums import DBMS from lib.core.enums import DBMS
from lib.core.enums import PAYLOAD from lib.core.enums import PAYLOAD
from lib.core.exception import sqlmapSyntaxException from lib.core.exception import sqlmapSyntaxException
from lib.core.settings import INBAND_FROM_TABLE from lib.core.settings import FROM_TABLE
from lib.core.unescaper import unescaper from lib.core.unescaper import unescaper
from lib.request.connect import Connect as Request from lib.request.connect import Connect as Request
from lib.utils.resume import resume from lib.utils.resume import resume
@ -102,11 +103,12 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
# entry per time # entry per time
# NOTE: I assume that only queries that get data from a table can # NOTE: I assume that only queries that get data from a table can
# return multiple entries # return multiple entries
if " FROM " in expression.upper() and " FROM DUAL" not in expression.upper() and "EXISTS(" not in expression.upper(): if " FROM " in expression.upper() and ((getIdentifiedDBMS() not in FROM_TABLE) or (getIdentifiedDBMS() in FROM_TABLE and not expression.upper().endswith(FROM_TABLE[getIdentifiedDBMS()]))) and "EXISTS(" not in expression.upper():
limitRegExp = re.search(queries[getIdentifiedDBMS()].limitregexp.query, expression, re.I) limitRegExp = re.search(queries[getIdentifiedDBMS()].limitregexp.query, expression, re.I)
topLimit = re.search("TOP\s+([\d]+)\s+", expression, re.I)
if limitRegExp: if limitRegExp or (getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit):
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ): if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL):
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query
@ -117,6 +119,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
limitCond = int(stopLimit) > 1 limitCond = int(stopLimit) > 1
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE): elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
if limitRegExp:
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query
@ -125,6 +128,10 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
stopLimit = limitRegExp.group(int(limitGroupStop)) stopLimit = limitRegExp.group(int(limitGroupStop))
limitCond = int(stopLimit) > 1 limitCond = int(stopLimit) > 1
elif topLimit:
startLimit = 0
stopLimit = int(topLimit.group(1))
limitCond = int(stopLimit) > 1
elif getIdentifiedDBMS() == DBMS.ORACLE: elif getIdentifiedDBMS() == DBMS.ORACLE:
limitCond = False limitCond = False
@ -140,7 +147,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
# From now on we need only the expression until the " LIMIT " # From now on we need only the expression until the " LIMIT "
# (or similar, depending on the back-end DBMS) word # (or similar, depending on the back-end DBMS) word
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ): if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL):
stopLimit += startLimit stopLimit += startLimit
untilLimitChar = expression.index(queries[getIdentifiedDBMS()].limitstring.query) untilLimitChar = expression.index(queries[getIdentifiedDBMS()].limitstring.query)
expression = expression[:untilLimitChar] expression = expression[:untilLimitChar]
@ -154,7 +161,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
stopLimit = conf.limitStop stopLimit = conf.limitStop
if not stopLimit or stopLimit <= 1: if not stopLimit or stopLimit <= 1:
if getIdentifiedDBMS() in INBAND_FROM_TABLE and expression.endswith(INBAND_FROM_TABLE[getIdentifiedDBMS()]): if getIdentifiedDBMS() in FROM_TABLE and expression.upper().endswith(FROM_TABLE[getIdentifiedDBMS()]):
test = False test = False
else: else:
test = True test = True
@ -177,7 +184,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
if output: if output:
count = parseUnionPage(output, countedExpression) count = parseUnionPage(output, countedExpression)
if count and count.isdigit() and int(count) > 0: if isNumPosStrValue(count):
stopLimit = int(count) stopLimit = int(count)
infoMsg = "the SQL query used returns " infoMsg = "the SQL query used returns "
@ -193,19 +200,19 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
stopLimit = 1 stopLimit = 1
elif ( not count or int(count) == 0 ): elif (not count or int(count) == 0):
warnMsg = "the SQL query used does not " warnMsg = "the SQL query used does not "
warnMsg += "return any output" warnMsg += "return any output"
logger.warn(warnMsg) logger.warn(warnMsg)
return return None
elif ( not count or int(count) == 0 ) and ( not stopLimit or stopLimit == 0 ): elif (not count or int(count) == 0) and (not stopLimit or stopLimit == 0):
warnMsg = "the SQL query used does not " warnMsg = "the SQL query used does not "
warnMsg += "return any output" warnMsg += "return any output"
logger.warn(warnMsg) logger.warn(warnMsg)
return return None
try: try:
for num in xrange(startLimit, stopLimit): for num in xrange(startLimit, stopLimit):

View File

@ -54,7 +54,7 @@ class Enumeration(GenericEnumeration):
else: else:
dbs = [conf.db] dbs = [conf.db]
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or conf.direct: if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
for db in dbs: for db in dbs:
if conf.excludeSysDbs and db in self.excludeDbsList: if conf.excludeSysDbs and db in self.excludeDbsList:
infoMsg = "skipping system database '%s'" % db infoMsg = "skipping system database '%s'" % db
@ -63,7 +63,7 @@ class Enumeration(GenericEnumeration):
continue continue
query = rootQuery.inband.query % db query = rootQuery.inband.query % db
value = inject.getValue(query, blind=False, error=False) value = inject.getValue(query, blind=False)
if value: if value:
kb.data.cachedTables[db] = arrayizeValue(value) kb.data.cachedTables[db] = arrayizeValue(value)
@ -81,7 +81,7 @@ class Enumeration(GenericEnumeration):
logger.info(infoMsg) logger.info(infoMsg)
query = rootQuery.blind.count % db query = rootQuery.blind.count % db
count = inject.getValue(query, inband=False, charsetType=2) count = inject.getValue(query, inband=False, error=False, charsetType=2)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
warnMsg = "unable to retrieve the number of " warnMsg = "unable to retrieve the number of "
@ -93,7 +93,7 @@ class Enumeration(GenericEnumeration):
for index in range(int(count)): for index in range(int(count)):
query = rootQuery.blind.query % (db, index, db) query = rootQuery.blind.query % (db, index, db)
table = inject.getValue(query, inband=False) table = inject.getValue(query, inband=False, error=False)
tables.append(table) tables.append(table)
kb.hintValue = table kb.hintValue = table
@ -144,10 +144,10 @@ class Enumeration(GenericEnumeration):
continue continue
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or conf.direct: if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
query = rootQuery.inband.query % db query = rootQuery.inband.query % db
query += tblQuery query += tblQuery
values = inject.getValue(query, blind=False, error=False) values = inject.getValue(query, blind=False)
if values: if values:
if isinstance(values, basestring): if isinstance(values, basestring):
@ -165,7 +165,7 @@ class Enumeration(GenericEnumeration):
query = rootQuery.blind.count2 query = rootQuery.blind.count2
query = query % db query = query % db
query += " AND %s" % tblQuery query += " AND %s" % tblQuery
count = inject.getValue(query, inband=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
warnMsg = "no table" warnMsg = "no table"
@ -184,7 +184,7 @@ class Enumeration(GenericEnumeration):
query = query % db query = query % db
query += " AND %s" % tblQuery query += " AND %s" % tblQuery
query = agent.limitQuery(index, query, tblCond) query = agent.limitQuery(index, query, tblCond)
tbl = inject.getValue(query, inband=False) tbl = inject.getValue(query, inband=False, error=False)
kb.hintValue = tbl kb.hintValue = tbl
foundTbls[db].append(tbl) foundTbls[db].append(tbl)
@ -229,10 +229,10 @@ class Enumeration(GenericEnumeration):
continue continue
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or conf.direct: if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
query = rootQuery.inband.query % (db, db, db, db, db) query = rootQuery.inband.query % (db, db, db, db, db)
query += " AND %s" % colQuery.replace("[DB]", db) query += " AND %s" % colQuery.replace("[DB]", db)
values = inject.getValue(query, blind=False, error=False) values = inject.getValue(query, blind=False)
if values: if values:
if isinstance(values, basestring): if isinstance(values, basestring):
@ -270,7 +270,7 @@ class Enumeration(GenericEnumeration):
query = rootQuery.blind.count2 query = rootQuery.blind.count2
query = query % (db, db, db, db, db) query = query % (db, db, db, db, db)
query += " AND %s" % colQuery.replace("[DB]", db) query += " AND %s" % colQuery.replace("[DB]", db)
count = inject.getValue(query, inband=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
warnMsg = "no tables contain column" warnMsg = "no tables contain column"
@ -289,7 +289,7 @@ class Enumeration(GenericEnumeration):
query = query % (db, db, db, db, db) query = query % (db, db, db, db, db)
query += " AND %s" % colQuery.replace("[DB]", db) query += " AND %s" % colQuery.replace("[DB]", db)
query = agent.limitQuery(index, query, colCond.replace("[DB]", db)) query = agent.limitQuery(index, query, colCond.replace("[DB]", db))
tbl = inject.getValue(query, inband=False) tbl = inject.getValue(query, inband=False, error=False)
kb.hintValue = tbl kb.hintValue = tbl
if tbl not in dbs[db]: if tbl not in dbs[db]:

View File

@ -41,7 +41,7 @@ class Enumeration(GenericEnumeration):
# Set containing the list of DBMS administrators # Set containing the list of DBMS administrators
areAdmins = set() areAdmins = set()
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or conf.direct: if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
if query2: if query2:
query = rootQuery.inband.query2 query = rootQuery.inband.query2
condition = rootQuery.inband.condition2 condition = rootQuery.inband.condition2
@ -54,7 +54,7 @@ class Enumeration(GenericEnumeration):
query += " WHERE " query += " WHERE "
query += " OR ".join("%s = '%s'" % (condition, user) for user in users) query += " OR ".join("%s = '%s'" % (condition, user) for user in users)
values = inject.getValue(query, blind=False, error=False) values = inject.getValue(query, blind=False)
if not values and not query2: if not values and not query2:
infoMsg = "trying with table USER_ROLE_PRIVS" infoMsg = "trying with table USER_ROLE_PRIVS"
@ -119,7 +119,7 @@ class Enumeration(GenericEnumeration):
query = rootQuery.blind.count2 % queryUser query = rootQuery.blind.count2 % queryUser
else: else:
query = rootQuery.blind.count % queryUser query = rootQuery.blind.count % queryUser
count = inject.getValue(query, inband=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
if not count.isdigit() and not query2: if not count.isdigit() and not query2:
@ -145,7 +145,7 @@ class Enumeration(GenericEnumeration):
query = rootQuery.blind.query2 % (queryUser, index) query = rootQuery.blind.query2 % (queryUser, index)
else: else:
query = rootQuery.blind.query % (queryUser, index) query = rootQuery.blind.query % (queryUser, index)
role = inject.getValue(query, inband=False) role = inject.getValue(query, inband=False, error=False)
# In Oracle we get the list of roles as string # In Oracle we get the list of roles as string
roles.add(role) roles.add(role)
@ -201,10 +201,10 @@ class Enumeration(GenericEnumeration):
colQuery = colQuery % column colQuery = colQuery % column
for db in dbs.keys(): for db in dbs.keys():
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or conf.direct: if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
query = rootQuery.inband.query query = rootQuery.inband.query
query += colQuery query += colQuery
values = inject.getValue(query, blind=False, error=False) values = inject.getValue(query, blind=False)
if values: if values:
if isinstance(values, basestring): if isinstance(values, basestring):
@ -241,7 +241,7 @@ class Enumeration(GenericEnumeration):
query = rootQuery.blind.count2 query = rootQuery.blind.count2
query += " WHERE %s" % colQuery query += " WHERE %s" % colQuery
count = inject.getValue(query, inband=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
warnMsg = "no tables contain column" warnMsg = "no tables contain column"
@ -259,7 +259,7 @@ class Enumeration(GenericEnumeration):
query = rootQuery.blind.query2 query = rootQuery.blind.query2
query += " WHERE %s" % colQuery query += " WHERE %s" % colQuery
query = agent.limitQuery(index, query) query = agent.limitQuery(index, query)
tbl = inject.getValue(query, inband=False) tbl = inject.getValue(query, inband=False, error=False)
kb.hintValue = tbl kb.hintValue = tbl
if tbl not in dbs[db]: if tbl not in dbs[db]:

View File

@ -149,12 +149,12 @@ class Enumeration:
condition = ( getIdentifiedDBMS() == DBMS.MSSQL and kb.dbmsVersion[0] in ( "2005", "2008" ) ) condition = ( getIdentifiedDBMS() == DBMS.MSSQL and kb.dbmsVersion[0] in ( "2005", "2008" ) )
condition |= ( getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema ) condition |= ( getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema )
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or conf.direct: if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
if condition: if condition:
query = rootQuery.inband.query2 query = rootQuery.inband.query2
else: else:
query = rootQuery.inband.query query = rootQuery.inband.query
value = inject.getValue(query, blind=False, error=False) value = inject.getValue(query, blind=False)
if value: if value:
kb.data.cachedUsers = arrayizeValue(value) kb.data.cachedUsers = arrayizeValue(value)
@ -167,7 +167,7 @@ class Enumeration:
query = rootQuery.blind.count2 query = rootQuery.blind.count2
else: else:
query = rootQuery.blind.count query = rootQuery.blind.count
count = inject.getValue(query, inband=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
errMsg = "unable to retrieve the number of database users" errMsg = "unable to retrieve the number of database users"
@ -186,7 +186,7 @@ class Enumeration:
query = rootQuery.blind.query2 % index query = rootQuery.blind.query2 % index
else: else:
query = rootQuery.blind.query % index query = rootQuery.blind.query % index
user = inject.getValue(query, inband=False) user = inject.getValue(query, inband=False, error=False)
if user: if user:
kb.data.cachedUsers.append(user) kb.data.cachedUsers.append(user)
@ -208,7 +208,7 @@ class Enumeration:
logger.info(infoMsg) logger.info(infoMsg)
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or conf.direct: if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
if getIdentifiedDBMS() == DBMS.MSSQL and kb.dbmsVersion[0] in ( "2005", "2008" ): if getIdentifiedDBMS() == DBMS.MSSQL and kb.dbmsVersion[0] in ( "2005", "2008" ):
query = rootQuery.inband.query2 query = rootQuery.inband.query2
else: else:
@ -230,7 +230,7 @@ class Enumeration:
query += " WHERE %s = '%s'" % (condition, conf.user) query += " WHERE %s = '%s'" % (condition, conf.user)
value = inject.getValue(query, blind=False, error=False) value = inject.getValue(query, blind=False)
if value: if value:
for user, password in value: for user, password in value:
@ -276,7 +276,7 @@ class Enumeration:
query = rootQuery.blind.count2 % user query = rootQuery.blind.count2 % user
else: else:
query = rootQuery.blind.count % user query = rootQuery.blind.count % user
count = inject.getValue(query, inband=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
warnMsg = "unable to retrieve the number of password " warnMsg = "unable to retrieve the number of password "
@ -312,7 +312,7 @@ class Enumeration:
query = rootQuery.blind.query % (user, index, user) query = rootQuery.blind.query % (user, index, user)
else: else:
query = rootQuery.blind.query % (user, index) query = rootQuery.blind.query % (user, index)
password = inject.getValue(query, inband=False) password = inject.getValue(query, inband=False, error=False)
if getIdentifiedDBMS() == DBMS.SYBASE: if getIdentifiedDBMS() == DBMS.SYBASE:
getCurrentThreadData().disableStdOut = False getCurrentThreadData().disableStdOut = False
password = "0x%s" % strToHex(password) password = "0x%s" % strToHex(password)
@ -429,7 +429,7 @@ class Enumeration:
"E": "EXECUTE" "E": "EXECUTE"
} }
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or conf.direct: if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
query = rootQuery.inband.query2 query = rootQuery.inband.query2
condition = rootQuery.inband.condition2 condition = rootQuery.inband.condition2
@ -451,7 +451,7 @@ class Enumeration:
else: else:
query += " OR ".join("%s = '%s'" % (condition, user) for user in users) query += " OR ".join("%s = '%s'" % (condition, user) for user in users)
values = inject.getValue(query, blind=False, error=False) values = inject.getValue(query, blind=False)
if not values and getIdentifiedDBMS() == DBMS.ORACLE and not query2: if not values and getIdentifiedDBMS() == DBMS.ORACLE and not query2:
infoMsg = "trying with table USER_SYS_PRIVS" infoMsg = "trying with table USER_SYS_PRIVS"
@ -554,7 +554,7 @@ class Enumeration:
query = rootQuery.blind.count2 % queryUser query = rootQuery.blind.count2 % queryUser
else: else:
query = rootQuery.blind.count % queryUser query = rootQuery.blind.count % queryUser
count = inject.getValue(query, inband=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
if not (isinstance(count, basestring) and count.isdigit()) and getIdentifiedDBMS() == DBMS.ORACLE and not query2: if not (isinstance(count, basestring) and count.isdigit()) and getIdentifiedDBMS() == DBMS.ORACLE and not query2:
@ -590,7 +590,7 @@ class Enumeration:
query = rootQuery.blind.query % (index, queryUser) query = rootQuery.blind.query % (index, queryUser)
else: else:
query = rootQuery.blind.query % (queryUser, index) query = rootQuery.blind.query % (queryUser, index)
privilege = inject.getValue(query, inband=False) privilege = inject.getValue(query, inband=False, error=False)
# In PostgreSQL we get 1 if the privilege is True, # In PostgreSQL we get 1 if the privilege is True,
# 0 otherwise # 0 otherwise
@ -675,12 +675,12 @@ class Enumeration:
rootQuery = queries[getIdentifiedDBMS()].dbs rootQuery = queries[getIdentifiedDBMS()].dbs
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or conf.direct: if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
query = rootQuery.inband.query2 query = rootQuery.inband.query2
else: else:
query = rootQuery.inband.query query = rootQuery.inband.query
value = inject.getValue(query, blind=False, error=False) value = inject.getValue(query, blind=False)
if value: if value:
kb.data.cachedDbs = arrayizeValue(value) kb.data.cachedDbs = arrayizeValue(value)
@ -693,7 +693,7 @@ class Enumeration:
query = rootQuery.blind.count2 query = rootQuery.blind.count2
else: else:
query = rootQuery.blind.count query = rootQuery.blind.count
count = inject.getValue(query, inband=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
errMsg = "unable to retrieve the number of databases" errMsg = "unable to retrieve the number of databases"
@ -708,7 +708,7 @@ class Enumeration:
query = rootQuery.blind.query2 % index query = rootQuery.blind.query2 % index
else: else:
query = rootQuery.blind.query % index query = rootQuery.blind.query % index
db = inject.getValue(query, inband=False) db = inject.getValue(query, inband=False, error=False)
if db: if db:
kb.data.cachedDbs.append(db) kb.data.cachedDbs.append(db)
@ -782,7 +782,7 @@ class Enumeration:
else: else:
dbs = kb.data.cachedDbs dbs = kb.data.cachedDbs
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or conf.direct: if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
query = rootQuery.inband.query query = rootQuery.inband.query
condition = rootQuery.inband.condition if 'condition' in rootQuery.inband else None condition = rootQuery.inband.condition if 'condition' in rootQuery.inband else None
@ -802,7 +802,7 @@ class Enumeration:
if getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE): if getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
query = safeStringFormat(query, conf.db) query = safeStringFormat(query, conf.db)
value = inject.getValue(query, blind=False, error=False) value = inject.getValue(query, blind=False)
if value: if value:
if getIdentifiedDBMS() == DBMS.SQLITE: if getIdentifiedDBMS() == DBMS.SQLITE:
@ -838,7 +838,7 @@ class Enumeration:
query = rootQuery.blind.count query = rootQuery.blind.count
else: else:
query = rootQuery.blind.count % db query = rootQuery.blind.count % db
count = inject.getValue(query, inband=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
warnMsg = "unable to retrieve the number of " warnMsg = "unable to retrieve the number of "
@ -863,7 +863,7 @@ class Enumeration:
query = rootQuery.blind.query % index query = rootQuery.blind.query % index
else: else:
query = rootQuery.blind.query % (db, index) query = rootQuery.blind.query % (db, index)
table = inject.getValue(query, inband=False) table = inject.getValue(query, inband=False, error=False)
tables.append(table) tables.append(table)
kb.hintValue = table kb.hintValue = table
@ -975,7 +975,7 @@ class Enumeration:
infoMsg += "on database '%s'" % conf.db infoMsg += "on database '%s'" % conf.db
logger.info(infoMsg) logger.info(infoMsg)
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or conf.direct: if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ): if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ):
query = rootQuery.inband.query % (conf.tbl, conf.db) query = rootQuery.inband.query % (conf.tbl, conf.db)
query += condQuery query += condQuery
@ -991,7 +991,7 @@ class Enumeration:
elif getIdentifiedDBMS() == DBMS.SQLITE: elif getIdentifiedDBMS() == DBMS.SQLITE:
query = rootQuery.inband.query % conf.tbl query = rootQuery.inband.query % conf.tbl
value = inject.getValue(query, blind=False, error=False) value = inject.getValue(query, blind=False)
if getIdentifiedDBMS() == DBMS.SQLITE: if getIdentifiedDBMS() == DBMS.SQLITE:
parseSqliteTableSchema(value) parseSqliteTableSchema(value)
@ -1025,13 +1025,13 @@ class Enumeration:
query += condQuery query += condQuery
elif getIdentifiedDBMS() == DBMS.SQLITE: elif getIdentifiedDBMS() == DBMS.SQLITE:
query = rootQuery.blind.query % conf.tbl query = rootQuery.blind.query % conf.tbl
value = inject.getValue(query, inband=False) value = inject.getValue(query, inband=False, error=False)
parseSqliteTableSchema(value) parseSqliteTableSchema(value)
return kb.data.cachedColumns return kb.data.cachedColumns
count = inject.getValue(query, inband=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
errMsg = "unable to retrieve the number of columns " errMsg = "unable to retrieve the number of columns "
@ -1066,7 +1066,7 @@ class Enumeration:
field = None field = None
query = agent.limitQuery(index, query, field) query = agent.limitQuery(index, query, field)
column = inject.getValue(query, inband=False) column = inject.getValue(query, inband=False, error=False)
if not onlyColNames: if not onlyColNames:
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ): if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ):
@ -1080,7 +1080,7 @@ class Enumeration:
elif getIdentifiedDBMS() == DBMS.FIREBIRD: elif getIdentifiedDBMS() == DBMS.FIREBIRD:
query = rootQuery.blind.query2 % (conf.tbl, column) query = rootQuery.blind.query2 % (conf.tbl, column)
colType = inject.getValue(query, inband=False) colType = inject.getValue(query, inband=False, error=False)
if getIdentifiedDBMS() == DBMS.FIREBIRD: if getIdentifiedDBMS() == DBMS.FIREBIRD:
colType = firebirdTypes[colType] if colType in firebirdTypes else colType colType = firebirdTypes[colType] if colType in firebirdTypes else colType
@ -1172,14 +1172,14 @@ class Enumeration:
entriesCount = 0 entriesCount = 0
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or conf.direct: if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
if getIdentifiedDBMS() == DBMS.ORACLE: if getIdentifiedDBMS() == DBMS.ORACLE:
query = rootQuery.inband.query % (colString, conf.tbl.upper()) query = rootQuery.inband.query % (colString, conf.tbl.upper())
elif getIdentifiedDBMS() == DBMS.SQLITE: elif getIdentifiedDBMS() == DBMS.SQLITE:
query = rootQuery.inband.query % (colString, conf.tbl) query = rootQuery.inband.query % (colString, conf.tbl)
else: else:
query = rootQuery.inband.query % (colString, conf.db, conf.tbl) query = rootQuery.inband.query % (colString, conf.db, conf.tbl)
entries = inject.getValue(query, blind=False, error=False, dump=True) entries = inject.getValue(query, blind=False, dump=True)
if entries: if entries:
if isinstance(entries, basestring): if isinstance(entries, basestring):
@ -1227,7 +1227,7 @@ class Enumeration:
query = rootQuery.blind.count % conf.tbl query = rootQuery.blind.count % conf.tbl
else: else:
query = rootQuery.blind.count % (conf.db, conf.tbl) query = rootQuery.blind.count % (conf.db, conf.tbl)
count = inject.getValue(query, inband=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
warnMsg = "unable to retrieve the number of " warnMsg = "unable to retrieve the number of "
@ -1260,7 +1260,7 @@ class Enumeration:
logger.info(infoMsg) logger.info(infoMsg)
query = rootQuery.blind.count2 % (column, conf.tbl) query = rootQuery.blind.count2 % (column, conf.tbl)
value = inject.getValue(query, inband=False) value = inject.getValue(query, inband=False, error=False)
if isNumPosStrValue(value): if isNumPosStrValue(value):
validColumnList = True validColumnList = True
@ -1307,7 +1307,7 @@ class Enumeration:
else: else:
query = rootQuery.blind.query2 % (column, conf.tbl, colList[0], pivotValue) query = rootQuery.blind.query2 % (column, conf.tbl, colList[0], pivotValue)
value = inject.getValue(query, inband=False) value = inject.getValue(query, inband=False, error=False)
if column == colList[0]: if column == colList[0]:
if not value: if not value:
@ -1345,7 +1345,7 @@ class Enumeration:
elif getIdentifiedDBMS() == DBMS.FIREBIRD: elif getIdentifiedDBMS() == DBMS.FIREBIRD:
query = rootQuery.blind.query % (index, column, conf.tbl) query = rootQuery.blind.query % (index, column, conf.tbl)
value = inject.getValue(query, inband=False) value = inject.getValue(query, inband=False, error=False)
lengths[column] = max(lengths[column], len(value) if value else 0) lengths[column] = max(lengths[column], len(value) if value else 0)
entries[column].append(value) entries[column].append(value)
@ -1514,14 +1514,14 @@ class Enumeration:
dbQuery = "%s%s" % (dbCond, dbCondParam) dbQuery = "%s%s" % (dbCond, dbCondParam)
dbQuery = dbQuery % db dbQuery = dbQuery % db
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or conf.direct: if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
query = rootQuery.inband.query2 query = rootQuery.inband.query2
else: else:
query = rootQuery.inband.query query = rootQuery.inband.query
query += dbQuery query += dbQuery
query += exclDbsQuery query += exclDbsQuery
values = inject.getValue(query, blind=False, error=False) values = inject.getValue(query, blind=False)
if values: if values:
if isinstance(values, basestring): if isinstance(values, basestring):
@ -1542,7 +1542,7 @@ class Enumeration:
query = rootQuery.blind.count query = rootQuery.blind.count
query += dbQuery query += dbQuery
query += exclDbsQuery query += exclDbsQuery
count = inject.getValue(query, inband=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
warnMsg = "no database" warnMsg = "no database"
@ -1564,7 +1564,7 @@ class Enumeration:
query += exclDbsQuery query += exclDbsQuery
query = agent.limitQuery(index, query, dbCond) query = agent.limitQuery(index, query, dbCond)
foundDbs.append(inject.getValue(query, inband=False)) foundDbs.append(inject.getValue(query, inband=False, error=False))
return foundDbs return foundDbs
@ -1622,11 +1622,11 @@ class Enumeration:
tblQuery = "%s%s" % (tblCond, tblCondParam) tblQuery = "%s%s" % (tblCond, tblCondParam)
tblQuery = tblQuery % tbl tblQuery = tblQuery % tbl
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or conf.direct: if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
query = rootQuery.inband.query query = rootQuery.inband.query
query += tblQuery query += tblQuery
query += exclDbsQuery query += exclDbsQuery
values = inject.getValue(query, blind=False, error=False) values = inject.getValue(query, blind=False)
if values: if values:
if isinstance(values, basestring): if isinstance(values, basestring):
@ -1647,7 +1647,7 @@ class Enumeration:
query = rootQuery.blind.count query = rootQuery.blind.count
query += tblQuery query += tblQuery
query += exclDbsQuery query += exclDbsQuery
count = inject.getValue(query, inband=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
warnMsg = "no databases have table" warnMsg = "no databases have table"
@ -1665,7 +1665,7 @@ class Enumeration:
query += tblQuery query += tblQuery
query += exclDbsQuery query += exclDbsQuery
query = agent.limitQuery(index, query) query = agent.limitQuery(index, query)
foundDb = inject.getValue(query, inband=False) foundDb = inject.getValue(query, inband=False, error=False)
if foundDb not in foundTbls: if foundDb not in foundTbls:
foundTbls[foundDb] = [] foundTbls[foundDb] = []
@ -1685,7 +1685,7 @@ class Enumeration:
query = rootQuery.blind.count2 query = rootQuery.blind.count2
query = query % db query = query % db
query += " AND %s" % tblQuery query += " AND %s" % tblQuery
count = inject.getValue(query, inband=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
warnMsg = "no table" warnMsg = "no table"
@ -1704,7 +1704,7 @@ class Enumeration:
query = query % db query = query % db
query += " AND %s" % tblQuery query += " AND %s" % tblQuery
query = agent.limitQuery(index, query) query = agent.limitQuery(index, query)
foundTbl = inject.getValue(query, inband=False) foundTbl = inject.getValue(query, inband=False, error=False)
kb.hintValue = foundTbl kb.hintValue = foundTbl
foundTbls[db].append(foundTbl) foundTbls[db].append(foundTbl)
@ -1772,11 +1772,11 @@ class Enumeration:
colQuery = "%s%s" % (colCond, colCondParam) colQuery = "%s%s" % (colCond, colCondParam)
colQuery = colQuery % column colQuery = colQuery % column
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or conf.direct: if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
query = rootQuery.inband.query query = rootQuery.inband.query
query += colQuery query += colQuery
query += exclDbsQuery query += exclDbsQuery
values = inject.getValue(query, blind=False, error=False) values = inject.getValue(query, blind=False)
if values: if values:
if isinstance(values, basestring): if isinstance(values, basestring):
@ -1815,7 +1815,7 @@ class Enumeration:
query = rootQuery.blind.count query = rootQuery.blind.count
query += colQuery query += colQuery
query += exclDbsQuery query += exclDbsQuery
count = inject.getValue(query, inband=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
warnMsg = "no databases have tables containing column" warnMsg = "no databases have tables containing column"
@ -1833,7 +1833,7 @@ class Enumeration:
query += colQuery query += colQuery
query += exclDbsQuery query += exclDbsQuery
query = agent.limitQuery(index, query) query = agent.limitQuery(index, query)
db = inject.getValue(query, inband=False) db = inject.getValue(query, inband=False, error=False)
if db not in dbs: if db not in dbs:
dbs[db] = {} dbs[db] = {}
@ -1855,7 +1855,7 @@ class Enumeration:
query = rootQuery.blind.count2 query = rootQuery.blind.count2
query = query % db query = query % db
query += " AND %s" % colQuery query += " AND %s" % colQuery
count = inject.getValue(query, inband=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
warnMsg = "no tables contain column" warnMsg = "no tables contain column"
@ -1874,7 +1874,7 @@ class Enumeration:
query = query % db query = query % db
query += " AND %s" % colQuery query += " AND %s" % colQuery
query = agent.limitQuery(index, query) query = agent.limitQuery(index, query)
tbl = inject.getValue(query, inband=False) tbl = inject.getValue(query, inband=False, error=False)
kb.hintValue = tbl kb.hintValue = tbl
if tbl not in dbs[db]: if tbl not in dbs[db]: