mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2024-11-25 19:13:48 +03:00
Implementation for #2709
This commit is contained in:
parent
db94d24db1
commit
222fd856fa
|
@ -19,7 +19,7 @@ from lib.core.enums import DBMS_DIRECTORY_NAME
|
||||||
from lib.core.enums import OS
|
from lib.core.enums import OS
|
||||||
|
|
||||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||||
VERSION = "1.1.9.23"
|
VERSION = "1.1.9.24"
|
||||||
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)
|
||||||
|
|
|
@ -278,86 +278,86 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||||
lastCheck = False
|
lastCheck = False
|
||||||
unexpectedCode = False
|
unexpectedCode = False
|
||||||
|
|
||||||
while len(charTbl) > 1:
|
if continuousOrder:
|
||||||
position = None
|
while len(charTbl) > 1:
|
||||||
|
position = None
|
||||||
|
|
||||||
if charsetType is None:
|
if charsetType is None:
|
||||||
if not firstCheck:
|
if not firstCheck:
|
||||||
try:
|
|
||||||
try:
|
try:
|
||||||
lastChar = [_ for _ in threadData.shared.value if _ is not None][-1]
|
try:
|
||||||
except IndexError:
|
lastChar = [_ for _ in threadData.shared.value if _ is not None][-1]
|
||||||
lastChar = None
|
except IndexError:
|
||||||
if 'a' <= lastChar <= 'z':
|
lastChar = None
|
||||||
position = charTbl.index(ord('a') - 1) # 96
|
if 'a' <= lastChar <= 'z':
|
||||||
elif 'A' <= lastChar <= 'Z':
|
position = charTbl.index(ord('a') - 1) # 96
|
||||||
position = charTbl.index(ord('A') - 1) # 64
|
elif 'A' <= lastChar <= 'Z':
|
||||||
elif '0' <= lastChar <= '9':
|
position = charTbl.index(ord('A') - 1) # 64
|
||||||
position = charTbl.index(ord('0') - 1) # 47
|
elif '0' <= lastChar <= '9':
|
||||||
except ValueError:
|
position = charTbl.index(ord('0') - 1) # 47
|
||||||
pass
|
|
||||||
finally:
|
|
||||||
firstCheck = True
|
|
||||||
|
|
||||||
elif not lastCheck and numThreads == 1: # not usable in multi-threading environment
|
|
||||||
if charTbl[(len(charTbl) >> 1)] < ord(' '):
|
|
||||||
try:
|
|
||||||
# favorize last char check if current value inclines toward 0
|
|
||||||
position = charTbl.index(1)
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
finally:
|
finally:
|
||||||
lastCheck = True
|
firstCheck = True
|
||||||
|
|
||||||
if position is None:
|
elif not lastCheck and numThreads == 1: # not usable in multi-threading environment
|
||||||
position = (len(charTbl) >> 1)
|
if charTbl[(len(charTbl) >> 1)] < ord(' '):
|
||||||
|
try:
|
||||||
|
# favorize last char check if current value inclines toward 0
|
||||||
|
position = charTbl.index(1)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
lastCheck = True
|
||||||
|
|
||||||
posValue = charTbl[position]
|
if position is None:
|
||||||
falsePayload = None
|
position = (len(charTbl) >> 1)
|
||||||
|
|
||||||
if "'%s'" % CHAR_INFERENCE_MARK not in payload:
|
posValue = charTbl[position]
|
||||||
forgedPayload = safeStringFormat(payload, (expressionUnescaped, idx, posValue))
|
falsePayload = None
|
||||||
falsePayload = safeStringFormat(payload, (expressionUnescaped, idx, RANDOM_INTEGER_MARKER))
|
|
||||||
else:
|
|
||||||
# e.g.: ... > '%c' -> ... > ORD(..)
|
|
||||||
markingValue = "'%s'" % CHAR_INFERENCE_MARK
|
|
||||||
unescapedCharValue = unescaper.escape("'%s'" % decodeIntToUnicode(posValue))
|
|
||||||
forgedPayload = safeStringFormat(payload, (expressionUnescaped, idx)).replace(markingValue, unescapedCharValue)
|
|
||||||
falsePayload = safeStringFormat(payload, (expressionUnescaped, idx)).replace(markingValue, NULL)
|
|
||||||
|
|
||||||
if timeBasedCompare:
|
if "'%s'" % CHAR_INFERENCE_MARK not in payload:
|
||||||
if kb.responseTimeMode:
|
forgedPayload = safeStringFormat(payload, (expressionUnescaped, idx, posValue))
|
||||||
kb.responseTimePayload = falsePayload
|
falsePayload = safeStringFormat(payload, (expressionUnescaped, idx, RANDOM_INTEGER_MARKER))
|
||||||
else:
|
else:
|
||||||
kb.responseTimePayload = None
|
# e.g.: ... > '%c' -> ... > ORD(..)
|
||||||
|
markingValue = "'%s'" % CHAR_INFERENCE_MARK
|
||||||
|
unescapedCharValue = unescaper.escape("'%s'" % decodeIntToUnicode(posValue))
|
||||||
|
forgedPayload = safeStringFormat(payload, (expressionUnescaped, idx)).replace(markingValue, unescapedCharValue)
|
||||||
|
falsePayload = safeStringFormat(payload, (expressionUnescaped, idx)).replace(markingValue, NULL)
|
||||||
|
|
||||||
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
|
if timeBasedCompare:
|
||||||
incrementCounter(kb.technique)
|
if kb.responseTimeMode:
|
||||||
|
kb.responseTimePayload = falsePayload
|
||||||
|
else:
|
||||||
|
kb.responseTimePayload = None
|
||||||
|
|
||||||
if not timeBasedCompare:
|
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
|
||||||
unexpectedCode |= threadData.lastCode not in (kb.injection.data[kb.technique].falseCode, kb.injection.data[kb.technique].trueCode)
|
incrementCounter(kb.technique)
|
||||||
if unexpectedCode:
|
|
||||||
warnMsg = "unexpected HTTP code '%s' detected. Will use (extra) validation step in similar cases" % threadData.lastCode
|
|
||||||
singleTimeWarnMessage(warnMsg)
|
|
||||||
|
|
||||||
if result:
|
if not timeBasedCompare:
|
||||||
minValue = posValue
|
unexpectedCode |= threadData.lastCode not in (kb.injection.data[kb.technique].falseCode, kb.injection.data[kb.technique].trueCode)
|
||||||
|
if unexpectedCode:
|
||||||
|
warnMsg = "unexpected HTTP code '%s' detected. Will use (extra) validation step in similar cases" % threadData.lastCode
|
||||||
|
singleTimeWarnMessage(warnMsg)
|
||||||
|
|
||||||
if type(charTbl) != xrange:
|
if result:
|
||||||
charTbl = charTbl[position:]
|
minValue = posValue
|
||||||
|
|
||||||
|
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:
|
else:
|
||||||
# xrange() - extended virtual charset used for memory/space optimization
|
maxValue = posValue
|
||||||
charTbl = xrange(charTbl[position], charTbl[-1] + 1)
|
|
||||||
else:
|
|
||||||
maxValue = posValue
|
|
||||||
|
|
||||||
if type(charTbl) != xrange:
|
if type(charTbl) != xrange:
|
||||||
charTbl = charTbl[:position]
|
charTbl = charTbl[:position]
|
||||||
else:
|
else:
|
||||||
charTbl = xrange(charTbl[0], charTbl[position])
|
charTbl = xrange(charTbl[0], charTbl[position])
|
||||||
|
|
||||||
if len(charTbl) == 1:
|
if len(charTbl) == 1:
|
||||||
if continuousOrder:
|
|
||||||
if maxValue == 1:
|
if maxValue == 1:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -416,25 +416,40 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||||
return decodeIntToUnicode(retVal)
|
return decodeIntToUnicode(retVal)
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
else:
|
||||||
|
candidates = list(originalTbl)
|
||||||
|
bit = 0
|
||||||
|
while len(candidates) > 1:
|
||||||
|
bits = {}
|
||||||
|
for candidate in candidates:
|
||||||
|
bit = 0
|
||||||
|
while candidate:
|
||||||
|
bits.setdefault(bit, 0)
|
||||||
|
bits[bit] += 1 if candidate & 1 else -1
|
||||||
|
candidate >>= 1
|
||||||
|
bit += 1
|
||||||
|
|
||||||
|
choice = sorted(bits.items(), key=lambda _: abs(_[1]))[0][0]
|
||||||
|
mask = 1 << choice
|
||||||
|
|
||||||
|
forgedPayload = safeStringFormat(payload.replace(INFERENCE_GREATER_CHAR, "&%d%s" % (mask, INFERENCE_GREATER_CHAR)), (expressionUnescaped, idx, 0))
|
||||||
|
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
|
||||||
|
incrementCounter(kb.technique)
|
||||||
|
|
||||||
|
if result:
|
||||||
|
candidates = [_ for _ in candidates if _ & mask > 0]
|
||||||
else:
|
else:
|
||||||
if minValue == maxChar or maxValue == minChar:
|
candidates = [_ for _ in candidates if _ & mask == 0]
|
||||||
return None
|
|
||||||
|
|
||||||
for index in xrange(len(originalTbl)):
|
bit += 1
|
||||||
if originalTbl[index] == minValue:
|
|
||||||
break
|
|
||||||
|
|
||||||
# If we are working with non-continuous elements, both minValue and character after
|
if candidates:
|
||||||
# are possible candidates
|
forgedPayload = safeStringFormat(payload.replace(INFERENCE_GREATER_CHAR, INFERENCE_EQUALS_CHAR), (expressionUnescaped, idx, candidates[0]))
|
||||||
for retVal in (originalTbl[index], originalTbl[index + 1]):
|
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
|
||||||
forgedPayload = safeStringFormat(payload.replace(INFERENCE_GREATER_CHAR, INFERENCE_EQUALS_CHAR), (expressionUnescaped, idx, retVal))
|
incrementCounter(kb.technique)
|
||||||
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
|
|
||||||
incrementCounter(kb.technique)
|
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
return decodeIntToUnicode(retVal)
|
return decodeIntToUnicode(candidates[0])
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Go multi-threading (--threads > 1)
|
# Go multi-threading (--threads > 1)
|
||||||
if conf.threads > 1 and isinstance(length, int) and length > 1:
|
if conf.threads > 1 and isinstance(length, int) and length > 1:
|
||||||
|
|
|
@ -46,7 +46,7 @@ e8e9fd4f224ead0caa1569312b5b2582 lib/core/optiondict.py
|
||||||
d8e9250f3775119df07e9070eddccd16 lib/core/replication.py
|
d8e9250f3775119df07e9070eddccd16 lib/core/replication.py
|
||||||
785f86e3f963fa3798f84286a4e83ff2 lib/core/revision.py
|
785f86e3f963fa3798f84286a4e83ff2 lib/core/revision.py
|
||||||
40c80b28b3a5819b737a5a17d4565ae9 lib/core/session.py
|
40c80b28b3a5819b737a5a17d4565ae9 lib/core/session.py
|
||||||
bc83df99ea0febcf872e078408a71c8f lib/core/settings.py
|
bb423d7f62041a13e0264e9718d003f2 lib/core/settings.py
|
||||||
d91291997d2bd2f6028aaf371bf1d3b6 lib/core/shell.py
|
d91291997d2bd2f6028aaf371bf1d3b6 lib/core/shell.py
|
||||||
2ad85c130cc5f2b3701ea85c2f6bbf20 lib/core/subprocessng.py
|
2ad85c130cc5f2b3701ea85c2f6bbf20 lib/core/subprocessng.py
|
||||||
effc153067a00bd43461bfc1cdec1122 lib/core/target.py
|
effc153067a00bd43461bfc1cdec1122 lib/core/target.py
|
||||||
|
@ -87,7 +87,7 @@ ac541a0d38e4ecb4e41e97799a7235f4 lib/takeover/registry.py
|
||||||
ff1af7f85fdf4f2a5369f2927d149824 lib/takeover/udf.py
|
ff1af7f85fdf4f2a5369f2927d149824 lib/takeover/udf.py
|
||||||
8df5a334823b724a2207a28c94f6fe3d lib/takeover/web.py
|
8df5a334823b724a2207a28c94f6fe3d lib/takeover/web.py
|
||||||
b4c3264b9b6dcbf00cb7bffa447d1f6c lib/takeover/xp_cmdshell.py
|
b4c3264b9b6dcbf00cb7bffa447d1f6c lib/takeover/xp_cmdshell.py
|
||||||
988677fd3625518b771566b407adfef6 lib/techniques/blind/inference.py
|
f18caf2e50366057771316a490c90795 lib/techniques/blind/inference.py
|
||||||
310efc965c862cfbd7b0da5150a5ad36 lib/techniques/blind/__init__.py
|
310efc965c862cfbd7b0da5150a5ad36 lib/techniques/blind/__init__.py
|
||||||
310efc965c862cfbd7b0da5150a5ad36 lib/techniques/dns/__init__.py
|
310efc965c862cfbd7b0da5150a5ad36 lib/techniques/dns/__init__.py
|
||||||
ab1601a7f429b47637c4fb8af703d0f1 lib/techniques/dns/test.py
|
ab1601a7f429b47637c4fb8af703d0f1 lib/techniques/dns/test.py
|
||||||
|
|
Loading…
Reference in New Issue
Block a user