mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2024-11-26 03:23: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 isTechniqueAvailable
|
||||||
from lib.core.common import randomInt
|
from lib.core.common import randomInt
|
||||||
from lib.core.common import randomStr
|
from lib.core.common import randomStr
|
||||||
|
from lib.core.common import safeSQLIdentificatorNaming
|
||||||
from lib.core.common import singleTimeWarnMessage
|
from lib.core.common import singleTimeWarnMessage
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import queries
|
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.dicts import FROM_DUMMY_TABLE
|
||||||
from lib.core.enums import DBMS
|
from lib.core.enums import DBMS
|
||||||
from lib.core.enums import PAYLOAD
|
from lib.core.enums import PAYLOAD
|
||||||
|
@ -463,6 +465,25 @@ class Agent(object):
|
||||||
rootQuery = queries[Backend.getIdentifiedDbms()]
|
rootQuery = queries[Backend.getIdentifiedDbms()]
|
||||||
return rootQuery.concatenate.query % (first, second)
|
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):
|
def concatQuery(self, query, unpack=True):
|
||||||
"""
|
"""
|
||||||
Take in input a query string and return its processed nulled,
|
Take in input a query string and return its processed nulled,
|
||||||
|
|
|
@ -205,3 +205,8 @@ POST_HINT_CONTENT_TYPES = {
|
||||||
DEPRECATED_HINTS = {
|
DEPRECATED_HINTS = {
|
||||||
"--replicate": "use '--dump-format=SQLITE' instead",
|
"--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 extra.safe2bin.safe2bin import safechardecode
|
||||||
|
from lib.core.agent import agent
|
||||||
from lib.core.bigarray import BigArray
|
from lib.core.bigarray import BigArray
|
||||||
from lib.core.common import Backend
|
from lib.core.common import Backend
|
||||||
from lib.core.common import isNoneValue
|
from lib.core.common import isNoneValue
|
||||||
|
@ -101,9 +102,9 @@ def pivotDumpTable(table, colList, count=None, blind=True):
|
||||||
for column in colList:
|
for column in colList:
|
||||||
def _(pivotValue):
|
def _(pivotValue):
|
||||||
if column == colList[0]:
|
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:
|
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))
|
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
|
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.bigarray import BigArray
|
||||||
from lib.core.common import Backend
|
from lib.core.common import Backend
|
||||||
from lib.core.common import clearConsoleLine
|
from lib.core.common import clearConsoleLine
|
||||||
|
@ -117,17 +120,23 @@ class Entries:
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
colList = sorted(filter(None, kb.data.cachedColumns[safeSQLIdentificatorNaming(conf.db)][safeSQLIdentificatorNaming(tbl, True)].keys()))
|
columns = kb.data.cachedColumns[safeSQLIdentificatorNaming(conf.db)][safeSQLIdentificatorNaming(tbl, True)]
|
||||||
colString = ", ".join(column for column in colList)
|
colList = sorted(filter(None, columns.keys()))
|
||||||
|
colNames = colString = ", ".join(column for column in colList)
|
||||||
rootQuery = queries[Backend.getIdentifiedDbms()].dump_table
|
rootQuery = queries[Backend.getIdentifiedDbms()].dump_table
|
||||||
|
|
||||||
infoMsg = "fetching entries"
|
infoMsg = "fetching entries"
|
||||||
if conf.col:
|
if conf.col:
|
||||||
infoMsg += " of column(s) '%s'" % colString
|
infoMsg += " of column(s) '%s'" % colNames
|
||||||
infoMsg += " for table '%s'" % unsafeSQLIdentificatorNaming(tbl)
|
infoMsg += " for table '%s'" % unsafeSQLIdentificatorNaming(tbl)
|
||||||
infoMsg += " in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
|
infoMsg += " in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
for column in colList:
|
||||||
|
_ = agent.preprocessField(tbl, column)
|
||||||
|
if _ != column:
|
||||||
|
colString = re.sub(r"\b%s\b" % column, _, colString)
|
||||||
|
|
||||||
entriesCount = 0
|
entriesCount = 0
|
||||||
|
|
||||||
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
|
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:
|
if not kb.data.dumpedTable and isInferenceAvailable() and not conf.direct:
|
||||||
infoMsg = "fetching number of "
|
infoMsg = "fetching number of "
|
||||||
if conf.col:
|
if conf.col:
|
||||||
infoMsg += "column(s) '%s' " % colString
|
infoMsg += "column(s) '%s' " % colNames
|
||||||
infoMsg += "entries for table '%s' " % unsafeSQLIdentificatorNaming(tbl)
|
infoMsg += "entries for table '%s' " % unsafeSQLIdentificatorNaming(tbl)
|
||||||
infoMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
|
infoMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
@ -224,7 +233,7 @@ class Entries:
|
||||||
elif not isNumPosStrValue(count):
|
elif not isNumPosStrValue(count):
|
||||||
warnMsg = "unable to retrieve the number of "
|
warnMsg = "unable to retrieve the number of "
|
||||||
if conf.col:
|
if conf.col:
|
||||||
warnMsg += "column(s) '%s' " % colString
|
warnMsg += "column(s) '%s' " % colNames
|
||||||
warnMsg += "entries for table '%s' " % unsafeSQLIdentificatorNaming(tbl)
|
warnMsg += "entries for table '%s' " % unsafeSQLIdentificatorNaming(tbl)
|
||||||
warnMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
|
warnMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
@ -269,16 +278,16 @@ class Entries:
|
||||||
entries[column] = BigArray()
|
entries[column] = BigArray()
|
||||||
|
|
||||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
|
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):
|
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())),
|
tbl.upper() if not conf.db else ("%s.%s" % (conf.db.upper(), tbl.upper())),
|
||||||
index)
|
index)
|
||||||
elif Backend.isDbms(DBMS.SQLITE):
|
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):
|
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 = NULL if column in emptyColumns else inject.getValue(query, union=False, error=False, dump=True)
|
||||||
value = '' if value is None else value
|
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):
|
if len(kb.data.dumpedTable) == 0 or (entriesCount == 0 and kb.permissionFlag):
|
||||||
warnMsg = "unable to retrieve the entries "
|
warnMsg = "unable to retrieve the entries "
|
||||||
if conf.col:
|
if conf.col:
|
||||||
warnMsg += "of columns '%s' " % colString
|
warnMsg += "of columns '%s' " % colNames
|
||||||
warnMsg += "for table '%s' " % unsafeSQLIdentificatorNaming(tbl)
|
warnMsg += "for table '%s' " % unsafeSQLIdentificatorNaming(tbl)
|
||||||
warnMsg += "in database '%s'%s" % (unsafeSQLIdentificatorNaming(conf.db), " (permission denied)" if kb.permissionFlag else "")
|
warnMsg += "in database '%s'%s" % (unsafeSQLIdentificatorNaming(conf.db), " (permission denied)" if kb.permissionFlag else "")
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
|
@ -274,7 +274,7 @@
|
||||||
</columns>
|
</columns>
|
||||||
<dump_table>
|
<dump_table>
|
||||||
<inband query="SELECT %s FROM %s"/>
|
<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>
|
</dump_table>
|
||||||
<!-- NOTE: in Oracle schema names are the counterpart to database names on other DBMSes -->
|
<!-- NOTE: in Oracle schema names are the counterpart to database names on other DBMSes -->
|
||||||
<search_db>
|
<search_db>
|
||||||
|
@ -608,7 +608,7 @@
|
||||||
</columns>
|
</columns>
|
||||||
<dump_table>
|
<dump_table>
|
||||||
<inband query="SELECT %s FROM %s"/>
|
<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>
|
</dump_table>
|
||||||
<search_db>
|
<search_db>
|
||||||
<inband query="SELECT schemaname FROM syscat.schemata WHERE " condition="schemaname"/>
|
<inband query="SELECT schemaname FROM syscat.schemata WHERE " condition="schemaname"/>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user