mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2026-08-04 14:55:40 +00:00
Fixing desync error from SLOW_ORDER_COUNT_THRESHOLD
This commit is contained in:
parent
1cdc69eb0e
commit
40ccd801dc
5 changed files with 58 additions and 24 deletions
|
|
@ -20,7 +20,7 @@ from lib.core.enums import OS
|
|||
from thirdparty import six
|
||||
|
||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||
VERSION = "1.10.7.74"
|
||||
VERSION = "1.10.7.75"
|
||||
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
||||
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
|
||||
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
|
||||
|
|
@ -879,9 +879,6 @@ HASHDB_MILESTONE_VALUE = "MvKpZrBqTn" # python -c 'import random, string; print
|
|||
# Warn user of possible delay due to large page dump in full UNION query injections
|
||||
LARGE_OUTPUT_THRESHOLD = 1024 ** 2
|
||||
|
||||
# On huge tables there is a considerable slowdown if every row retrieval requires ORDER BY (most noticable in table dumping using ERROR injections)
|
||||
SLOW_ORDER_COUNT_THRESHOLD = 10000
|
||||
|
||||
# Give up on hash recognition if nothing was found in first given number of rows
|
||||
HASH_RECOGNITION_QUIT_THRESHOLD = 1000
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ from lib.core.common import initTechnique
|
|||
from lib.core.common import isListLike
|
||||
from lib.core.common import isNumPosStrValue
|
||||
from lib.core.common import listToStrValue
|
||||
from lib.core.common import readInput
|
||||
from lib.core.common import unArrayizeValue
|
||||
from lib.core.common import wasLastResponseHTTPError
|
||||
from lib.core.compat import xrange
|
||||
|
|
@ -51,7 +50,6 @@ from lib.core.settings import MIN_ERROR_CHUNK_LENGTH
|
|||
from lib.core.settings import NULL
|
||||
from lib.core.settings import PARTIAL_VALUE_MARKER
|
||||
from lib.core.settings import ROTATING_CHARS
|
||||
from lib.core.settings import SLOW_ORDER_COUNT_THRESHOLD
|
||||
from lib.core.settings import SQL_SCALAR_REGEX
|
||||
from lib.core.settings import TURN_OFF_RESUME_INFO_LIMIT
|
||||
from lib.core.threads import getCurrentThreadData
|
||||
|
|
@ -322,7 +320,7 @@ def errorUse(expression, dump=False):
|
|||
# entry at a time
|
||||
# NOTE: we assume that only queries that get data from a table can
|
||||
# return multiple entries
|
||||
if (dump and (conf.limitStart or conf.limitStop)) or (" FROM " in expression.upper() and ((Backend.getIdentifiedDbms() not in FROM_DUMMY_TABLE) or (Backend.getIdentifiedDbms() in FROM_DUMMY_TABLE and not expression.upper().endswith(FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()]))) and ("(CASE" not in expression.upper() or ("(CASE" in expression.upper() and "WHEN use" in expression))) and not re.search(SQL_SCALAR_REGEX, expression, re.I):
|
||||
if not re.search(SQL_SCALAR_REGEX, expression, re.I) and ((dump and (conf.limitStart or conf.limitStop)) or (" FROM " in expression.upper() and ((Backend.getIdentifiedDbms() not in FROM_DUMMY_TABLE) or (Backend.getIdentifiedDbms() in FROM_DUMMY_TABLE and not expression.upper().endswith(FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()]))) and ("(CASE" not in expression.upper() or ("(CASE" in expression.upper() and "WHEN use" in expression)))):
|
||||
expression, limitCond, topLimit, startLimit, stopLimit = agent.limitCondition(expression, dump)
|
||||
|
||||
if limitCond:
|
||||
|
|
@ -367,13 +365,10 @@ def errorUse(expression, dump=False):
|
|||
return value
|
||||
|
||||
if isNumPosStrValue(count) and int(count) > 1:
|
||||
if " ORDER BY " in expression and (stopLimit - startLimit) > SLOW_ORDER_COUNT_THRESHOLD:
|
||||
message = "due to huge table size do you want to remove "
|
||||
message += "ORDER BY clause gaining speed over consistency? [y/N] "
|
||||
|
||||
if readInput(message, default='N', boolean=True):
|
||||
expression = expression[:expression.index(" ORDER BY ")]
|
||||
|
||||
# NOTE: the ORDER BY clause is deliberately NOT stripped here. This path fetches each column
|
||||
# of a row in a separate LIMIT/OFFSET query, so dropping ORDER BY would let the per-column
|
||||
# offsets resolve to different physical rows and silently misalign cells across the row. Huge
|
||||
# tables are handled cheaply and safely by keyset (seek) pagination (see plugins/generic/entries.py).
|
||||
numThreads = min(conf.threads, (stopLimit - startLimit))
|
||||
|
||||
threadData = getCurrentThreadData()
|
||||
|
|
|
|||
|
|
@ -189,12 +189,12 @@ def _dumpSingle(tbl, colList, count, cursor, tableRef, entries, lengths):
|
|||
produced = 0
|
||||
|
||||
while produced < target:
|
||||
if pivotValue is None:
|
||||
query = blind.keyset_first % (field, tableRef)
|
||||
else:
|
||||
query = _embed(blind.keyset_next, pivotValue, field, tableRef, field)
|
||||
|
||||
query = agent.whereQuery(query)
|
||||
# Advance with ORDER BY ... LIMIT 1 (like the composite path), NOT MIN(): the value-extraction
|
||||
# casts the aggregated column to VARCHAR *inside* MIN(), yielding a LEXICAL minimum ('10' after
|
||||
# '1') that disagrees with the numeric '>' comparison and silently skips rows (2..9, 11..). The
|
||||
# ORDER BY is on the raw (numeric) column, so the next cursor value is the true successor.
|
||||
condition = "1=1" if pivotValue is None else "%s>%s" % (field, _lit(pivotValue))
|
||||
query = agent.whereQuery(blind.keyset_ordered % (field, tableRef, condition, field))
|
||||
value = unArrayizeValue(inject.getValue(query))
|
||||
|
||||
if isNoneValue(value) or value == NULL:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue