mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2026-07-03 23:11:29 +00:00
Minor improvement of UNION detection
This commit is contained in:
parent
bd10f84a9b
commit
1716ad1524
5 changed files with 36 additions and 13 deletions
|
|
@ -163,10 +163,10 @@ df768bcb9838dc6c46dab9b4a877056cb4742bd6cfaaf438c4a3712c5cc0d264 extra/shutils/
|
|||
9af5fdfa8b2425d404d86ab08d3644caa95bcf77605551f5da482a59d1e54a22 extra/vulnserver/vulnserver.py
|
||||
a2bf70d7f87c3a4e0675c0bad54119a4e04efa6ea2730a8338d5aebcd995630e lib/controller/action.py
|
||||
736715a73941a06e5d3d349dd01a1f1b171f54eb4c374c6752b2cc44b0977ffe lib/controller/checks.py
|
||||
666935b658074dc9c42153622b75d4ec7bfe56fbe0742de827a5d30a1a0f9d96 lib/controller/controller.py
|
||||
2086100cd7a78a4e8c12d72bd4f5b414ec6b3f49926e83285494534140e60ce7 lib/controller/controller.py
|
||||
d69e84f1648cdb907f5d2dd454f03874a4613752b07867510145d51d84b3c56f lib/controller/handler.py
|
||||
1966ca704961fb987ab757f0a4afddbf841d1a880631b701487c75cef63d60c3 lib/controller/__init__.py
|
||||
9c5764c92ce536d1f0f96200359ee5ef1f37f9128769bf990cb77f1d1f8e17b1 lib/core/agent.py
|
||||
48ffe93d61734e16c3b20153b51595853d9ac1fbcf0b537e0e61e957b0c0bfa6 lib/core/agent.py
|
||||
c51c33501cc905586a9aaac93b06f2ac6f71628d032a7dc39fd0ef05d7ee3856 lib/core/bigarray.py
|
||||
f73bbb05c1cfd642e8f556f3047f8418bed07b06f555d445b6f14c03c105b87a lib/core/common.py
|
||||
8f1272487e1adfcc8c755a2f56f0c6d21eac5e685a73a9a159482f9dc9142bc5 lib/core/compat.py
|
||||
|
|
@ -189,7 +189,7 @@ b14628a6c9327d110afe50b01f3171f64f61823343b8de89596e854b00b74928 lib/core/dump.
|
|||
9bf174058f15d14e24e94f9aaf42df045119d3617c6c54bd2f3af79b462f331d lib/core/replication.py
|
||||
0b8c38a01bb01f843d94a6c5f2075ee47520d0c4aa799cecea9c3e2c5a4a23a6 lib/core/revision.py
|
||||
888daba83fd4a34e9503fe21f01fef4cc730e5cde871b1d40e15d4cbc847d56c lib/core/session.py
|
||||
459f3adf2d8acfe810410faea7fa5bddfc2ee0b1af284413a4a9fd1d11334047 lib/core/settings.py
|
||||
c84d55438df9338804398ec3d8bc7b95cb4024dd356db9aeb4ea1cb19edcb794 lib/core/settings.py
|
||||
c7804223319e18eb0b8e2cbf0a8b6896d1cefb7b0b1a2e9f1cf826a8a3b56750 lib/core/shell.py
|
||||
a2e98a94b231432736d6b304fc75525c8b5fdb4768c418387c5b4c1a610dad64 lib/core/subprocessng.py
|
||||
15d36cdac9389d0a54a6c33fbb89f32bb65e303f50de573773dcb6d4618bca64 lib/core/target.py
|
||||
|
|
@ -250,7 +250,7 @@ bde75d41ac3e5747b96d2af4c33922573158cb43b48714a28490d6720dd85d89 lib/techniques
|
|||
1966ca704961fb987ab757f0a4afddbf841d1a880631b701487c75cef63d60c3 lib/techniques/ssti/__init__.py
|
||||
14637b64878248e5965887b07aa68e62615dac88e2ffc6c3a581430bdd4e309e lib/techniques/ssti/inject.py
|
||||
1966ca704961fb987ab757f0a4afddbf841d1a880631b701487c75cef63d60c3 lib/techniques/union/__init__.py
|
||||
ceec65f8cb7c3254c4671351c837418c76ac5bc55ccbc40779f67231b54d7085 lib/techniques/union/test.py
|
||||
f6678ac1342f8d234ed32ae69be5ac5d7837393e9348929ec029c9764c030e82 lib/techniques/union/test.py
|
||||
c68f8259e0a89a556d049f227041849df584313bd1b5349b02f74a47778c901c lib/techniques/union/use.py
|
||||
1966ca704961fb987ab757f0a4afddbf841d1a880631b701487c75cef63d60c3 lib/techniques/xpath/__init__.py
|
||||
c61816c9dba9f6cc2223aed1a923f95130979e5f0a88ec254ee667d955ed2734 lib/techniques/xpath/inject.py
|
||||
|
|
|
|||
|
|
@ -561,9 +561,10 @@ def start():
|
|||
checkNullConnection()
|
||||
|
||||
if (len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None)) and (kb.injection.place is None or kb.injection.parameter is None):
|
||||
if not any((conf.string, conf.notString, conf.regexp)) and PAYLOAD.TECHNIQUE.BOOLEAN in conf.technique:
|
||||
# NOTE: this is not needed anymore, leaving only to display
|
||||
# a warning message to the user in case the page is not stable
|
||||
if not any((conf.string, conf.notString, conf.regexp)) and any(_ in conf.technique for _ in (PAYLOAD.TECHNIQUE.BOOLEAN, PAYLOAD.TECHNIQUE.UNION)):
|
||||
# NOTE: besides the not-stable warning, this marks dynamic content for removal, which
|
||||
# UNION column-count detection relies on too (it compares pages) - so it must run when
|
||||
# UNION is tested even if BOOLEAN is excluded (e.g. '--technique=U' on a dynamic page)
|
||||
checkStability()
|
||||
|
||||
# Do a little prioritization reorder of a testable parameter list
|
||||
|
|
|
|||
|
|
@ -958,12 +958,19 @@ class Agent(object):
|
|||
if not infoFile:
|
||||
query = _collate(query)
|
||||
|
||||
# A fuzzy-discovered per-column type template (kb.unionTemplate, e.g. ['1234', '%s', '5678'])
|
||||
# forces type-compatible fillers on strict DBMSes (e.g. Apache Derby, which rejects bare NULL
|
||||
# and demands UNION column-type parity); '%s' marks the slot carrying the injected expression.
|
||||
template = kb.unionTemplate if isinstance(kb.unionTemplate, (list, tuple)) and len(kb.unionTemplate) == count else None
|
||||
|
||||
for element in xrange(0, count):
|
||||
if element > 0:
|
||||
unionQuery += ','
|
||||
|
||||
if conf.uValues and conf.uValues.count(',') + 1 == count:
|
||||
unionQuery += conf.uValues.split(',')[element]
|
||||
elif template is not None:
|
||||
unionQuery += query if template[element] == "%s" else template[element]
|
||||
elif element == position:
|
||||
unionQuery += query
|
||||
else:
|
||||
|
|
@ -985,7 +992,9 @@ class Agent(object):
|
|||
if element > 0:
|
||||
unionQuery += ','
|
||||
|
||||
if element == position:
|
||||
if template is not None:
|
||||
unionQuery += _collate(multipleUnions) if template[element] == "%s" else template[element]
|
||||
elif element == position:
|
||||
unionQuery += _collate(multipleUnions)
|
||||
else:
|
||||
unionQuery += char
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ from lib.core.enums import OS
|
|||
from thirdparty import six
|
||||
|
||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||
VERSION = "1.10.7.8"
|
||||
VERSION = "1.10.7.9"
|
||||
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
||||
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
|
||||
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
|
||||
|
|
@ -141,6 +141,9 @@ FUZZ_UNION_ERROR_REGEX = r"(?i)data\s?type|mismatch|comparable|compatible|conver
|
|||
# Upper threshold for starting the fuzz(y) UNION test
|
||||
FUZZ_UNION_MAX_COLUMNS = 10
|
||||
|
||||
# Maximum number of probe requests the fuzz(y) UNION test may issue (bounds its otherwise exponential type-combination search when run automatically)
|
||||
FUZZ_UNION_MAX_REQUESTS = 80
|
||||
|
||||
# Regular expression used for recognition of generic maximum connection messages
|
||||
MAX_CONNECTIONS_REGEX = r"\bmax.{1,100}\bconnection"
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ from lib.core.enums import FUZZ_UNION_COLUMN
|
|||
from lib.core.enums import PAYLOAD
|
||||
from lib.core.settings import FUZZ_UNION_ERROR_REGEX
|
||||
from lib.core.settings import FUZZ_UNION_MAX_COLUMNS
|
||||
from lib.core.settings import FUZZ_UNION_MAX_REQUESTS
|
||||
from lib.core.settings import LIMITED_ROWS_TEST_NUMBER
|
||||
from lib.core.settings import MAX_RATIO
|
||||
from lib.core.settings import MIN_RATIO
|
||||
|
|
@ -190,12 +191,14 @@ def _fuzzUnionCols(place, parameter, prefix, suffix):
|
|||
choices = getPublicTypeMembers(FUZZ_UNION_COLUMN, True)
|
||||
random.shuffle(choices)
|
||||
|
||||
attempts = 0
|
||||
for candidate in itertools.product(choices, repeat=kb.orderByColumns):
|
||||
if retVal:
|
||||
if retVal or attempts >= FUZZ_UNION_MAX_REQUESTS: # bound the exponential type-combination search
|
||||
break
|
||||
elif FUZZ_UNION_COLUMN.STRING not in candidate:
|
||||
continue
|
||||
else:
|
||||
attempts += 1
|
||||
candidate = [_.replace(FUZZ_UNION_COLUMN.INTEGER, str(randomInt())).replace(FUZZ_UNION_COLUMN.STRING, "'%s'" % randomStr(20)) for _ in candidate]
|
||||
|
||||
query = agent.prefixQuery("UNION ALL SELECT %s%s" % (','.join(candidate), FROM_DUMMY_TABLE.get(Backend.getIdentifiedDbms(), "")), prefix=prefix)
|
||||
|
|
@ -332,16 +335,21 @@ def _unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix)
|
|||
if Backend.getIdentifiedDbms() and kb.orderByColumns and kb.orderByColumns < FUZZ_UNION_MAX_COLUMNS:
|
||||
if kb.fuzzUnionTest is None:
|
||||
msg = "do you want to (re)try to find proper "
|
||||
msg += "UNION column types with fuzzy test? [y/N] "
|
||||
msg += "UNION column types with a fuzzy test? [Y/n] "
|
||||
|
||||
kb.fuzzUnionTest = readInput(msg, default='N', boolean=True)
|
||||
kb.fuzzUnionTest = readInput(msg, default='Y', boolean=True)
|
||||
if kb.fuzzUnionTest:
|
||||
kb.unionTemplate = _fuzzUnionCols(place, parameter, prefix, suffix)
|
||||
|
||||
# apply the discovered per-column type template through a normal confirmation so
|
||||
# the resulting vector (and later extraction) is built with type-compatible columns
|
||||
if kb.unionTemplate:
|
||||
validPayload, vector = _unionConfirm(comment, place, parameter, prefix, suffix, len(kb.unionTemplate))
|
||||
|
||||
warnMsg = "if UNION based SQL injection is not detected, "
|
||||
warnMsg += "please consider "
|
||||
|
||||
if not conf.uChar and count > 1 and kb.uChar == NULL and conf.uValues is None:
|
||||
if not all((validPayload, vector)) and not conf.uChar and count > 1 and kb.uChar == NULL and conf.uValues is None:
|
||||
message = "injection not exploitable with NULL values. Do you want to try with a random integer value for option '--union-char'? [Y/n] "
|
||||
|
||||
if not readInput(message, default='Y', boolean=True):
|
||||
|
|
@ -380,6 +388,8 @@ def unionTest(comment, place, parameter, value, prefix, suffix):
|
|||
negativeLogic = kb.negativeLogic
|
||||
setTechnique(PAYLOAD.TECHNIQUE.UNION)
|
||||
|
||||
kb.unionTemplate = None # reset any per-column type template carried over from a previous parameter
|
||||
|
||||
try:
|
||||
if negativeLogic:
|
||||
pushValue(kb.negativeLogic)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue