mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-06-06 06:03:22 +03:00
Patching silent per-thread issue with technique switching (fixes #3784)
This commit is contained in:
parent
32e09c8dfb
commit
3abd3e1a8d
|
@ -12,6 +12,7 @@ from lib.core.common import Backend
|
||||||
from lib.core.common import extractRegexResult
|
from lib.core.common import extractRegexResult
|
||||||
from lib.core.common import filterNone
|
from lib.core.common import filterNone
|
||||||
from lib.core.common import getSQLSnippet
|
from lib.core.common import getSQLSnippet
|
||||||
|
from lib.core.common import getTechnique
|
||||||
from lib.core.common import isDBMSVersionAtLeast
|
from lib.core.common import isDBMSVersionAtLeast
|
||||||
from lib.core.common import isNumber
|
from lib.core.common import isNumber
|
||||||
from lib.core.common import isTechniqueAvailable
|
from lib.core.common import isTechniqueAvailable
|
||||||
|
@ -89,8 +90,8 @@ class Agent(object):
|
||||||
|
|
||||||
if kb.forceWhere:
|
if kb.forceWhere:
|
||||||
where = kb.forceWhere
|
where = kb.forceWhere
|
||||||
elif where is None and isTechniqueAvailable(kb.technique):
|
elif where is None and isTechniqueAvailable(getTechnique()):
|
||||||
where = kb.injection.data[kb.technique].where
|
where = kb.injection.data[getTechnique()].where
|
||||||
|
|
||||||
if kb.injection.place is not None:
|
if kb.injection.place is not None:
|
||||||
place = kb.injection.place
|
place = kb.injection.place
|
||||||
|
@ -234,8 +235,8 @@ class Agent(object):
|
||||||
expression = unescaper.escape(expression)
|
expression = unescaper.escape(expression)
|
||||||
query = None
|
query = None
|
||||||
|
|
||||||
if where is None and kb.technique and kb.technique in kb.injection.data:
|
if where is None and getTechnique() is not None and getTechnique() in kb.injection.data:
|
||||||
where = kb.injection.data[kb.technique].where
|
where = kb.injection.data[getTechnique()].where
|
||||||
|
|
||||||
# If we are replacing (<where>) the parameter original value with
|
# If we are replacing (<where>) the parameter original value with
|
||||||
# our payload do not prepend with the prefix
|
# our payload do not prepend with the prefix
|
||||||
|
@ -244,7 +245,7 @@ class Agent(object):
|
||||||
|
|
||||||
# If the technique is stacked queries (<stype>) do not put a space
|
# If the technique is stacked queries (<stype>) do not put a space
|
||||||
# after the prefix or it is in GROUP BY / ORDER BY (<clause>)
|
# after the prefix or it is in GROUP BY / ORDER BY (<clause>)
|
||||||
elif kb.technique == PAYLOAD.TECHNIQUE.STACKED:
|
elif getTechnique() == PAYLOAD.TECHNIQUE.STACKED:
|
||||||
query = kb.injection.prefix
|
query = kb.injection.prefix
|
||||||
elif kb.injection.clause == [2, 3] or kb.injection.clause == [2] or kb.injection.clause == [3]:
|
elif kb.injection.clause == [2, 3] or kb.injection.clause == [2] or kb.injection.clause == [3]:
|
||||||
query = kb.injection.prefix
|
query = kb.injection.prefix
|
||||||
|
@ -282,9 +283,9 @@ class Agent(object):
|
||||||
# Take default values if None
|
# Take default values if None
|
||||||
suffix = kb.injection.suffix if kb.injection and suffix is None else suffix
|
suffix = kb.injection.suffix if kb.injection and suffix is None else suffix
|
||||||
|
|
||||||
if kb.technique and kb.technique in kb.injection.data:
|
if getTechnique() is not None and getTechnique() in kb.injection.data:
|
||||||
where = kb.injection.data[kb.technique].where if where is None else where
|
where = kb.injection.data[getTechnique()].where if where is None else where
|
||||||
comment = kb.injection.data[kb.technique].comment if comment is None else comment
|
comment = kb.injection.data[getTechnique()].comment if comment is None else comment
|
||||||
|
|
||||||
if Backend.getIdentifiedDbms() == DBMS.ACCESS and any((comment or "").startswith(_) for _ in ("--", "[GENERIC_SQL_COMMENT]")):
|
if Backend.getIdentifiedDbms() == DBMS.ACCESS and any((comment or "").startswith(_) for _ in ("--", "[GENERIC_SQL_COMMENT]")):
|
||||||
comment = queries[DBMS.ACCESS].comment.query
|
comment = queries[DBMS.ACCESS].comment.query
|
||||||
|
|
|
@ -1125,6 +1125,20 @@ def readInput(message, default=None, checkBatch=True, boolean=False):
|
||||||
|
|
||||||
return retVal or ""
|
return retVal or ""
|
||||||
|
|
||||||
|
def setTechnique(technique):
|
||||||
|
"""
|
||||||
|
Thread-safe setting of currently used technique (Note: dealing with cases of per-thread technique switching)
|
||||||
|
"""
|
||||||
|
|
||||||
|
getCurrentThreadData().technique = technique
|
||||||
|
|
||||||
|
def getTechnique():
|
||||||
|
"""
|
||||||
|
Thread-safe getting of currently used technique
|
||||||
|
"""
|
||||||
|
|
||||||
|
return getCurrentThreadData().technique or kb.technique
|
||||||
|
|
||||||
def randomRange(start=0, stop=1000, seed=None):
|
def randomRange(start=0, stop=1000, seed=None):
|
||||||
"""
|
"""
|
||||||
Returns random integer value in given range
|
Returns random integer value in given range
|
||||||
|
@ -3231,18 +3245,16 @@ def isHeavyQueryBased(technique=None):
|
||||||
Returns True whether current (kb.)technique is heavy-query based
|
Returns True whether current (kb.)technique is heavy-query based
|
||||||
|
|
||||||
>>> pushValue(kb.injection.data)
|
>>> pushValue(kb.injection.data)
|
||||||
>>> pushValue(kb.technique)
|
>>> setTechnique(PAYLOAD.TECHNIQUE.STACKED)
|
||||||
>>> kb.technique = PAYLOAD.TECHNIQUE.STACKED
|
>>> kb.injection.data[getTechnique()] = [test for test in getSortedInjectionTests() if "heavy" in test["title"].lower()][0]
|
||||||
>>> kb.injection.data[kb.technique] = [test for test in getSortedInjectionTests() if "heavy" in test["title"].lower()][0]
|
|
||||||
>>> isHeavyQueryBased()
|
>>> isHeavyQueryBased()
|
||||||
True
|
True
|
||||||
>>> kb.technique = popValue()
|
|
||||||
>>> kb.injection.data = popValue()
|
>>> kb.injection.data = popValue()
|
||||||
"""
|
"""
|
||||||
|
|
||||||
retVal = False
|
retVal = False
|
||||||
|
|
||||||
technique = technique or kb.technique
|
technique = technique or getTechnique()
|
||||||
|
|
||||||
if isTechniqueAvailable(technique):
|
if isTechniqueAvailable(technique):
|
||||||
data = getTechniqueData(technique)
|
data = getTechniqueData(technique)
|
||||||
|
@ -3630,7 +3642,7 @@ def unhandledExceptionMessage():
|
||||||
errMsg += "Python version: %s\n" % PYVERSION
|
errMsg += "Python version: %s\n" % PYVERSION
|
||||||
errMsg += "Operating system: %s\n" % platform.platform()
|
errMsg += "Operating system: %s\n" % platform.platform()
|
||||||
errMsg += "Command line: %s\n" % re.sub(r".+?\bsqlmap\.py\b", "sqlmap.py", getUnicode(" ".join(sys.argv), encoding=sys.stdin.encoding))
|
errMsg += "Command line: %s\n" % re.sub(r".+?\bsqlmap\.py\b", "sqlmap.py", getUnicode(" ".join(sys.argv), encoding=sys.stdin.encoding))
|
||||||
errMsg += "Technique: %s\n" % (enumValueToNameLookup(PAYLOAD.TECHNIQUE, kb.technique) if kb.get("technique") else ("DIRECT" if conf.get("direct") else None))
|
errMsg += "Technique: %s\n" % (enumValueToNameLookup(PAYLOAD.TECHNIQUE, getTechnique()) if getTechnique() is not None else ("DIRECT" if conf.get("direct") else None))
|
||||||
errMsg += "Back-end DBMS:"
|
errMsg += "Back-end DBMS:"
|
||||||
|
|
||||||
if Backend.getDbms() is not None:
|
if Backend.getDbms() is not None:
|
||||||
|
|
|
@ -18,7 +18,7 @@ from lib.core.enums import OS
|
||||||
from thirdparty.six import unichr as _unichr
|
from thirdparty.six import unichr as _unichr
|
||||||
|
|
||||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||||
VERSION = "1.3.6.58"
|
VERSION = "1.3.7.0"
|
||||||
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
||||||
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
|
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)
|
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
|
||||||
|
|
|
@ -63,6 +63,7 @@ class _ThreadData(threading.local):
|
||||||
self.retriesCount = 0
|
self.retriesCount = 0
|
||||||
self.seqMatcher = difflib.SequenceMatcher(None)
|
self.seqMatcher = difflib.SequenceMatcher(None)
|
||||||
self.shared = shared
|
self.shared = shared
|
||||||
|
self.technique = None
|
||||||
self.validationRun = 0
|
self.validationRun = 0
|
||||||
self.valueStack = []
|
self.valueStack = []
|
||||||
|
|
||||||
|
@ -113,6 +114,7 @@ def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardExceptio
|
||||||
|
|
||||||
kb.threadContinue = True
|
kb.threadContinue = True
|
||||||
kb.threadException = False
|
kb.threadException = False
|
||||||
|
kb.technique = ThreadData.technique
|
||||||
|
|
||||||
if threadChoice and numThreads == 1 and not (kb.injection.data and not any(_ not in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED) for _ in kb.injection.data)):
|
if threadChoice and numThreads == 1 and not (kb.injection.data and not any(_ not in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED) for _ in kb.injection.data)):
|
||||||
while True:
|
while True:
|
||||||
|
@ -206,6 +208,7 @@ def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardExceptio
|
||||||
finally:
|
finally:
|
||||||
kb.threadContinue = True
|
kb.threadContinue = True
|
||||||
kb.threadException = False
|
kb.threadException = False
|
||||||
|
kb.technique = None
|
||||||
|
|
||||||
for lock in kb.locks.values():
|
for lock in kb.locks.values():
|
||||||
if lock.locked():
|
if lock.locked():
|
||||||
|
|
|
@ -19,6 +19,7 @@ from lib.core.common import expandAsteriskForColumns
|
||||||
from lib.core.common import extractExpectedValue
|
from lib.core.common import extractExpectedValue
|
||||||
from lib.core.common import filterNone
|
from lib.core.common import filterNone
|
||||||
from lib.core.common import getPublicTypeMembers
|
from lib.core.common import getPublicTypeMembers
|
||||||
|
from lib.core.common import getTechnique
|
||||||
from lib.core.common import getTechniqueData
|
from lib.core.common import getTechniqueData
|
||||||
from lib.core.common import hashDBRetrieve
|
from lib.core.common import hashDBRetrieve
|
||||||
from lib.core.common import hashDBWrite
|
from lib.core.common import hashDBWrite
|
||||||
|
@ -31,6 +32,7 @@ from lib.core.common import popValue
|
||||||
from lib.core.common import pushValue
|
from lib.core.common import pushValue
|
||||||
from lib.core.common import randomStr
|
from lib.core.common import randomStr
|
||||||
from lib.core.common import readInput
|
from lib.core.common import readInput
|
||||||
|
from lib.core.common import setTechnique
|
||||||
from lib.core.common import singleTimeWarnMessage
|
from lib.core.common import singleTimeWarnMessage
|
||||||
from lib.core.compat import xrange
|
from lib.core.compat import xrange
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
|
@ -88,7 +90,7 @@ def _goInference(payload, expression, charsetType=None, firstChar=None, lastChar
|
||||||
if value is not None:
|
if value is not None:
|
||||||
return value
|
return value
|
||||||
|
|
||||||
timeBasedCompare = (kb.technique in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED))
|
timeBasedCompare = (getTechnique() in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED))
|
||||||
|
|
||||||
if timeBasedCompare and conf.threads > 1 and kb.forceThreads is None:
|
if timeBasedCompare and conf.threads > 1 and kb.forceThreads is None:
|
||||||
msg = "multi-threading is considered unsafe in "
|
msg = "multi-threading is considered unsafe in "
|
||||||
|
@ -160,9 +162,9 @@ def _goInferenceProxy(expression, fromUser=False, batch=False, unpack=True, char
|
||||||
parameter through a bisection algorithm.
|
parameter through a bisection algorithm.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
initTechnique(kb.technique)
|
initTechnique(getTechnique())
|
||||||
|
|
||||||
query = agent.prefixQuery(kb.injection.data[kb.technique].vector)
|
query = agent.prefixQuery(kb.injection.data[getTechnique()].vector)
|
||||||
query = agent.suffixQuery(query)
|
query = agent.suffixQuery(query)
|
||||||
payload = agent.payload(newValue=query)
|
payload = agent.payload(newValue=query)
|
||||||
count = None
|
count = None
|
||||||
|
@ -307,10 +309,10 @@ def _goBooleanProxy(expression):
|
||||||
Retrieve the output of a boolean based SQL query
|
Retrieve the output of a boolean based SQL query
|
||||||
"""
|
"""
|
||||||
|
|
||||||
initTechnique(kb.technique)
|
initTechnique(getTechnique())
|
||||||
|
|
||||||
if conf.dnsDomain:
|
if conf.dnsDomain:
|
||||||
query = agent.prefixQuery(kb.injection.data[kb.technique].vector)
|
query = agent.prefixQuery(kb.injection.data[getTechnique()].vector)
|
||||||
query = agent.suffixQuery(query)
|
query = agent.suffixQuery(query)
|
||||||
payload = agent.payload(newValue=query)
|
payload = agent.payload(newValue=query)
|
||||||
output = _goDns(payload, expression)
|
output = _goDns(payload, expression)
|
||||||
|
@ -318,13 +320,13 @@ def _goBooleanProxy(expression):
|
||||||
if output is not None:
|
if output is not None:
|
||||||
return output
|
return output
|
||||||
|
|
||||||
vector = kb.injection.data[kb.technique].vector
|
vector = kb.injection.data[getTechnique()].vector
|
||||||
vector = vector.replace(INFERENCE_MARKER, expression)
|
vector = vector.replace(INFERENCE_MARKER, expression)
|
||||||
query = agent.prefixQuery(vector)
|
query = agent.prefixQuery(vector)
|
||||||
query = agent.suffixQuery(query)
|
query = agent.suffixQuery(query)
|
||||||
payload = agent.payload(newValue=query)
|
payload = agent.payload(newValue=query)
|
||||||
|
|
||||||
timeBasedCompare = kb.technique in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED)
|
timeBasedCompare = getTechnique() in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED)
|
||||||
|
|
||||||
output = hashDBRetrieve(expression, checkConf=True)
|
output = hashDBRetrieve(expression, checkConf=True)
|
||||||
|
|
||||||
|
@ -401,7 +403,7 @@ def getValue(expression, blind=True, union=True, error=True, time=True, fromUser
|
||||||
|
|
||||||
if not conf.forceDns:
|
if not conf.forceDns:
|
||||||
if union and isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION):
|
if union and isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION):
|
||||||
kb.technique = PAYLOAD.TECHNIQUE.UNION
|
setTechnique(PAYLOAD.TECHNIQUE.UNION)
|
||||||
kb.forcePartialUnion = kb.injection.data[PAYLOAD.TECHNIQUE.UNION].vector[8]
|
kb.forcePartialUnion = kb.injection.data[PAYLOAD.TECHNIQUE.UNION].vector[8]
|
||||||
fallback = not expected and kb.injection.data[PAYLOAD.TECHNIQUE.UNION].where == PAYLOAD.WHERE.ORIGINAL and not kb.forcePartialUnion
|
fallback = not expected and kb.injection.data[PAYLOAD.TECHNIQUE.UNION].where == PAYLOAD.WHERE.ORIGINAL and not kb.forcePartialUnion
|
||||||
|
|
||||||
|
@ -433,7 +435,7 @@ def getValue(expression, blind=True, union=True, error=True, time=True, fromUser
|
||||||
singleTimeWarnMessage(warnMsg)
|
singleTimeWarnMessage(warnMsg)
|
||||||
|
|
||||||
if error and any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) and not found:
|
if error and any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) and not found:
|
||||||
kb.technique = PAYLOAD.TECHNIQUE.ERROR if isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) else PAYLOAD.TECHNIQUE.QUERY
|
setTechnique(PAYLOAD.TECHNIQUE.ERROR if isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) else PAYLOAD.TECHNIQUE.QUERY)
|
||||||
value = errorUse(forgeCaseExpression if expected == EXPECTED.BOOL else query, dump)
|
value = errorUse(forgeCaseExpression if expected == EXPECTED.BOOL else query, 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
|
||||||
|
@ -446,7 +448,7 @@ def getValue(expression, blind=True, union=True, error=True, time=True, fromUser
|
||||||
singleTimeWarnMessage(warnMsg)
|
singleTimeWarnMessage(warnMsg)
|
||||||
|
|
||||||
if blind and isTechniqueAvailable(PAYLOAD.TECHNIQUE.BOOLEAN) and not found:
|
if blind and isTechniqueAvailable(PAYLOAD.TECHNIQUE.BOOLEAN) and not found:
|
||||||
kb.technique = PAYLOAD.TECHNIQUE.BOOLEAN
|
setTechnique(PAYLOAD.TECHNIQUE.BOOLEAN)
|
||||||
|
|
||||||
if expected == EXPECTED.BOOL:
|
if expected == EXPECTED.BOOL:
|
||||||
value = _goBooleanProxy(booleanExpression)
|
value = _goBooleanProxy(booleanExpression)
|
||||||
|
@ -461,9 +463,9 @@ def getValue(expression, blind=True, union=True, error=True, time=True, fromUser
|
||||||
kb.responseTimeMode = "%s|%s" % (match.group(1), match.group(2)) if match else None
|
kb.responseTimeMode = "%s|%s" % (match.group(1), match.group(2)) if match else None
|
||||||
|
|
||||||
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.TIME):
|
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.TIME):
|
||||||
kb.technique = PAYLOAD.TECHNIQUE.TIME
|
setTechnique(PAYLOAD.TECHNIQUE.TIME)
|
||||||
else:
|
else:
|
||||||
kb.technique = PAYLOAD.TECHNIQUE.STACKED
|
setTechnique(PAYLOAD.TECHNIQUE.STACKED)
|
||||||
|
|
||||||
if expected == EXPECTED.BOOL:
|
if expected == EXPECTED.BOOL:
|
||||||
value = _goBooleanProxy(booleanExpression)
|
value = _goBooleanProxy(booleanExpression)
|
||||||
|
@ -505,12 +507,12 @@ def getValue(expression, blind=True, union=True, error=True, time=True, fromUser
|
||||||
|
|
||||||
def goStacked(expression, silent=False):
|
def goStacked(expression, silent=False):
|
||||||
if PAYLOAD.TECHNIQUE.STACKED in kb.injection.data:
|
if PAYLOAD.TECHNIQUE.STACKED in kb.injection.data:
|
||||||
kb.technique = PAYLOAD.TECHNIQUE.STACKED
|
setTechnique(PAYLOAD.TECHNIQUE.STACKED)
|
||||||
else:
|
else:
|
||||||
for technique in getPublicTypeMembers(PAYLOAD.TECHNIQUE, True):
|
for technique in getPublicTypeMembers(PAYLOAD.TECHNIQUE, True):
|
||||||
_ = getTechniqueData(technique)
|
_ = getTechniqueData(technique)
|
||||||
if _ and "stacked" in _["title"].lower():
|
if _ and "stacked" in _["title"].lower():
|
||||||
kb.technique = technique
|
setTechnique(technique)
|
||||||
break
|
break
|
||||||
|
|
||||||
expression = cleanQuery(expression)
|
expression = cleanQuery(expression)
|
||||||
|
|
|
@ -20,6 +20,7 @@ from lib.core.common import getAutoDirectories
|
||||||
from lib.core.common import getManualDirectories
|
from lib.core.common import getManualDirectories
|
||||||
from lib.core.common import getPublicTypeMembers
|
from lib.core.common import getPublicTypeMembers
|
||||||
from lib.core.common import getSQLSnippet
|
from lib.core.common import getSQLSnippet
|
||||||
|
from lib.core.common import getTechnique
|
||||||
from lib.core.common import isTechniqueAvailable
|
from lib.core.common import isTechniqueAvailable
|
||||||
from lib.core.common import isWindowsDriveLetterPath
|
from lib.core.common import isWindowsDriveLetterPath
|
||||||
from lib.core.common import normalizePath
|
from lib.core.common import normalizePath
|
||||||
|
@ -147,8 +148,8 @@ class Web(object):
|
||||||
uplQuery = getUnicode(fileContent).replace(SHELL_WRITABLE_DIR_TAG, directory.replace('/', '\\\\') if Backend.isOs(OS.WINDOWS) else directory)
|
uplQuery = getUnicode(fileContent).replace(SHELL_WRITABLE_DIR_TAG, directory.replace('/', '\\\\') if Backend.isOs(OS.WINDOWS) else directory)
|
||||||
query = ""
|
query = ""
|
||||||
|
|
||||||
if isTechniqueAvailable(kb.technique):
|
if isTechniqueAvailable(getTechnique()):
|
||||||
where = kb.injection.data[kb.technique].where
|
where = kb.injection.data[getTechnique()].where
|
||||||
|
|
||||||
if where == PAYLOAD.WHERE.NEGATIVE:
|
if where == PAYLOAD.WHERE.NEGATIVE:
|
||||||
randInt = randomInt()
|
randInt = randomInt()
|
||||||
|
|
|
@ -22,6 +22,7 @@ from lib.core.common import filterControlChars
|
||||||
from lib.core.common import getCharset
|
from lib.core.common import getCharset
|
||||||
from lib.core.common import getCounter
|
from lib.core.common import getCounter
|
||||||
from lib.core.common import getPartRun
|
from lib.core.common import getPartRun
|
||||||
|
from lib.core.common import getTechnique
|
||||||
from lib.core.common import goGoodSamaritan
|
from lib.core.common import goGoodSamaritan
|
||||||
from lib.core.common import hashDBRetrieve
|
from lib.core.common import hashDBRetrieve
|
||||||
from lib.core.common import hashDBWrite
|
from lib.core.common import hashDBWrite
|
||||||
|
@ -80,7 +81,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||||
asciiTbl = getCharset(charsetType)
|
asciiTbl = getCharset(charsetType)
|
||||||
|
|
||||||
threadData = getCurrentThreadData()
|
threadData = getCurrentThreadData()
|
||||||
timeBasedCompare = (kb.technique in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED))
|
timeBasedCompare = (getTechnique() in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED))
|
||||||
retVal = hashDBRetrieve(expression, checkConf=True)
|
retVal = hashDBRetrieve(expression, checkConf=True)
|
||||||
|
|
||||||
if retVal:
|
if retVal:
|
||||||
|
@ -201,7 +202,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||||
forgedPayload = agent.extractPayload(payload)
|
forgedPayload = agent.extractPayload(payload)
|
||||||
forgedPayload = safeStringFormat(forgedPayload.replace(INFERENCE_GREATER_CHAR, INFERENCE_EQUALS_CHAR), (expressionUnescaped, idx, posValue)).replace(markingValue, unescapedCharValue)
|
forgedPayload = safeStringFormat(forgedPayload.replace(INFERENCE_GREATER_CHAR, INFERENCE_EQUALS_CHAR), (expressionUnescaped, idx, posValue)).replace(markingValue, unescapedCharValue)
|
||||||
result = Request.queryPage(agent.replacePayload(payload, forgedPayload), timeBasedCompare=timeBasedCompare, raise404=False)
|
result = Request.queryPage(agent.replacePayload(payload, forgedPayload), timeBasedCompare=timeBasedCompare, raise404=False)
|
||||||
incrementCounter(kb.technique)
|
incrementCounter(getTechnique())
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
return hintValue[idx - 1]
|
return hintValue[idx - 1]
|
||||||
|
@ -228,13 +229,13 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||||
|
|
||||||
result = not Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
|
result = not Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
|
||||||
|
|
||||||
if result and timeBasedCompare and kb.injection.data[kb.technique].trueCode:
|
if result and timeBasedCompare and kb.injection.data[getTechnique()].trueCode:
|
||||||
result = threadData.lastCode == kb.injection.data[kb.technique].trueCode
|
result = threadData.lastCode == kb.injection.data[getTechnique()].trueCode
|
||||||
if not result:
|
if not result:
|
||||||
warnMsg = "detected HTTP code '%s' in validation phase is differing from expected '%s'" % (threadData.lastCode, kb.injection.data[kb.technique].trueCode)
|
warnMsg = "detected HTTP code '%s' in validation phase is differing from expected '%s'" % (threadData.lastCode, kb.injection.data[getTechnique()].trueCode)
|
||||||
singleTimeWarnMessage(warnMsg)
|
singleTimeWarnMessage(warnMsg)
|
||||||
|
|
||||||
incrementCounter(kb.technique)
|
incrementCounter(getTechnique())
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -269,7 +270,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||||
elif len(charTbl) == 1:
|
elif len(charTbl) == 1:
|
||||||
forgedPayload = safeStringFormat(payload.replace(INFERENCE_GREATER_CHAR, INFERENCE_EQUALS_CHAR), (expressionUnescaped, idx, charTbl[0]))
|
forgedPayload = safeStringFormat(payload.replace(INFERENCE_GREATER_CHAR, INFERENCE_EQUALS_CHAR), (expressionUnescaped, idx, charTbl[0]))
|
||||||
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
|
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
|
||||||
incrementCounter(kb.technique)
|
incrementCounter(getTechnique())
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
return decodeIntToUnicode(charTbl[0])
|
return decodeIntToUnicode(charTbl[0])
|
||||||
|
@ -338,10 +339,10 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||||
kb.responseTimePayload = None
|
kb.responseTimePayload = None
|
||||||
|
|
||||||
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
|
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
|
||||||
incrementCounter(kb.technique)
|
incrementCounter(getTechnique())
|
||||||
|
|
||||||
if not timeBasedCompare:
|
if not timeBasedCompare:
|
||||||
unexpectedCode |= threadData.lastCode not in (kb.injection.data[kb.technique].falseCode, kb.injection.data[kb.technique].trueCode)
|
unexpectedCode |= threadData.lastCode not in (kb.injection.data[getTechnique()].falseCode, kb.injection.data[getTechnique()].trueCode)
|
||||||
if unexpectedCode:
|
if unexpectedCode:
|
||||||
warnMsg = "unexpected HTTP code '%s' detected. Will use (extra) validation step in similar cases" % threadData.lastCode
|
warnMsg = "unexpected HTTP code '%s' detected. Will use (extra) validation step in similar cases" % threadData.lastCode
|
||||||
singleTimeWarnMessage(warnMsg)
|
singleTimeWarnMessage(warnMsg)
|
||||||
|
@ -439,7 +440,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||||
|
|
||||||
forgedPayload = safeStringFormat(payload.replace(INFERENCE_GREATER_CHAR, "&%d%s" % (mask, INFERENCE_GREATER_CHAR)), (expressionUnescaped, idx, 0))
|
forgedPayload = safeStringFormat(payload.replace(INFERENCE_GREATER_CHAR, "&%d%s" % (mask, INFERENCE_GREATER_CHAR)), (expressionUnescaped, idx, 0))
|
||||||
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
|
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
|
||||||
incrementCounter(kb.technique)
|
incrementCounter(getTechnique())
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
candidates = [_ for _ in candidates if _ & mask > 0]
|
candidates = [_ for _ in candidates if _ & mask > 0]
|
||||||
|
@ -451,7 +452,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||||
if candidates:
|
if candidates:
|
||||||
forgedPayload = safeStringFormat(payload.replace(INFERENCE_GREATER_CHAR, INFERENCE_EQUALS_CHAR), (expressionUnescaped, idx, candidates[0]))
|
forgedPayload = safeStringFormat(payload.replace(INFERENCE_GREATER_CHAR, INFERENCE_EQUALS_CHAR), (expressionUnescaped, idx, candidates[0]))
|
||||||
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
|
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
|
||||||
incrementCounter(kb.technique)
|
incrementCounter(getTechnique())
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
return decodeIntToUnicode(candidates[0])
|
return decodeIntToUnicode(candidates[0])
|
||||||
|
@ -569,12 +570,12 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||||
# One-shot query containing equals commonValue
|
# One-shot query containing equals commonValue
|
||||||
testValue = unescaper.escape("'%s'" % commonValue) if "'" not in commonValue else unescaper.escape("%s" % commonValue, quote=False)
|
testValue = unescaper.escape("'%s'" % commonValue) if "'" not in commonValue else unescaper.escape("%s" % commonValue, quote=False)
|
||||||
|
|
||||||
query = kb.injection.data[kb.technique].vector
|
query = kb.injection.data[getTechnique()].vector
|
||||||
query = agent.prefixQuery(query.replace(INFERENCE_MARKER, "(%s)%s%s" % (expressionUnescaped, INFERENCE_EQUALS_CHAR, testValue)))
|
query = agent.prefixQuery(query.replace(INFERENCE_MARKER, "(%s)%s%s" % (expressionUnescaped, INFERENCE_EQUALS_CHAR, testValue)))
|
||||||
query = agent.suffixQuery(query)
|
query = agent.suffixQuery(query)
|
||||||
|
|
||||||
result = Request.queryPage(agent.payload(newValue=query), timeBasedCompare=timeBasedCompare, raise404=False)
|
result = Request.queryPage(agent.payload(newValue=query), timeBasedCompare=timeBasedCompare, raise404=False)
|
||||||
incrementCounter(kb.technique)
|
incrementCounter(getTechnique())
|
||||||
|
|
||||||
# Did we have luck?
|
# Did we have luck?
|
||||||
if result:
|
if result:
|
||||||
|
@ -593,12 +594,12 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||||
subquery = queries[Backend.getIdentifiedDbms()].substring.query % (expressionUnescaped, 1, len(commonPattern))
|
subquery = queries[Backend.getIdentifiedDbms()].substring.query % (expressionUnescaped, 1, len(commonPattern))
|
||||||
testValue = unescaper.escape("'%s'" % commonPattern) if "'" not in commonPattern else unescaper.escape("%s" % commonPattern, quote=False)
|
testValue = unescaper.escape("'%s'" % commonPattern) if "'" not in commonPattern else unescaper.escape("%s" % commonPattern, quote=False)
|
||||||
|
|
||||||
query = kb.injection.data[kb.technique].vector
|
query = kb.injection.data[getTechnique()].vector
|
||||||
query = agent.prefixQuery(query.replace(INFERENCE_MARKER, "(%s)=%s" % (subquery, testValue)))
|
query = agent.prefixQuery(query.replace(INFERENCE_MARKER, "(%s)=%s" % (subquery, testValue)))
|
||||||
query = agent.suffixQuery(query)
|
query = agent.suffixQuery(query)
|
||||||
|
|
||||||
result = Request.queryPage(agent.payload(newValue=query), timeBasedCompare=timeBasedCompare, raise404=False)
|
result = Request.queryPage(agent.payload(newValue=query), timeBasedCompare=timeBasedCompare, raise404=False)
|
||||||
incrementCounter(kb.technique)
|
incrementCounter(getTechnique())
|
||||||
|
|
||||||
# Did we have luck?
|
# Did we have luck?
|
||||||
if result:
|
if result:
|
||||||
|
@ -678,7 +679,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||||
|
|
||||||
_ = finalValue or partialValue
|
_ = finalValue or partialValue
|
||||||
|
|
||||||
return getCounter(kb.technique), safecharencode(_) if kb.safeCharEncode else _
|
return getCounter(getTechnique()), safecharencode(_) if kb.safeCharEncode else _
|
||||||
|
|
||||||
def queryOutputLength(expression, payload):
|
def queryOutputLength(expression, payload):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -21,6 +21,7 @@ from lib.core.common import extractRegexResult
|
||||||
from lib.core.common import firstNotNone
|
from lib.core.common import firstNotNone
|
||||||
from lib.core.common import getConsoleWidth
|
from lib.core.common import getConsoleWidth
|
||||||
from lib.core.common import getPartRun
|
from lib.core.common import getPartRun
|
||||||
|
from lib.core.common import getTechnique
|
||||||
from lib.core.common import hashDBRetrieve
|
from lib.core.common import hashDBRetrieve
|
||||||
from lib.core.common import hashDBWrite
|
from lib.core.common import hashDBWrite
|
||||||
from lib.core.common import incrementCounter
|
from lib.core.common import incrementCounter
|
||||||
|
@ -43,7 +44,6 @@ from lib.core.dicts import FROM_DUMMY_TABLE
|
||||||
from lib.core.enums import DBMS
|
from lib.core.enums import DBMS
|
||||||
from lib.core.enums import HASHDB_KEYS
|
from lib.core.enums import HASHDB_KEYS
|
||||||
from lib.core.enums import HTTP_HEADER
|
from lib.core.enums import HTTP_HEADER
|
||||||
from lib.core.enums import PAYLOAD
|
|
||||||
from lib.core.exception import SqlmapDataException
|
from lib.core.exception import SqlmapDataException
|
||||||
from lib.core.settings import CHECK_ZERO_COLUMNS_THRESHOLD
|
from lib.core.settings import CHECK_ZERO_COLUMNS_THRESHOLD
|
||||||
from lib.core.settings import MAX_ERROR_CHUNK_LENGTH
|
from lib.core.settings import MAX_ERROR_CHUNK_LENGTH
|
||||||
|
@ -124,7 +124,7 @@ def _oneShotErrorUse(expression, field=None, chunkTest=False):
|
||||||
nulledCastedField = queries[Backend.getIdentifiedDbms()].substring.query % (nulledCastedField, offset, kb.errorChunkLength)
|
nulledCastedField = queries[Backend.getIdentifiedDbms()].substring.query % (nulledCastedField, offset, kb.errorChunkLength)
|
||||||
|
|
||||||
# Forge the error-based SQL injection request
|
# Forge the error-based SQL injection request
|
||||||
vector = kb.injection.data[PAYLOAD.TECHNIQUE.ERROR].vector
|
vector = kb.injection.data[getTechnique()].vector
|
||||||
query = agent.prefixQuery(vector)
|
query = agent.prefixQuery(vector)
|
||||||
query = agent.suffixQuery(query)
|
query = agent.suffixQuery(query)
|
||||||
injExpression = expression.replace(field, nulledCastedField, 1) if field else expression
|
injExpression = expression.replace(field, nulledCastedField, 1) if field else expression
|
||||||
|
@ -135,7 +135,7 @@ def _oneShotErrorUse(expression, field=None, chunkTest=False):
|
||||||
# Perform the request
|
# Perform the request
|
||||||
page, headers, _ = Request.queryPage(payload, content=True, raise404=False)
|
page, headers, _ = Request.queryPage(payload, content=True, raise404=False)
|
||||||
|
|
||||||
incrementCounter(PAYLOAD.TECHNIQUE.ERROR)
|
incrementCounter(getTechnique())
|
||||||
|
|
||||||
if page and conf.noEscape:
|
if page and conf.noEscape:
|
||||||
page = re.sub(r"('|\%%27)%s('|\%%27).*?('|\%%27)%s('|\%%27)" % (kb.chars.start, kb.chars.stop), "", page)
|
page = re.sub(r"('|\%%27)%s('|\%%27).*?('|\%%27)%s('|\%%27)" % (kb.chars.start, kb.chars.stop), "", page)
|
||||||
|
@ -299,7 +299,7 @@ def errorUse(expression, dump=False):
|
||||||
SQL injection vulnerability on the affected parameter.
|
SQL injection vulnerability on the affected parameter.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
initTechnique(PAYLOAD.TECHNIQUE.ERROR)
|
initTechnique(getTechnique())
|
||||||
|
|
||||||
abortedFlag = False
|
abortedFlag = False
|
||||||
count = None
|
count = None
|
||||||
|
@ -461,7 +461,7 @@ def errorUse(expression, dump=False):
|
||||||
duration = calculateDeltaSeconds(start)
|
duration = calculateDeltaSeconds(start)
|
||||||
|
|
||||||
if not kb.bruteMode:
|
if not kb.bruteMode:
|
||||||
debugMsg = "performed %d queries in %.2f seconds" % (kb.counters[PAYLOAD.TECHNIQUE.ERROR], duration)
|
debugMsg = "performed %d queries in %.2f seconds" % (kb.counters[getTechnique()], duration)
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
|
@ -20,6 +20,7 @@ from lib.core.common import randomInt
|
||||||
from lib.core.common import randomStr
|
from lib.core.common import randomStr
|
||||||
from lib.core.common import readInput
|
from lib.core.common import readInput
|
||||||
from lib.core.common import removeReflectiveValues
|
from lib.core.common import removeReflectiveValues
|
||||||
|
from lib.core.common import setTechnique
|
||||||
from lib.core.common import singleTimeLogMessage
|
from lib.core.common import singleTimeLogMessage
|
||||||
from lib.core.common import singleTimeWarnMessage
|
from lib.core.common import singleTimeWarnMessage
|
||||||
from lib.core.common import stdev
|
from lib.core.common import stdev
|
||||||
|
@ -323,7 +324,7 @@ def unionTest(comment, place, parameter, value, prefix, suffix):
|
||||||
return
|
return
|
||||||
|
|
||||||
negativeLogic = kb.negativeLogic
|
negativeLogic = kb.negativeLogic
|
||||||
kb.technique = PAYLOAD.TECHNIQUE.UNION
|
setTechnique(PAYLOAD.TECHNIQUE.UNION)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if negativeLogic:
|
if negativeLogic:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user