gazillion changes, nothing will work, muhahaha

This commit is contained in:
Miroslav Stampar 2012-02-17 14:22:48 +00:00
parent dcf7277a0f
commit aee269cc14
8 changed files with 492 additions and 549 deletions

View File

@ -61,6 +61,7 @@ from lib.core.convert import unicodeencode
from lib.core.convert import urldecode
from lib.core.convert import urlencode
from lib.core.enums import DBMS
from lib.core.enums import EXPECTED
from lib.core.enums import HTTPHEADER
from lib.core.enums import HTTPMETHOD
from lib.core.enums import OS
@ -2206,10 +2207,10 @@ def trimAlphaNum(value):
def isNumPosStrValue(value):
"""
Returns True if value is a string with a positive integer representation
Returns True if value is a string (or integer) with a positive integer representation
"""
return value and isinstance(value, basestring) and value.isdigit() and value != "0"
return (value and isinstance(value, basestring) and value.isdigit() and value != "0") or (isinstance(value, int) and value != 0)
@cachedmethod
def aliasToDbmsEnum(dbms):
@ -3096,3 +3097,36 @@ def getCounter(technique):
"""
return kb.counters.get(technique, 0)
def extractExpectedValue(value, expected):
"""
Extracts and returns expected value by a given type
"""
if not expected:
return value
value = unArrayizeValue(value)
if isNoneValue(value):
value = None
elif expected == EXPECTED.BOOL:
if isinstance(value, int):
value = bool(value)
elif isinstance(value, basestring):
value = value.strip().lower()
if value in ("true", "false"):
value = value == "true"
elif value in ("1", "-1"):
value = True
elif value == "0":
value = False
else:
value = None
elif expected == EXPECTED.INT:
if isinstance(value, basestring):
if value.isdigit():
value = int(value)
else:
value = None
return value

View File

@ -1467,6 +1467,7 @@ def __setKnowledgeBaseAttributes(flushAll=True):
kb.reflectiveCounters = {REFLECTIVE_COUNTER.MISS:0, REFLECTIVE_COUNTER.HIT:0}
kb.responseTimes = []
kb.resumedQueries = {}
kb.resumeValues = True
kb.safeCharEncode = False
kb.singleLogFlags = set()
kb.skipOthersDbms = None

View File

@ -57,6 +57,8 @@ DUMP_DEL_MARKER = "__DEL__"
PARAMETER_AMP_MARKER = "__AMP__"
PARAMETER_SEMICOLON_MARKER = "__SEMICOLON__"
PARTIAL_VALUE_MARKER = "__PARTIAL__"
URI_QUESTION_MARKER = "__QUESTION_MARK__"
PAYLOAD_DELIMITER = "\x00"

View File

@ -17,8 +17,10 @@ from lib.core.common import calculateDeltaSeconds
from lib.core.common import cleanQuery
from lib.core.common import dataToSessionFile
from lib.core.common import expandAsteriskForColumns
from lib.core.common import extractExpectedValue
from lib.core.common import getPublicTypeMembers
from lib.core.common import initTechnique
from lib.core.common import isNoneValue
from lib.core.common import isNumPosStrValue
from lib.core.common import isTechniqueAvailable
from lib.core.common import parseUnionPage
@ -72,7 +74,7 @@ def __goInference(payload, expression, charsetType=None, firstChar=None, lastCha
return value
def __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected=None, num=None, resumeValue=True, charsetType=None, firstChar=None, lastChar=None, dump=False):
def __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected=None, num=None, charsetType=None, firstChar=None, lastChar=None, dump=False):
outputs = []
origExpr = None
@ -91,16 +93,7 @@ def __goInferenceFields(expression, expressionFields, expressionFieldsList, payl
else:
expressionReplaced = expression.replace(expressionFields, field, 1)
if resumeValue:
output = resume(expressionReplaced, payload)
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 = __goInference(payload, expressionReplaced, charsetType, firstChar, lastChar, dump)
output = __goInference(payload, expressionReplaced, charsetType, firstChar, lastChar, dump)
if isinstance(num, int):
expression = origExpr
@ -109,7 +102,7 @@ def __goInferenceFields(expression, expressionFields, expressionFieldsList, payl
return outputs
def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, resumeValue=True, unpack=True, charsetType=None, firstChar=None, lastChar=None, dump=False):
def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, unpack=True, charsetType=None, firstChar=None, lastChar=None, dump=False):
"""
Retrieve the output of a SQL query characted by character taking
advantage of an blind SQL injection vulnerability on the affected
@ -129,14 +122,6 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
untilLimitChar = None
untilOrderChar = None
if resumeValue:
output = resume(expression, payload)
else:
output = None
if output and (expected is None or (expected == EXPECTED.INT and output.isdigit())):
return output
if not unpack:
return __goInference(payload, expression, charsetType, firstChar, lastChar, dump)
@ -229,12 +214,8 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
untilOrderChar = countedExpression.index(" ORDER BY ")
countedExpression = countedExpression[:untilOrderChar]
if resumeValue:
count = resume(countedExpression, payload)
if not stopLimit:
if not count or not count.isdigit():
count = __goInference(payload, countedExpression, 2, firstChar, lastChar)
count = __goInference(payload, countedExpression, 2, firstChar, lastChar)
if isNumPosStrValue(count):
count = int(count)
@ -298,17 +279,12 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
return None
elif (not count or int(count) == 0) and (not stopLimit or stopLimit == 0):
if not count:
warnMsg = "the SQL query provided does not "
warnMsg += "return any output"
logger.warn(warnMsg)
elif (not stopLimit or stopLimit == 0):
return None
try:
for num in xrange(startLimit, stopLimit):
output = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, num, resumeValue=resumeValue, charsetType=charsetType, firstChar=firstChar, lastChar=lastChar, dump=dump)
output = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, num, charsetType=charsetType, firstChar=firstChar, lastChar=lastChar, dump=dump)
outputs.append(output)
except KeyboardInterrupt:
@ -321,12 +297,12 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
elif Backend.getIdentifiedDbms() in FROM_DUMMY_TABLE and expression.upper().startswith("SELECT ") and " FROM " not in expression.upper():
expression += FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()]
outputs = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, resumeValue=resumeValue, charsetType=charsetType, firstChar=firstChar, lastChar=lastChar, dump=dump)
outputs = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, charsetType=charsetType, firstChar=firstChar, lastChar=lastChar, dump=dump)
returnValue = ", ".join(output for output in outputs)
return returnValue
def __goBooleanProxy(expression, resumeValue=True):
def __goBooleanProxy(expression):
"""
Retrieve the output of a boolean based SQL query
"""
@ -340,54 +316,37 @@ def __goBooleanProxy(expression, resumeValue=True):
payload = agent.payload(newValue=query)
timeBasedCompare = kb.technique in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED)
if resumeValue:
output = resume(expression, payload)
else:
output = None
output = conf.hashDB.retrieve(expression) if not any([conf.flushSession, conf.freshQueries, not kb.resumeValues]) else None
if not output:
output = Request.queryPage(payload, timeBasedCompare=timeBasedCompare, raise404=False)
if output is not None:
conf.hashDB.write(expression, output)
return output
def __goError(expression, expected=None, resumeValue=True, dump=False):
def __goError(expression, expected=None, dump=False):
"""
Retrieve the output of a SQL query taking advantage of an error-based
SQL injection vulnerability on the affected parameter.
"""
output = None
if resumeValue:
output = resume(expression, None)
if output and expected == EXPECTED.INT and not output.isdigit():
output = None
if output is None:
output = errorUse(expression, expected, resumeValue, dump)
output = errorUse(expression, expected, dump)
return output
def __goInband(expression, expected=None, unique=True, resumeValue=True, unpack=True, dump=False):
def __goInband(expression, expected=None, unique=True, unpack=True, dump=False):
"""
Retrieve the output of a SQL query taking advantage of an inband SQL
injection vulnerability on the affected parameter.
"""
output = None
partial = False
data = None
output = unionUse(expression, unpack=unpack, dump=dump)
if isinstance(output, basestring):
output = parseUnionPage(output, unique)
if output is None:
output = unionUse(expression, unpack=unpack, dump=dump)
if isinstance(output, list):
data = output
else:
data = parseUnionPage(output, unique)
return data
return output
def getValue(expression, blind=True, inband=True, error=True, time=True, fromUser=False, expected=None, batch=False, unpack=True, unique=True, resumeValue=True, charsetType=None, firstChar=None, lastChar=None, dump=False, suppressOutput=None, expectingNone=False, safeCharEncode=True):
"""
@ -398,6 +357,7 @@ def getValue(expression, blind=True, inband=True, error=True, time=True, fromUse
"""
kb.safeCharEncode = safeCharEncode
kb.resumeValues = resumeValue
if suppressOutput is not None:
pushValue(getCurrentThreadData().disableStdOut)
@ -433,9 +393,9 @@ def getValue(expression, blind=True, inband=True, error=True, time=True, fromUse
kb.technique = PAYLOAD.TECHNIQUE.UNION
if expected == EXPECTED.BOOL:
value = __goInband(forgeCaseExpression, expected, unique, resumeValue, unpack, dump)
value = __goInband(forgeCaseExpression, expected, unique, unpack, dump)
else:
value = __goInband(query, expected, unique, resumeValue, unpack, dump)
value = __goInband(query, expected, unique, unpack, dump)
count += 1
found = (value is not None) or (value is None and expectingNone) or count >= MAX_TECHNIQUES_PER_VALUE
@ -444,9 +404,9 @@ def getValue(expression, blind=True, inband=True, error=True, time=True, fromUse
kb.technique = PAYLOAD.TECHNIQUE.ERROR
if expected == EXPECTED.BOOL:
value = __goError(forgeCaseExpression, expected, resumeValue, dump)
value = __goError(forgeCaseExpression, expected, dump)
else:
value = __goError(query, expected, resumeValue, dump)
value = __goError(query, expected, dump)
count += 1
found = (value is not None) or (value is None and expectingNone) or count >= MAX_TECHNIQUES_PER_VALUE
@ -455,9 +415,9 @@ def getValue(expression, blind=True, inband=True, error=True, time=True, fromUse
kb.technique = PAYLOAD.TECHNIQUE.BOOLEAN
if expected == EXPECTED.BOOL:
value = __goBooleanProxy(booleanExpression, resumeValue)
value = __goBooleanProxy(booleanExpression)
else:
value = __goInferenceProxy(query, fromUser, expected, batch, resumeValue, unpack, charsetType, firstChar, lastChar, dump)
value = __goInferenceProxy(query, fromUser, expected, batch, unpack, charsetType, firstChar, lastChar, dump)
count += 1
found = (value is not None) or (value is None and expectingNone) or count >= MAX_TECHNIQUES_PER_VALUE
@ -469,9 +429,9 @@ def getValue(expression, blind=True, inband=True, error=True, time=True, fromUse
kb.technique = PAYLOAD.TECHNIQUE.STACKED
if expected == EXPECTED.BOOL:
value = __goBooleanProxy(booleanExpression, resumeValue)
value = __goBooleanProxy(booleanExpression)
else:
value = __goInferenceProxy(query, fromUser, expected, batch, resumeValue, unpack, charsetType, firstChar, lastChar, dump)
value = __goInferenceProxy(query, fromUser, expected, batch, unpack, charsetType, firstChar, lastChar, dump)
if value and isinstance(value, basestring):
value = value.strip()
@ -481,28 +441,13 @@ def getValue(expression, blind=True, inband=True, error=True, time=True, fromUse
raise sqlmapNotVulnerableException, errMsg
finally:
kb.resumeValues = True
if suppressOutput is not None:
getCurrentThreadData().disableStdOut = popValue()
if value and expected == EXPECTED.BOOL:
if isinstance(value, basestring):
value = value.strip().lower()
if value in ("true", "false"):
value = value == "true"
elif value in ("1", "-1"):
value = True
elif value == "0":
value = False
else:
value = None
elif isinstance(value, int):
value = bool(value)
elif value == [None]:
value = None
kb.safeCharEncode = False
return value
return extractExpectedValue(value, expected)
def goStacked(expression, silent=False):
kb.technique = PAYLOAD.TECHNIQUE.STACKED

View File

@ -13,7 +13,6 @@ import traceback
from lib.core.agent import agent
from lib.core.common import Backend
from lib.core.common import dataToSessionFile
from lib.core.common import dataToStdout
from lib.core.common import decodeIntToUnicode
from lib.core.common import filterControlChars
@ -46,6 +45,7 @@ from lib.core.settings import INFERENCE_GREATER_CHAR
from lib.core.settings import INFERENCE_EQUALS_CHAR
from lib.core.settings import INFERENCE_NOT_EQUALS_CHAR
from lib.core.settings import MAX_TIME_REVALIDATION_STEPS
from lib.core.settings import PARTIAL_VALUE_MARKER
from lib.core.settings import PYVERSION
from lib.core.threads import getCurrentThreadData
from lib.core.threads import runThreads
@ -58,466 +58,459 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
on an affected host
"""
retVal = conf.hashDB.retrieve(expression) if not any([conf.flushSession, conf.freshQueries]) else None
if retVal:
return 0, retVal
partialValue = ""
finalValue = ""
partialValue = u""
finalValue = None
abortedFlag = False
asciiTbl = getCharset(charsetType)
timeBasedCompare = (kb.technique in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED))
retVal = conf.hashDB.retrieve(expression) if not any([conf.flushSession, conf.freshQueries, not kb.resumeValues]) else None
# Set kb.partRun in case "common prediction" feature (a.k.a. "good
# samaritan") is used
kb.partRun = getPartRun() if conf.predictOutput else None
if "LENGTH(" in expression or "LEN(" in expression:
firstChar = 0
elif dump and conf.firstChar is not None and ( isinstance(conf.firstChar, int) or ( isinstance(conf.firstChar, basestring) and conf.firstChar.isdigit() ) ):
firstChar = int(conf.firstChar) - 1
elif firstChar is None:
firstChar = 0
elif ( isinstance(firstChar, basestring) and firstChar.isdigit() ) or isinstance(firstChar, int):
firstChar = int(firstChar) - 1
if "LENGTH(" in expression or "LEN(" in expression:
lastChar = 0
elif dump and conf.lastChar is not None and ( isinstance(conf.lastChar, int) or ( isinstance(conf.lastChar, basestring) and conf.lastChar.isdigit() ) ):
lastChar = int(conf.lastChar)
elif lastChar in ( None, "0" ):
lastChar = 0
elif ( isinstance(lastChar, basestring) and lastChar.isdigit() ) or isinstance(lastChar, int):
lastChar = int(lastChar)
if Backend.getDbms():
_, _, _, _, _, _, fieldToCastStr, _ = agent.getFields(expression)
nulledCastedField = agent.nullAndCastField(fieldToCastStr)
expressionReplaced = expression.replace(fieldToCastStr, nulledCastedField, 1)
expressionUnescaped = unescaper.unescape(expressionReplaced)
else:
expressionUnescaped = unescaper.unescape(expression)
if length and not isinstance(length, int) and length.isdigit():
length = int(length)
if length == 0:
return 0, ""
if lastChar > 0 and length > ( lastChar - firstChar ):
length = ( lastChar - firstChar )
showEta = conf.eta and isinstance(length, int)
numThreads = min(conf.threads, length)
if showEta:
progress = ProgressBar(maxValue=length)
progressTime = []
if timeBasedCompare and conf.threads > 1:
warnMsg = "multi-threading is considered unsafe in time-based data retrieval. Going to switch it off automatically"
singleTimeWarnMessage(warnMsg)
if numThreads > 1:
if not timeBasedCompare:
debugMsg = "starting %d thread%s" % (numThreads, ("s" if numThreads > 1 else ""))
logger.debug(debugMsg)
if retVal:
if PARTIAL_VALUE_MARKER in retVal:
partialValue = retVal.replace(PARTIAL_VALUE_MARKER, "")
dataToStdout("[%s] [INFO] resuming partial value: '%s'\r\n" % (time.strftime("%X"), safecharencode(partialValue)))
else:
numThreads = 1
dataToStdout("[%s] [INFO] resumed: %s\r\n" % (time.strftime("%X"), safecharencode(retVal)))
return 0, retVal
if conf.threads == 1 and not timeBasedCompare:
warnMsg = "running in a single-thread mode. Please consider "
warnMsg += "usage of option '--threads' for faster data retrieval"
singleTimeWarnMessage(warnMsg)
try:
# Set kb.partRun in case "common prediction" feature (a.k.a. "good
# samaritan") is used
kb.partRun = getPartRun() if conf.predictOutput else None
if conf.verbose in (1, 2) and not showEta:
if isinstance(length, int) and conf.threads > 1:
dataToStdout("[%s] [INFO] retrieved: %s" % (time.strftime("%X"), "_" * min(length, conf.progressWidth)))
dataToStdout("\r[%s] [INFO] retrieved: " % time.strftime("%X"))
if partialValue:
firstChar = len(partialValue)
elif "LENGTH(" in expression or "LEN(" in expression:
firstChar = 0
elif dump and conf.firstChar is not None and ( isinstance(conf.firstChar, int) or ( isinstance(conf.firstChar, basestring) and conf.firstChar.isdigit() ) ):
firstChar = int(conf.firstChar) - 1
elif firstChar is None:
firstChar = 0
elif ( isinstance(firstChar, basestring) and firstChar.isdigit() ) or isinstance(firstChar, int):
firstChar = int(firstChar) - 1
if "LENGTH(" in expression or "LEN(" in expression:
lastChar = 0
elif dump and conf.lastChar is not None and ( isinstance(conf.lastChar, int) or ( isinstance(conf.lastChar, basestring) and conf.lastChar.isdigit() ) ):
lastChar = int(conf.lastChar)
elif lastChar in ( None, "0" ):
lastChar = 0
elif ( isinstance(lastChar, basestring) and lastChar.isdigit() ) or isinstance(lastChar, int):
lastChar = int(lastChar)
if Backend.getDbms():
_, _, _, _, _, _, fieldToCastStr, _ = agent.getFields(expression)
nulledCastedField = agent.nullAndCastField(fieldToCastStr)
expressionReplaced = expression.replace(fieldToCastStr, nulledCastedField, 1)
expressionUnescaped = unescaper.unescape(expressionReplaced)
else:
dataToStdout("[%s] [INFO] retrieved: " % time.strftime("%X"))
expressionUnescaped = unescaper.unescape(expression)
hintlock = threading.Lock()
if length and not isinstance(length, int) and length.isdigit():
length = int(length)
def tryHint(idx):
hintlock.acquire()
hintValue = kb.hintValue
hintlock.release()
if length == 0:
return 0, ""
if hintValue is not None and len(hintValue) >= idx:
if Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.MAXDB, DBMS.DB2):
posValue = hintValue[idx-1]
if lastChar > 0 and length > ( lastChar - firstChar ):
length = ( lastChar - firstChar )
showEta = conf.eta and isinstance(length, int)
numThreads = min(conf.threads, length)
if showEta:
progress = ProgressBar(maxValue=length)
progressTime = []
if timeBasedCompare and conf.threads > 1:
warnMsg = "multi-threading is considered unsafe in time-based data retrieval. Going to switch it off automatically"
singleTimeWarnMessage(warnMsg)
if numThreads > 1:
if not timeBasedCompare:
debugMsg = "starting %d thread%s" % (numThreads, ("s" if numThreads > 1 else ""))
logger.debug(debugMsg)
else:
posValue = ord(hintValue[idx-1])
numThreads = 1
forgedPayload = safeStringFormat(payload.replace(INFERENCE_GREATER_CHAR, INFERENCE_EQUALS_CHAR), (expressionUnescaped, idx, posValue))
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
incrementCounter(kb.technique)
if conf.threads == 1 and not timeBasedCompare:
warnMsg = "running in a single-thread mode. Please consider "
warnMsg += "usage of option '--threads' for faster data retrieval"
singleTimeWarnMessage(warnMsg)
if result:
return hintValue[idx-1]
hintlock.acquire()
kb.hintValue = None
hintlock.release()
return None
def validateChar(idx, value):
"""
Used in time-based inference (in case that original and retrieved
value are not equal there will be a deliberate delay).
"""
forgedPayload = safeStringFormat(payload.replace(INFERENCE_GREATER_CHAR, INFERENCE_NOT_EQUALS_CHAR), (expressionUnescaped, idx, value))
incrementCounter(kb.technique)
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
return not result
def getChar(idx, charTbl=asciiTbl, continuousOrder=True, expand=charsetType is None, shiftTable=None):
"""
continuousOrder means that distance between each two neighbour's
numerical values is exactly 1
"""
result = tryHint(idx)
if result:
return result
originalTbl = list(charTbl)
if continuousOrder and shiftTable is None:
# Used for gradual expanding into unicode charspace
shiftTable = [5, 4]
if CHAR_INFERENCE_MARK in payload and ord('\n') in charTbl:
charTbl.remove(ord('\n'))
if len(charTbl) == 1:
forgedPayload = safeStringFormat(payload.replace(INFERENCE_GREATER_CHAR, INFERENCE_EQUALS_CHAR), (expressionUnescaped, idx, charTbl[0]))
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
incrementCounter(kb.technique)
if result:
return decodeIntToUnicode(charTbl[0])
if conf.verbose in (1, 2) and not showEta:
if isinstance(length, int) and conf.threads > 1:
dataToStdout("[%s] [INFO] retrieved: %s" % (time.strftime("%X"), "_" * min(length, conf.progressWidth)))
dataToStdout("\r[%s] [INFO] retrieved: " % time.strftime("%X"))
else:
return None
dataToStdout("[%s] [INFO] retrieved: " % time.strftime("%X"))
maxChar = maxValue = charTbl[-1]
minChar = minValue = charTbl[0]
hintlock = threading.Lock()
while len(charTbl) != 1:
position = (len(charTbl) >> 1)
posValue = charTbl[position]
def tryHint(idx):
hintlock.acquire()
hintValue = kb.hintValue
hintlock.release()
if CHAR_INFERENCE_MARK not in payload:
forgedPayload = safeStringFormat(payload, (expressionUnescaped, idx, posValue))
else:
# e.g.: ... > '%c' -> ... > ORD(..)
markingValue = "'%s'" % CHAR_INFERENCE_MARK
unescapedCharValue = unescaper.unescape("'%s'" % decodeIntToUnicode(posValue))
forgedPayload = safeStringFormat(payload, (expressionUnescaped, idx)).replace(markingValue, unescapedCharValue)
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
incrementCounter(kb.technique)
if result:
minValue = posValue
if type(charTbl) != xrange:
charTbl = charTbl[position:]
if hintValue is not None and len(hintValue) >= idx:
if Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.MAXDB, DBMS.DB2):
posValue = hintValue[idx-1]
else:
# xrange() - extended virtual charset used for memory/space optimization
charTbl = xrange(charTbl[position], charTbl[-1] + 1)
else:
maxValue = posValue
posValue = ord(hintValue[idx-1])
if type(charTbl) != xrange:
charTbl = charTbl[:position]
else:
charTbl = xrange(charTbl[0], charTbl[position])
forgedPayload = safeStringFormat(payload.replace(INFERENCE_GREATER_CHAR, INFERENCE_EQUALS_CHAR), (expressionUnescaped, idx, posValue))
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
incrementCounter(kb.technique)
if result:
return hintValue[idx-1]
hintlock.acquire()
kb.hintValue = None
hintlock.release()
return None
def validateChar(idx, value):
"""
Used in time-based inference (in case that original and retrieved
value are not equal there will be a deliberate delay).
"""
forgedPayload = safeStringFormat(payload.replace(INFERENCE_GREATER_CHAR, INFERENCE_NOT_EQUALS_CHAR), (expressionUnescaped, idx, value))
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
incrementCounter(kb.technique)
return not result
def getChar(idx, charTbl=asciiTbl, continuousOrder=True, expand=charsetType is None, shiftTable=None):
"""
continuousOrder means that distance between each two neighbour's
numerical values is exactly 1
"""
result = tryHint(idx)
if result:
return result
originalTbl = list(charTbl)
if continuousOrder and shiftTable is None:
# Used for gradual expanding into unicode charspace
shiftTable = [5, 4]
if CHAR_INFERENCE_MARK in payload and ord('\n') in charTbl:
charTbl.remove(ord('\n'))
if len(charTbl) == 1:
if continuousOrder:
if maxValue == 1:
return None
forgedPayload = safeStringFormat(payload.replace(INFERENCE_GREATER_CHAR, INFERENCE_EQUALS_CHAR), (expressionUnescaped, idx, charTbl[0]))
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
incrementCounter(kb.technique)
# Going beyond the original charset
elif minValue == maxChar:
# If the original charTbl was [0,..,127] new one
# will be [128,..,128*16-1] or from 128 to 2047
# and instead of making a HUGE list with all the
# elements we use a xrange, which is a virtual
# list
if expand and shiftTable:
charTbl = xrange(maxChar + 1, (maxChar + 1) << shiftTable.pop())
originalTbl = list(charTbl)
maxChar = maxValue = charTbl[-1]
minChar = minValue = charTbl[0]
else:
return None
else:
retVal = minValue + 1
if retVal in originalTbl or (retVal == ord('\n') and CHAR_INFERENCE_MARK in payload):
if timeBasedCompare and not validateChar(idx, retVal):
if not kb.originalTimeDelay:
kb.originalTimeDelay = conf.timeSec
if (conf.timeSec - kb.originalTimeDelay) < MAX_TIME_REVALIDATION_STEPS:
errMsg = "invalid character detected. retrying.."
logger.error(errMsg)
warnMsg = "increasing time delay to %d second%s " % (conf.timeSec, 's' if conf.timeSec > 1 else '')
logger.warn(warnMsg)
conf.timeSec += 1
if kb.adjustTimeDelay:
dbgMsg = "turning off auto-adjustment mechanism"
logger.debug(dbgMsg)
kb.adjustTimeDelay = False
return getChar(idx, originalTbl, continuousOrder, expand, shiftTable)
else:
errMsg = "unable to properly validate last character value ('%s').." % decodeIntToUnicode(retVal)
logger.error(errMsg)
conf.timeSec = kb.originalTimeDelay
return decodeIntToUnicode(retVal)
else:
return decodeIntToUnicode(retVal)
else:
return None
if result:
return decodeIntToUnicode(charTbl[0])
else:
if minValue == maxChar or maxValue == minChar:
return None
# If we are working with non-continuous elements, set
# both minValue and character afterwards are possible
# candidates
for retVal in (originalTbl[originalTbl.index(minValue)], originalTbl[originalTbl.index(minValue) + 1]):
forgedPayload = safeStringFormat(payload.replace(INFERENCE_GREATER_CHAR, INFERENCE_EQUALS_CHAR), (expressionUnescaped, idx, retVal))
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
incrementCounter(kb.technique)
if result:
return decodeIntToUnicode(retVal)
return None
def etaProgressUpdate(charTime, index):
if len(progressTime) <= ( (length * 3) / 100 ):
eta = 0
else:
midTime = sum(progressTime) / len(progressTime)
midTimeWithLatest = (midTime + charTime) / 2
eta = midTimeWithLatest * (length - index) / conf.threads
maxChar = maxValue = charTbl[-1]
minChar = minValue = charTbl[0]
progressTime.append(charTime)
progress.update(index)
progress.draw(eta)
while len(charTbl) != 1:
position = (len(charTbl) >> 1)
posValue = charTbl[position]
# Go multi-threading (--threads > 1)
if conf.threads > 1 and isinstance(length, int) and length > 1:
value = []
threadData = getCurrentThreadData()
if CHAR_INFERENCE_MARK not in payload:
forgedPayload = safeStringFormat(payload, (expressionUnescaped, idx, posValue))
else:
# e.g.: ... > '%c' -> ... > ORD(..)
markingValue = "'%s'" % CHAR_INFERENCE_MARK
unescapedCharValue = unescaper.unescape("'%s'" % decodeIntToUnicode(posValue))
forgedPayload = safeStringFormat(payload, (expressionUnescaped, idx)).replace(markingValue, unescapedCharValue)
threadData.shared.value = [ None ] * length
threadData.shared.index = [ firstChar ] # As list for python nested function scoping
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
incrementCounter(kb.technique)
try:
def blindThread():
threadData = getCurrentThreadData()
if result:
minValue = posValue
while kb.threadContinue:
kb.locks.index.acquire()
if type(charTbl) != xrange:
charTbl = charTbl[position:]
else:
# xrange() - extended virtual charset used for memory/space optimization
charTbl = xrange(charTbl[position], charTbl[-1] + 1)
else:
maxValue = posValue
if threadData.shared.index[0] >= length:
if type(charTbl) != xrange:
charTbl = charTbl[:position]
else:
charTbl = xrange(charTbl[0], charTbl[position])
if len(charTbl) == 1:
if continuousOrder:
if maxValue == 1:
return None
# Going beyond the original charset
elif minValue == maxChar:
# If the original charTbl was [0,..,127] new one
# will be [128,..,128*16-1] or from 128 to 2047
# and instead of making a HUGE list with all the
# elements we use a xrange, which is a virtual
# list
if expand and shiftTable:
charTbl = xrange(maxChar + 1, (maxChar + 1) << shiftTable.pop())
originalTbl = list(charTbl)
maxChar = maxValue = charTbl[-1]
minChar = minValue = charTbl[0]
else:
return None
else:
retVal = minValue + 1
if retVal in originalTbl or (retVal == ord('\n') and CHAR_INFERENCE_MARK in payload):
if timeBasedCompare and not validateChar(idx, retVal):
if not kb.originalTimeDelay:
kb.originalTimeDelay = conf.timeSec
if (conf.timeSec - kb.originalTimeDelay) < MAX_TIME_REVALIDATION_STEPS:
errMsg = "invalid character detected. retrying.."
logger.error(errMsg)
warnMsg = "increasing time delay to %d second%s " % (conf.timeSec, 's' if conf.timeSec > 1 else '')
logger.warn(warnMsg)
conf.timeSec += 1
if kb.adjustTimeDelay:
dbgMsg = "turning off auto-adjustment mechanism"
logger.debug(dbgMsg)
kb.adjustTimeDelay = False
return getChar(idx, originalTbl, continuousOrder, expand, shiftTable)
else:
errMsg = "unable to properly validate last character value ('%s').." % decodeIntToUnicode(retVal)
logger.error(errMsg)
conf.timeSec = kb.originalTimeDelay
return decodeIntToUnicode(retVal)
else:
return decodeIntToUnicode(retVal)
else:
return None
else:
if minValue == maxChar or maxValue == minChar:
return None
# If we are working with non-continuous elements, set
# both minValue and character afterwards are possible
# candidates
for retVal in (originalTbl[originalTbl.index(minValue)], originalTbl[originalTbl.index(minValue) + 1]):
forgedPayload = safeStringFormat(payload.replace(INFERENCE_GREATER_CHAR, INFERENCE_EQUALS_CHAR), (expressionUnescaped, idx, retVal))
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
incrementCounter(kb.technique)
if result:
return decodeIntToUnicode(retVal)
return None
def etaProgressUpdate(charTime, index):
if len(progressTime) <= ( (length * 3) / 100 ):
eta = 0
else:
midTime = sum(progressTime) / len(progressTime)
midTimeWithLatest = (midTime + charTime) / 2
eta = midTimeWithLatest * (length - index) / conf.threads
progressTime.append(charTime)
progress.update(index)
progress.draw(eta)
# Go multi-threading (--threads > 1)
if conf.threads > 1 and isinstance(length, int) and length > 1:
value = []
threadData = getCurrentThreadData()
threadData.shared.value = [ None ] * length
threadData.shared.index = [ firstChar ] # As list for python nested function scoping
threadData.shared.start = firstChar
try:
def blindThread():
threadData = getCurrentThreadData()
while kb.threadContinue:
kb.locks.index.acquire()
if threadData.shared.index[0] >= length:
kb.locks.index.release()
return
threadData.shared.index[0] += 1
curidx = threadData.shared.index[0]
kb.locks.index.release()
return
if kb.threadContinue:
charStart = time.time()
val = getChar(curidx)
if val is None:
val = INFERENCE_UNKNOWN_CHAR
else:
break
threadData.shared.index[0] += 1
curidx = threadData.shared.index[0]
kb.locks.index.release()
kb.locks.value.acquire()
threadData.shared.value[curidx - 1] = val
currentValue = list(threadData.shared.value)
kb.locks.value.release()
if kb.threadContinue:
charStart = time.time()
val = getChar(curidx)
if val is None:
val = INFERENCE_UNKNOWN_CHAR
else:
break
if kb.threadContinue:
if showEta:
etaProgressUpdate(time.time() - charStart, threadData.shared.index[0])
elif conf.verbose >= 1:
startCharIndex = 0
endCharIndex = 0
kb.locks.value.acquire()
threadData.shared.value[curidx-1] = val
currentValue = list(threadData.shared.value)
kb.locks.value.release()
for i in xrange(length):
if currentValue[i] is not None:
endCharIndex = max(endCharIndex, i)
if kb.threadContinue:
if showEta:
etaProgressUpdate(time.time() - charStart, threadData.shared.index[0])
elif conf.verbose >= 1:
startCharIndex = 0
endCharIndex = 0
output = ''
for i in xrange(length):
if currentValue[i] is not None:
endCharIndex = max(endCharIndex, i)
if endCharIndex > conf.progressWidth:
startCharIndex = endCharIndex - conf.progressWidth
output = ''
count = threadData.shared.start
if endCharIndex > conf.progressWidth:
startCharIndex = endCharIndex - conf.progressWidth
for i in xrange(startCharIndex, endCharIndex + 1):
output += '_' if currentValue[i] is None else currentValue[i]
count = 0
for i in xrange(length):
count += 1 if currentValue[i] is not None else 0
for i in xrange(startCharIndex, endCharIndex + 1):
output += '_' if currentValue[i] is None else currentValue[i]
if startCharIndex > 0:
output = '..' + output[2:]
for i in xrange(length):
count += 1 if currentValue[i] is not None else 0
if (endCharIndex - startCharIndex == conf.progressWidth) and (endCharIndex < length-1):
output = output[:-2] + '..'
if startCharIndex > 0:
output = '..' + output[2:]
if conf.verbose in (1, 2) and not showEta:
output += '_' * (min(length, conf.progressWidth) - len(output))
status = ' %d/%d (%d%s)' % (count, length, round(100.0*count/length), '%')
output += status if count != length else " "*len(status)
if (endCharIndex - startCharIndex == conf.progressWidth) and (endCharIndex < length-1):
output = output[:-2] + '..'
dataToStdout("\r[%s] [INFO] retrieved: %s" % (time.strftime("%X"), filterControlChars(output)))
if conf.verbose in (1, 2) and not showEta:
output += '_' * (min(length, conf.progressWidth) - len(output))
status = ' %d/%d (%d%s)' % (count, length, round(100.0*count/length), '%')
output += status if count != length else " "*len(status)
runThreads(numThreads, blindThread, startThreadMsg=False)
dataToStdout("\r[%s] [INFO] retrieved: %s" % (time.strftime("%X"), filterControlChars(output)))
except KeyboardInterrupt:
abortedFlag = True
if not kb.threadContinue:
if int(threading.currentThread().getName()) == numThreads - 1:
partialValue = unicode()
for v in threadData.shared.value:
if v is None:
break
elif isinstance(v, basestring):
partialValue += v
finally:
value = map(lambda _: partialValue[_] if _ < len(partialValue) else threadData.shared.value[_], xrange(length))
if len(partialValue) > 0:
dataToSessionFile(replaceNewlineTabs(partialValue))
infoMsg = None
runThreads(numThreads, blindThread, startThreadMsg=False)
# If we have got one single character not correctly fetched it
# can mean that the connection to the target url was lost
if None in value:
partialValue = "".join(_ for _ in value[:value.index(None)])
except KeyboardInterrupt:
raise
finally:
value = threadData.shared.value
infoMsg = None
# If we have got one single character not correctly fetched it
# can mean that the connection to the target url was lost
if None in value:
for v in value:
if isinstance(v, basestring) and v is not None:
partialValue += v
if partialValue:
finalValue = partialValue
infoMsg = "\r[%s] [INFO] partially retrieved: %s" % (time.strftime("%X"), filterControlChars(finalValue))
else:
finalValue = "".join(value)
infoMsg = "\r[%s] [INFO] retrieved: %s" % (time.strftime("%X"), filterControlChars(finalValue))
if isinstance(finalValue, basestring) and len(finalValue) > 0:
dataToSessionFile(replaceNewlineTabs(finalValue))
if conf.verbose in (1, 2) and not showEta and infoMsg:
dataToStdout(infoMsg)
# No multi-threading (--threads = 1)
else:
index = firstChar
while True:
index += 1
charStart = time.time()
# Common prediction feature (a.k.a. "good samaritan")
# NOTE: to be used only when multi-threading is not set for
# the moment
if conf.predictOutput and len(finalValue) > 0 and kb.partRun is not None:
val = None
commonValue, commonPattern, commonCharset, otherCharset = goGoodSamaritan(finalValue, asciiTbl)
# If there is one single output in common-outputs, check
# it via equal against the query output
if commonValue is not None:
# One-shot query containing equals commonValue
testValue = unescaper.unescape("'%s'" % commonValue) if "'" not in commonValue else unescaper.unescape("%s" % commonValue, quote=False)
query = agent.prefixQuery(safeStringFormat("AND (%s) = %s", (expressionUnescaped, testValue)))
query = agent.suffixQuery(query)
result = Request.queryPage(agent.payload(newValue=query), timeBasedCompare=timeBasedCompare, raise404=False)
incrementCounter(kb.technique)
# Did we have luck?
if result:
dataToSessionFile(replaceNewlineTabs(commonValue[index-1:]))
if showEta:
etaProgressUpdate(time.time() - charStart, len(commonValue))
elif conf.verbose in (1, 2):
dataToStdout(commonValue[index-1:])
finalValue = commonValue
break
# If there is a common pattern starting with finalValue,
# check it via equal against the substring-query output
if commonPattern is not None:
# Substring-query containing equals commonPattern
subquery = queries[Backend.getIdentifiedDbms()].substring.query % (expressionUnescaped, 1, len(commonPattern))
testValue = unescaper.unescape("'%s'" % commonPattern) if "'" not in commonPattern else unescaper.unescape("%s" % commonPattern, quote=False)
query = agent.prefixQuery(safeStringFormat("AND (%s) = %s", (subquery, testValue)))
query = agent.suffixQuery(query)
result = Request.queryPage(agent.payload(newValue=query), timeBasedCompare=timeBasedCompare, raise404=False)
incrementCounter(kb.technique)
# Did we have luck?
if result:
val = commonPattern[index-1:]
index += len(val)-1
# Otherwise if there is no commonValue (single match from
# txt/common-outputs.txt) and no commonPattern
# (common pattern) use the returned common charset only
# to retrieve the query output
if not val and commonCharset:
val = getChar(index, commonCharset, False)
# If we had no luck with commonValue and common charset,
# use the returned other charset
if not val:
val = getChar(index, otherCharset, otherCharset == asciiTbl)
if partialValue:
infoMsg = "\r[%s] [INFO] partially retrieved: %s" % (time.strftime("%X"), filterControlChars(partialValue))
else:
val = getChar(index, asciiTbl)
finalValue = "".join(value)
infoMsg = "\r[%s] [INFO] retrieved: %s" % (time.strftime("%X"), filterControlChars(finalValue))
if val is None or ( lastChar > 0 and index > lastChar ):
break
if conf.verbose in (1, 2) and not showEta and infoMsg:
dataToStdout(infoMsg)
if kb.data.processChar:
val = kb.data.processChar(val)
# No multi-threading (--threads = 1)
else:
index = firstChar
finalValue += val
dataToSessionFile(replaceNewlineTabs(val))
while True:
index += 1
charStart = time.time()
if showEta:
etaProgressUpdate(time.time() - charStart, index)
elif conf.verbose in (1, 2):
dataToStdout(val)
# Common prediction feature (a.k.a. "good samaritan")
# NOTE: to be used only when multi-threading is not set for
# the moment
if conf.predictOutput and len(partialValue) > 0 and kb.partRun is not None:
val = None
commonValue, commonPattern, commonCharset, otherCharset = goGoodSamaritan(partialValue, asciiTbl)
if len(finalValue) > INFERENCE_BLANK_BREAK and finalValue[-INFERENCE_BLANK_BREAK:].isspace():
break
# If there is one single output in common-outputs, check
# it via equal against the query output
if commonValue is not None:
# One-shot query containing equals commonValue
testValue = unescaper.unescape("'%s'" % commonValue) if "'" not in commonValue else unescaper.unescape("%s" % commonValue, quote=False)
query = agent.prefixQuery(safeStringFormat("AND (%s) = %s", (expressionUnescaped, testValue)))
query = agent.suffixQuery(query)
result = Request.queryPage(agent.payload(newValue=query), timeBasedCompare=timeBasedCompare, raise404=False)
incrementCounter(kb.technique)
# Did we have luck?
if result:
if showEta:
etaProgressUpdate(time.time() - charStart, len(commonValue))
elif conf.verbose in (1, 2):
dataToStdout(commonValue[index-1:])
finalValue = commonValue
break
# If there is a common pattern starting with partialValue,
# check it via equal against the substring-query output
if commonPattern is not None:
# Substring-query containing equals commonPattern
subquery = queries[Backend.getIdentifiedDbms()].substring.query % (expressionUnescaped, 1, len(commonPattern))
testValue = unescaper.unescape("'%s'" % commonPattern) if "'" not in commonPattern else unescaper.unescape("%s" % commonPattern, quote=False)
query = agent.prefixQuery(safeStringFormat("AND (%s) = %s", (subquery, testValue)))
query = agent.suffixQuery(query)
result = Request.queryPage(agent.payload(newValue=query), timeBasedCompare=timeBasedCompare, raise404=False)
incrementCounter(kb.technique)
# Did we have luck?
if result:
val = commonPattern[index-1:]
index += len(val)-1
# Otherwise if there is no commonValue (single match from
# txt/common-outputs.txt) and no commonPattern
# (common pattern) use the returned common charset only
# to retrieve the query output
if not val and commonCharset:
val = getChar(index, commonCharset, False)
# If we had no luck with commonValue and common charset,
# use the returned other charset
if not val:
val = getChar(index, otherCharset, otherCharset == asciiTbl)
else:
val = getChar(index, asciiTbl)
if val is None or ( lastChar > 0 and index > lastChar ):
finalValue = partialValue
break
if kb.data.processChar:
val = kb.data.processChar(val)
partialValue += val
if showEta:
etaProgressUpdate(time.time() - charStart, index)
elif conf.verbose in (1, 2):
dataToStdout(val)
if len(partialValue) > INFERENCE_BLANK_BREAK and partialValue[-INFERENCE_BLANK_BREAK:].isspace():
finalValue = partialValue
break
except KeyboardInterrupt:
abortedFlag = True
if conf.verbose in (1, 2) or showEta:
dataToStdout("\n")
@ -526,11 +519,16 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
infoMsg = "retrieved: %s" % filterControlChars(finalValue)
logger.info(infoMsg)
if not partialValue:
if finalValue is not None:
conf.hashDB.write(expression, finalValue)
dataToSessionFile("]\n")
else:
conf.hashDB.write(expression, "%s%s" % (PARTIAL_VALUE_MARKER, partialValue))
if kb.threadException:
raise sqlmapThreadException, "something unexpected happened inside the threads"
return getCounter(kb.technique), safecharencode(finalValue) if kb.safeCharEncode else finalValue
if abortedFlag:
raise KeyboardInterrupt
_ = finalValue or partialValue
return getCounter(kb.technique), safecharencode(_) if kb.safeCharEncode else _

View File

@ -45,10 +45,9 @@ from lib.core.threads import getCurrentThreadData
from lib.core.threads import runThreads
from lib.core.unescaper import unescaper
from lib.request.connect import Connect as Request
from lib.utils.resume import resume
def __oneShotErrorUse(expression, field):
retVal = conf.hashDB.retrieve(expression) if not any([conf.flushSession, conf.freshQueries]) else None
retVal = conf.hashDB.retrieve(expression) if not any([conf.flushSession, conf.freshQueries, not kb.resumeValues]) else None
threadData = getCurrentThreadData()
threadData.resumed = retVal is not None
@ -137,7 +136,7 @@ def __oneShotErrorUse(expression, field):
return safecharencode(retVal) if kb.safeCharEncode else retVal
def __errorFields(expression, expressionFields, expressionFieldsList, expected=None, num=None, resumeValue=True):
def __errorFields(expression, expressionFields, expressionFieldsList, expected=None, num=None):
outputs = []
origExpr = None
@ -158,22 +157,13 @@ def __errorFields(expression, expressionFields, expressionFieldsList, expected=N
else:
expressionReplaced = expression.replace(expressionFields, field, 1)
if resumeValue:
output = resume(expressionReplaced, None)
output = __oneShotErrorUse(expressionReplaced, field)
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)
if not kb.threadContinue:
return None
output = __oneShotErrorUse(expressionReplaced, field)
if not kb.threadContinue:
return None
if output is not None:
dataToStdout("[%s] [INFO] %s: %s\r\n" % (time.strftime("%X"), "resumed" if threadData.resumed else "retrieved", safecharencode(output)))
if output is not None:
dataToStdout("[%s] [INFO] %s: %s\r\n" % (time.strftime("%X"), "resumed" if threadData.resumed else "retrieved", safecharencode(output)))
if isinstance(num, int):
expression = origExpr
@ -194,7 +184,7 @@ def __errorReplaceChars(value):
return retVal
def errorUse(expression, expected=None, resumeValue=True, dump=False):
def errorUse(expression, expected=None, dump=False):
"""
Retrieve the output of a SQL query taking advantage of the error-based
SQL injection vulnerability on the affected parameter.
@ -207,18 +197,11 @@ def errorUse(expression, expected=None, resumeValue=True, dump=False):
start = time.time()
startLimit = 0
stopLimit = None
output = None
outputs = []
untilLimitChar = None
untilOrderChar = None
if resumeValue:
output = resume(expression, None)
else:
output = None
if output and (expected is None or (expected == EXPECTED.INT and output.isdigit())):
return output
_, _, _, _, _, expressionFieldsList, expressionFields, _ = agent.getFields(expression)
# We have to check if the SQL query might return multiple entries
@ -295,11 +278,8 @@ def errorUse(expression, expected=None, resumeValue=True, dump=False):
if " ORDER BY " in expression:
countedExpression = countedExpression[:countedExpression.index(" ORDER BY ")]
count = resume(countedExpression, None)
if not count or not count.isdigit():
_, _, _, _, _, _, countedExpressionFields, _ = agent.getFields(countedExpression)
count = __oneShotErrorUse(countedExpression, countedExpressionFields)
_, _, _, _, _, _, countedExpressionFields, _ = agent.getFields(countedExpression)
count = __oneShotErrorUse(countedExpression, countedExpressionFields)
if isNumPosStrValue(count):
if isinstance(stopLimit, int) and stopLimit > 0:
@ -360,7 +340,7 @@ def errorUse(expression, expected=None, resumeValue=True, dump=False):
finally:
kb.locks.limits.release()
output = __errorFields(expression, expressionFields, expressionFieldsList, expected, num, resumeValue)
output = __errorFields(expression, expressionFields, expressionFieldsList, expected, num)
if not kb.threadContinue:
break

View File

@ -43,10 +43,9 @@ from lib.core.threads import getCurrentThreadData
from lib.core.threads import runThreads
from lib.core.unescaper import unescaper
from lib.request.connect import Connect as Request
from lib.utils.resume import resume
def __oneShotUnionUse(expression, unpack=True, limited=False):
retVal = conf.hashDB.retrieve(expression) if not any([conf.flushSession, conf.freshQueries]) else None
retVal = conf.hashDB.retrieve(expression) if not any([conf.flushSession, conf.freshQueries, not kb.resumeValues]) else None
threadData = getCurrentThreadData()
threadData.resumed = retVal is not None
@ -233,14 +232,8 @@ def unionUse(expression, unpack=True, dump=False):
_ = countedExpression.upper().rindex(" ORDER BY ")
countedExpression = countedExpression[:_]
count = resume(countedExpression, None)
count = parseUnionPage(count)
if not count or not count.isdigit():
output = __oneShotUnionUse(countedExpression, unpack)
if output:
count = parseUnionPage(output)
output = __oneShotUnionUse(countedExpression, unpack)
count = parseUnionPage(output)
if isNumPosStrValue(count):
if isinstance(stopLimit, int) and stopLimit > 0:
@ -301,10 +294,7 @@ def unionUse(expression, unpack=True, dump=False):
field = None
limitedExpr = agent.limitQuery(num, expression, field)
output = resume(limitedExpr, None)
if not output:
output = __oneShotUnionUse(limitedExpr, unpack, True)
output = __oneShotUnionUse(limitedExpr, unpack, True)
if not kb.threadContinue:
break

View File

@ -69,13 +69,6 @@ def queryOutputLength(expression, payload):
infoMsg = "retrieving the length of query output"
logger.info(infoMsg)
output = resume(lengthExpr, payload)
if output:
return 0, output, regExpr
dataToSessionFile("[%s][%s][%s][%s][" % (conf.url, kb.injection.place, conf.parameters[kb.injection.place], lengthExpr))
start = time.time()
lengthExprUnescaped = unescaper.unescape(lengthExpr)
count, length = bisection(payload, lengthExprUnescaped, charsetType=2)