mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-05-10 10:43:44 +03:00
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:
parent
81be23976e
commit
daebb0010b
|
@ -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(", ", ",")
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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": (
|
||||||
|
|
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -178,7 +156,7 @@ 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)
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -324,25 +298,54 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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,10 +103,11 @@ 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
|
||||||
|
@ -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 "
|
||||||
|
@ -198,14 +205,14 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
|
||||||
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):
|
||||||
|
|
|
@ -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]:
|
||||||
|
|
|
@ -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]:
|
||||||
|
|
|
@ -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]:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user