implementation of MySQL GROUP_CONCAT technique

This commit is contained in:
Miroslav Stampar 2011-02-15 00:28:27 +00:00
parent 808b03fc3e
commit 199f14df46
5 changed files with 33 additions and 1 deletions

View File

@ -1121,6 +1121,7 @@ def __cleanupOptions():
conf.keepAlive = True
conf.nullConnection = not conf.textOnly
conf.threads = 4 if conf.threads < 4 else conf.threads
conf.groupConcat = True
if conf.tor:
conf.proxy = DEFAULT_TOR_PROXY

View File

@ -58,6 +58,10 @@ PAYLOAD_DELIMITER = "\x00"
CHAR_INFERENCE_MARK = "%c"
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)
TIME_STDEV_COEFF = 10

View File

@ -149,6 +149,9 @@ def cmdLineParser():
help="Max number of concurrent HTTP(s) "
"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 = OptionGroup(parser, "Injection", "These options can be "
"used to specify which parameters to test "

View File

@ -45,6 +45,8 @@ from lib.core.exception import sqlmapNoneDataException
from lib.core.exception import sqlmapUnsupportedFeatureException
from lib.core.exception import sqlmapUserQuitException
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.shell import autoCompletion
from lib.core.unescaper import unescaper
@ -1193,13 +1195,31 @@ class Enumeration:
entriesCount = 0
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:
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:
query = rootQuery.inband.query % (colString, conf.tbl)
else:
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 isinstance(entries, basestring):

View File

@ -149,6 +149,10 @@ nullConnection = False
# Default: 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,
# provide custom injection payloads and optional tampering scripts.