Skip to content

Commit cea5127

Browse files
committed
Update for an Issue sqlmapproject#6
1 parent c3d191e commit cea5127

File tree

3 files changed

+30
-8
lines changed

3 files changed

+30
-8
lines changed

lib/core/agent.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,7 @@ def concatQuery(self, query, unpack=True):
555555

556556
return concatenatedQuery
557557

558-
def forgeInbandQuery(self, query, position, count, comment, prefix, suffix, char, where, multipleUnions=None, limited=False):
558+
def forgeInbandQuery(self, query, position, count, comment, prefix, suffix, char, where, multipleUnions=None, limited=False, fromTable=None):
559559
"""
560560
Take in input an query (pseudo query) string and return its
561561
processed UNION ALL SELECT query.
@@ -586,6 +586,8 @@ def forgeInbandQuery(self, query, position, count, comment, prefix, suffix, char
586586
@rtype: C{str}
587587
"""
588588

589+
fromTable = fromTable or FROM_DUMMY_TABLE.get(Backend.getIdentifiedDbms(), "")
590+
589591
if query.startswith("SELECT "):
590592
query = query[len("SELECT "):]
591593

@@ -598,7 +600,7 @@ def forgeInbandQuery(self, query, position, count, comment, prefix, suffix, char
598600

599601
if limited:
600602
inbandQuery += ','.join(char if _ != position else '(SELECT %s)' % query for _ in xrange(0, count))
601-
inbandQuery += FROM_DUMMY_TABLE.get(Backend.getIdentifiedDbms(), "")
603+
inbandQuery += fromTable
602604
inbandQuery = self.suffixQuery(inbandQuery, comment, suffix)
603605

604606
return inbandQuery
@@ -615,8 +617,8 @@ def forgeInbandQuery(self, query, position, count, comment, prefix, suffix, char
615617
intoRegExp = intoRegExp.group(1)
616618
query = query[:query.index(intoRegExp)]
617619

618-
if Backend.getIdentifiedDbms() in FROM_DUMMY_TABLE and inbandQuery.endswith(FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()]):
619-
inbandQuery = inbandQuery[:-len(FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()])]
620+
if fromTable and inbandQuery.endswith(fromTable):
621+
inbandQuery = inbandQuery[:-len(fromTable)]
620622

621623
for element in xrange(0, count):
622624
if element > 0:
@@ -635,9 +637,9 @@ def forgeInbandQuery(self, query, position, count, comment, prefix, suffix, char
635637
conditionIndex = query.index(" FROM ")
636638
inbandQuery += query[conditionIndex:]
637639

638-
if Backend.getIdentifiedDbms() in FROM_DUMMY_TABLE:
640+
if fromTable:
639641
if " FROM " not in inbandQuery or "(CASE " in inbandQuery or "(IIF" in inbandQuery:
640-
inbandQuery += FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()]
642+
inbandQuery += fromTable
641643

642644
if intoRegExp:
643645
inbandQuery += intoRegExp
@@ -654,8 +656,8 @@ def forgeInbandQuery(self, query, position, count, comment, prefix, suffix, char
654656
else:
655657
inbandQuery += char
656658

657-
if Backend.getIdentifiedDbms() in FROM_DUMMY_TABLE:
658-
inbandQuery += FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()]
659+
if fromTable:
660+
inbandQuery += fromTable
659661

660662
inbandQuery = self.suffixQuery(inbandQuery, comment, suffix)
661663

lib/core/settings.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,3 +458,6 @@
458458

459459
# Regular expression used for extracting ASP.NET View State values
460460
VIEWSTATE_REGEX = r'(?P<name>__VIEWSTATE[^"]*)[^>]+value="(?P<name>[^"]+)'
461+
462+
# Number of rows to generate inside the full union test for limited output (mustn't be too large to prevent payload length problems)
463+
LIMITED_ROWS_TEST_NUMBER = 15

lib/techniques/union/test.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from lib.core.data import logger
2929
from lib.core.dicts import FROM_DUMMY_TABLE
3030
from lib.core.enums import PAYLOAD
31+
from lib.core.settings import LIMITED_ROWS_TEST_NUMBER
3132
from lib.core.settings import UNION_MIN_RESPONSE_CHARS
3233
from lib.core.settings import UNION_STDEV_COEFF
3334
from lib.core.settings import MIN_RATIO
@@ -205,6 +206,22 @@ def __unionPosition(comment, place, parameter, prefix, suffix, count, where=PAYL
205206

206207
if not all(_ in content for _ in (phrase, phrase2)):
207208
vector = (position, count, comment, prefix, suffix, kb.uChar, PAYLOAD.WHERE.NEGATIVE, kb.unionDuplicates)
209+
elif not kb.unionDuplicates:
210+
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())
211+
212+
# Check for limited row output
213+
query = agent.forgeInbandQuery(randQueryUnescaped, position, count, comment, prefix, suffix, kb.uChar, where, fromTable=fromTable)
214+
payload = agent.payload(place=place, parameter=parameter, newValue=query, where=where)
215+
216+
# Perform the request
217+
page, headers = Request.queryPage(payload, place=place, content=True, raise404=False)
218+
content = "%s%s".lower() % (removeReflectiveValues(page, payload) or "", \
219+
removeReflectiveValues(listToStrValue(headers.headers if headers else None), \
220+
payload, True) or "")
221+
if content.count(phrase) > 0 and content.count(phrase) < LIMITED_ROWS_TEST_NUMBER:
222+
warnMsg = "output with limited number of rows detected. Switching to partial mode"
223+
logger.warn(warnMsg)
224+
vector = (position, count, comment, prefix, suffix, kb.uChar, PAYLOAD.WHERE.NEGATIVE, kb.unionDuplicates)
208225

209226
unionErrorCase = kb.errorIsNone and wasLastRequestDBMSError()
210227

0 commit comments

Comments
 (0)