mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2024-11-25 19:13:48 +03:00
Implementation for an Issue #340
This commit is contained in:
parent
3f84cefc77
commit
7a1d484115
|
@ -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,
|
||||
|
|
|
@ -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)"},
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -274,7 +274,7 @@
|
|||
</columns>
|
||||
<dump_table>
|
||||
<inband query="SELECT %s FROM %s"/>
|
||||
<blind query="SELECT %s FROM (SELECT %s,ROWNUM AS LIMIT FROM %s) WHERE LIMIT=%d" count="SELECT COUNT(*) FROM %s"/>
|
||||
<blind query="SELECT ENTRY_VALUE FROM (SELECT %s AS ENTRY_VALUE,ROWNUM AS LIMIT FROM %s) WHERE LIMIT=%d" count="SELECT COUNT(*) FROM %s"/>
|
||||
</dump_table>
|
||||
<!-- NOTE: in Oracle schema names are the counterpart to database names on other DBMSes -->
|
||||
<search_db>
|
||||
|
@ -608,7 +608,7 @@
|
|||
</columns>
|
||||
<dump_table>
|
||||
<inband query="SELECT %s FROM %s"/>
|
||||
<blind query="SELECT %s FROM (SELECT ROW_NUMBER() OVER () AS LIMIT,%s FROM %s) AS foobar WHERE LIMIT=%d" count="SELECT COUNT(*) FROM %s"/>
|
||||
<blind query="SELECT ENTRY_VALUE FROM (SELECT ROW_NUMBER() OVER () AS LIMIT,%s AS ENTRY_VALUE FROM %s) AS foobar WHERE LIMIT=%d" count="SELECT COUNT(*) FROM %s"/>
|
||||
</dump_table>
|
||||
<search_db>
|
||||
<inband query="SELECT schemaname FROM syscat.schemata WHERE " condition="schemaname"/>
|
||||
|
|
Loading…
Reference in New Issue
Block a user