diff --git a/lib/core/agent.py b/lib/core/agent.py
index 6b56b8ef0..edc6530ab 100644
--- a/lib/core/agent.py
+++ b/lib/core/agent.py
@@ -15,10 +15,12 @@ from lib.core.common import isNumber
from lib.core.common import isTechniqueAvailable
from lib.core.common import randomInt
from lib.core.common import randomStr
+from lib.core.common import safeSQLIdentificatorNaming
from lib.core.common import singleTimeWarnMessage
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import queries
+from lib.core.dicts import DUMP_DATA_PREPROCESS
from lib.core.dicts import FROM_DUMMY_TABLE
from lib.core.enums import DBMS
from lib.core.enums import PAYLOAD
@@ -463,6 +465,25 @@ class Agent(object):
rootQuery = queries[Backend.getIdentifiedDbms()]
return rootQuery.concatenate.query % (first, second)
+ def preprocessField(self, table, field):
+ """
+ Does a field preprocessing (if needed) based on it's type (e.g. image to text)
+ Note: used primarily in dumping of custom tables
+ """
+
+ retVal = field
+ if conf.db in table:
+ table = table.split(conf.db)[-1].strip('.')
+ try:
+ columns = kb.data.cachedColumns[safeSQLIdentificatorNaming(conf.db)][safeSQLIdentificatorNaming(table, True)]
+ for name, type_ in columns.items():
+ if type_ and type_.upper() in DUMP_DATA_PREPROCESS.get(Backend.getDbms(), {}) and name == field:
+ retVal = DUMP_DATA_PREPROCESS[Backend.getDbms()][type_.upper()] % name
+ break
+ except KeyError:
+ pass
+ return retVal
+
def concatQuery(self, query, unpack=True):
"""
Take in input a query string and return its processed nulled,
diff --git a/lib/core/dicts.py b/lib/core/dicts.py
index 926395d6a..acc2e338b 100644
--- a/lib/core/dicts.py
+++ b/lib/core/dicts.py
@@ -205,3 +205,8 @@ POST_HINT_CONTENT_TYPES = {
DEPRECATED_HINTS = {
"--replicate": "use '--dump-format=SQLITE' instead",
}
+
+DUMP_DATA_PREPROCESS = {
+ DBMS.ORACLE: {"XMLTYPE": "(%s).getStringVal()"}, # Reference: https://www.tibcommunity.com/docs/DOC-3643
+ DBMS.MSSQL: {"IMAGE": "CONVERT(VARBINARY(MAX),%s)"},
+ }
diff --git a/lib/utils/pivotdumptable.py b/lib/utils/pivotdumptable.py
index a48f87903..b93b7c30d 100644
--- a/lib/utils/pivotdumptable.py
+++ b/lib/utils/pivotdumptable.py
@@ -6,6 +6,7 @@ See the file 'doc/COPYING' for copying permission
"""
from extra.safe2bin.safe2bin import safechardecode
+from lib.core.agent import agent
from lib.core.bigarray import BigArray
from lib.core.common import Backend
from lib.core.common import isNoneValue
@@ -101,9 +102,9 @@ def pivotDumpTable(table, colList, count=None, blind=True):
for column in colList:
def _(pivotValue):
if column == colList[0]:
- query = dumpNode.query.replace("'%s'", "%s") % (column, table, column, unescaper.unescape(pivotValue, False))
+ query = dumpNode.query.replace("'%s'", "%s") % (agent.preprocessField(table, column), table, agent.preprocessField(table, column), unescaper.unescape(pivotValue, False))
else:
- query = dumpNode.query2.replace("'%s'", "%s") % (column, table, colList[0], unescaper.unescape(pivotValue, False))
+ query = dumpNode.query2.replace("'%s'", "%s") % (agent.preprocessField(table, column), table, agent.preprocessField(table, colList[0]), unescaper.unescape(pivotValue, False))
return unArrayizeValue(inject.getValue(query, blind=blind, time=blind, union=not blind, error=not blind))
diff --git a/plugins/generic/entries.py b/plugins/generic/entries.py
index 5586b6d51..659f9cdda 100644
--- a/plugins/generic/entries.py
+++ b/plugins/generic/entries.py
@@ -5,6 +5,9 @@ Copyright (c) 2006-2012 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
+import re
+
+from lib.core.agent import agent
from lib.core.bigarray import BigArray
from lib.core.common import Backend
from lib.core.common import clearConsoleLine
@@ -117,17 +120,23 @@ class Entries:
continue
- colList = sorted(filter(None, kb.data.cachedColumns[safeSQLIdentificatorNaming(conf.db)][safeSQLIdentificatorNaming(tbl, True)].keys()))
- colString = ", ".join(column for column in colList)
+ columns = kb.data.cachedColumns[safeSQLIdentificatorNaming(conf.db)][safeSQLIdentificatorNaming(tbl, True)]
+ colList = sorted(filter(None, columns.keys()))
+ colNames = colString = ", ".join(column for column in colList)
rootQuery = queries[Backend.getIdentifiedDbms()].dump_table
infoMsg = "fetching entries"
if conf.col:
- infoMsg += " of column(s) '%s'" % colString
+ infoMsg += " of column(s) '%s'" % colNames
infoMsg += " for table '%s'" % unsafeSQLIdentificatorNaming(tbl)
infoMsg += " in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
logger.info(infoMsg)
+ for column in colList:
+ _ = agent.preprocessField(tbl, column)
+ if _ != column:
+ colString = re.sub(r"\b%s\b" % column, _, colString)
+
entriesCount = 0
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
@@ -190,7 +199,7 @@ class Entries:
if not kb.data.dumpedTable and isInferenceAvailable() and not conf.direct:
infoMsg = "fetching number of "
if conf.col:
- infoMsg += "column(s) '%s' " % colString
+ infoMsg += "column(s) '%s' " % colNames
infoMsg += "entries for table '%s' " % unsafeSQLIdentificatorNaming(tbl)
infoMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
logger.info(infoMsg)
@@ -224,7 +233,7 @@ class Entries:
elif not isNumPosStrValue(count):
warnMsg = "unable to retrieve the number of "
if conf.col:
- warnMsg += "column(s) '%s' " % colString
+ warnMsg += "column(s) '%s' " % colNames
warnMsg += "entries for table '%s' " % unsafeSQLIdentificatorNaming(tbl)
warnMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
logger.warn(warnMsg)
@@ -269,16 +278,16 @@ class Entries:
entries[column] = BigArray()
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
- query = rootQuery.blind.query % (column, conf.db, conf.tbl, sorted(colList, key=len)[0], index)
+ query = rootQuery.blind.query % (agent.preprocessField(tbl, column), conf.db, conf.tbl, sorted(colList, key=len)[0], index)
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
- query = rootQuery.blind.query % (column, column,
+ query = rootQuery.blind.query % (agent.preprocessField(tbl, column),
tbl.upper() if not conf.db else ("%s.%s" % (conf.db.upper(), tbl.upper())),
index)
elif Backend.isDbms(DBMS.SQLITE):
- query = rootQuery.blind.query % (column, tbl, index)
+ query = rootQuery.blind.query % (agent.preprocessField(tbl, column), tbl, index)
elif Backend.isDbms(DBMS.FIREBIRD):
- query = rootQuery.blind.query % (index, column, tbl)
+ query = rootQuery.blind.query % (index, agent.preprocessField(tbl, column), tbl)
value = NULL if column in emptyColumns else inject.getValue(query, union=False, error=False, dump=True)
value = '' if value is None else value
@@ -302,7 +311,7 @@ class Entries:
if len(kb.data.dumpedTable) == 0 or (entriesCount == 0 and kb.permissionFlag):
warnMsg = "unable to retrieve the entries "
if conf.col:
- warnMsg += "of columns '%s' " % colString
+ warnMsg += "of columns '%s' " % colNames
warnMsg += "for table '%s' " % unsafeSQLIdentificatorNaming(tbl)
warnMsg += "in database '%s'%s" % (unsafeSQLIdentificatorNaming(conf.db), " (permission denied)" if kb.permissionFlag else "")
logger.warn(warnMsg)
diff --git a/xml/queries.xml b/xml/queries.xml
index 917a865d2..c40c76798 100644
--- a/xml/queries.xml
+++ b/xml/queries.xml
@@ -274,7 +274,7 @@
-
+
@@ -608,7 +608,7 @@
-
+