mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-02-03 13:14:13 +03:00
implementation of MySQL GROUP_CONCAT technique
This commit is contained in:
parent
808b03fc3e
commit
199f14df46
|
@ -1121,6 +1121,7 @@ def __cleanupOptions():
|
||||||
conf.keepAlive = True
|
conf.keepAlive = True
|
||||||
conf.nullConnection = not conf.textOnly
|
conf.nullConnection = not conf.textOnly
|
||||||
conf.threads = 4 if conf.threads < 4 else conf.threads
|
conf.threads = 4 if conf.threads < 4 else conf.threads
|
||||||
|
conf.groupConcat = True
|
||||||
|
|
||||||
if conf.tor:
|
if conf.tor:
|
||||||
conf.proxy = DEFAULT_TOR_PROXY
|
conf.proxy = DEFAULT_TOR_PROXY
|
||||||
|
|
|
@ -58,6 +58,10 @@ PAYLOAD_DELIMITER = "\x00"
|
||||||
CHAR_INFERENCE_MARK = "%c"
|
CHAR_INFERENCE_MARK = "%c"
|
||||||
NON_CONTROL_CHAR_REGEX = r'[^\x00-\x1f]'
|
NON_CONTROL_CHAR_REGEX = r'[^\x00-\x1f]'
|
||||||
|
|
||||||
|
# dumping characters used in GROUP_CONCAT MySQL technique
|
||||||
|
CONCAT_ROW_DELIMITER = ','
|
||||||
|
CONCAT_VALUE_DELIMITER = '|'
|
||||||
|
|
||||||
# coefficient used for a time-based query delay checking (must be >= 7)
|
# coefficient used for a time-based query delay checking (must be >= 7)
|
||||||
TIME_STDEV_COEFF = 10
|
TIME_STDEV_COEFF = 10
|
||||||
|
|
||||||
|
|
|
@ -149,6 +149,9 @@ def cmdLineParser():
|
||||||
help="Max number of concurrent HTTP(s) "
|
help="Max number of concurrent HTTP(s) "
|
||||||
"requests (default 1)")
|
"requests (default 1)")
|
||||||
|
|
||||||
|
optimization.add_option("--group-concat", dest="groupConcat", action="store_true",
|
||||||
|
default=False, help="Use GROUP_CONCAT MySQL technique in dumping phase")
|
||||||
|
|
||||||
# Injection options
|
# Injection options
|
||||||
injection = OptionGroup(parser, "Injection", "These options can be "
|
injection = OptionGroup(parser, "Injection", "These options can be "
|
||||||
"used to specify which parameters to test "
|
"used to specify which parameters to test "
|
||||||
|
|
|
@ -45,6 +45,8 @@ from lib.core.exception import sqlmapNoneDataException
|
||||||
from lib.core.exception import sqlmapUnsupportedFeatureException
|
from lib.core.exception import sqlmapUnsupportedFeatureException
|
||||||
from lib.core.exception import sqlmapUserQuitException
|
from lib.core.exception import sqlmapUserQuitException
|
||||||
from lib.core.session import setOs
|
from lib.core.session import setOs
|
||||||
|
from lib.core.settings import CONCAT_ROW_DELIMITER
|
||||||
|
from lib.core.settings import CONCAT_VALUE_DELIMITER
|
||||||
from lib.core.settings import SQL_STATEMENTS
|
from lib.core.settings import SQL_STATEMENTS
|
||||||
from lib.core.shell import autoCompletion
|
from lib.core.shell import autoCompletion
|
||||||
from lib.core.unescaper import unescaper
|
from lib.core.unescaper import unescaper
|
||||||
|
@ -1193,13 +1195,31 @@ class Enumeration:
|
||||||
entriesCount = 0
|
entriesCount = 0
|
||||||
|
|
||||||
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
|
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
|
||||||
|
entries = []
|
||||||
|
|
||||||
|
if Backend.getIdentifiedDbms() == DBMS.MYSQL and isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) and conf.groupConcat:
|
||||||
|
randStr, randStr2 = randomStr(), randomStr()
|
||||||
|
filterFunction = "REPLACE(REPLACE(IFNULL(%s, ' '),'%s','%s'),'%s','%s')"\
|
||||||
|
% ('%s', CONCAT_VALUE_DELIMITER, randStr, CONCAT_ROW_DELIMITER, randStr2)
|
||||||
|
concats = ",".join(map(lambda x: "CONCAT(%s, '|')" % (filterFunction % x), colList[:-1]))
|
||||||
|
concats += ",%s" % (filterFunction % colList[-1])
|
||||||
|
query = "SELECT GROUP_CONCAT(%s) FROM %s.%s" % (concats, conf.db, conf.tbl)
|
||||||
|
value = inject.getValue(query, blind=False)
|
||||||
|
if isinstance(value, basestring):
|
||||||
|
for line in value.split(CONCAT_ROW_DELIMITER):
|
||||||
|
row = line.split(CONCAT_VALUE_DELIMITER)
|
||||||
|
row = filter(lambda x: x.replace(randStr, CONCAT_VALUE_DELIMITER).replace(randStr2, CONCAT_ROW_DELIMITER), row)
|
||||||
|
entries.append(row)
|
||||||
|
|
||||||
if Backend.getIdentifiedDbms() == DBMS.ORACLE:
|
if Backend.getIdentifiedDbms() == DBMS.ORACLE:
|
||||||
query = rootQuery.inband.query % (colString, conf.tbl.upper() if not conf.db else ("%s.%s" % (conf.db.upper(), conf.tbl.upper())))
|
query = rootQuery.inband.query % (colString, conf.tbl.upper() if not conf.db else ("%s.%s" % (conf.db.upper(), conf.tbl.upper())))
|
||||||
elif Backend.getIdentifiedDbms() == DBMS.SQLITE:
|
elif Backend.getIdentifiedDbms() == DBMS.SQLITE:
|
||||||
query = rootQuery.inband.query % (colString, conf.tbl)
|
query = rootQuery.inband.query % (colString, conf.tbl)
|
||||||
else:
|
else:
|
||||||
query = rootQuery.inband.query % (colString, conf.db, conf.tbl)
|
query = rootQuery.inband.query % (colString, conf.db, conf.tbl)
|
||||||
entries = inject.getValue(query, blind=False, dump=True)
|
|
||||||
|
if not (Backend.getIdentifiedDbms() == DBMS.MYSQL and entries):
|
||||||
|
entries = inject.getValue(query, blind=False, dump=True)
|
||||||
|
|
||||||
if entries:
|
if entries:
|
||||||
if isinstance(entries, basestring):
|
if isinstance(entries, basestring):
|
||||||
|
|
|
@ -149,6 +149,10 @@ nullConnection = False
|
||||||
# Default: 1
|
# Default: 1
|
||||||
threads = 1
|
threads = 1
|
||||||
|
|
||||||
|
# Use GROUP_CONCAT MySQL technique in dumping phase.
|
||||||
|
# Valid: True or False
|
||||||
|
groupConcat = False
|
||||||
|
|
||||||
|
|
||||||
# These options can be used to specify which parameters to test for,
|
# These options can be used to specify which parameters to test for,
|
||||||
# provide custom injection payloads and optional tampering scripts.
|
# provide custom injection payloads and optional tampering scripts.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user