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.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.data import conf
from lib.core.data import kb
@@ -30,8 +31,8 @@ def action():
# system to be able to go ahead with the injection
setHandler()
if not kb.dbmsDetected or not conf.dbmsHandler:
htmlParsed = getErrorParsedDBMSesFormatted()
if not backend.getDbms() or not conf.dbmsHandler:
htmlParsed = format.getErrorParsedDBMSes()
errMsg = "sqlmap was not able to fingerprint the "
errMsg += "back-end database management system"

View File

@@ -13,15 +13,14 @@ import time
from lib.core.agent import agent
from lib.core.common import aliasToDbmsEnum
from lib.core.common import backend
from lib.core.common import beep
from lib.core.common import extractRegexResult
from lib.core.common import findDynamicContent
from lib.core.common import format
from lib.core.common import getComparePageRatio
from lib.core.common import getCompiledRegex
from lib.core.common import getErrorParsedDBMSes
from lib.core.common import getErrorParsedDBMSesFormatted
from lib.core.common import getIdentifiedDBMS
from lib.core.common import getInjectionTests
from lib.core.common import getSortedInjectionTests
from lib.core.common import getUnicode
from lib.core.common import popValue
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.session import setDynamicMarkings
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.threads import getCurrentThreadData
from lib.core.unescaper import unescaper
@@ -78,8 +78,8 @@ def unescapeDbms(payload, injection, dbms):
payload = unescape(payload, dbms=dbms)
elif conf.dbms is not None:
payload = unescape(payload, dbms=conf.dbms)
elif getIdentifiedDBMS() is not None:
payload = unescape(payload, dbms=getIdentifiedDBMS())
elif backend.getIdentifiedDbms() is not None:
payload = unescape(payload, dbms=backend.getIdentifiedDbms())
return payload
@@ -91,7 +91,7 @@ def checkSqlInjection(place, parameter, value):
# Set the flag for sql injection test mode
kb.testMode = True
for test in getInjectionTests():
for test in getSortedInjectionTests():
try:
if kb.endDetection:
break
@@ -164,19 +164,19 @@ def checkSqlInjection(place, parameter, value):
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 += "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]"
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:
debugMsg = "skipping test '%s' because " % title
debugMsg += "the parsed error message(s) showed "
debugMsg += "that the back-end DBMS could be "
debugMsg += "%s" % getErrorParsedDBMSesFormatted()
debugMsg += "%s" % format.getErrorParsedDBMSes()
logger.debug(debugMsg)
continue
@@ -395,7 +395,7 @@ def checkSqlInjection(place, parameter, value):
# Force back-end DBMS according to the current
# test value for proper payload unescaping
kb.misc.forcedDbms = dbms
backend.forceDbms(dbms)
# Skip test if the user provided custom column
# 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)
if not getIdentifiedDBMS():
if not backend.getIdentifiedDbms():
warnMsg = "using unescaped version of the test "
warnMsg += "because of zero knowledge of the "
warnMsg += "back-end DBMS"
@@ -426,8 +426,8 @@ def checkSqlInjection(place, parameter, value):
# by unionTest() directly
where = vector[6]
# Reset back-end DBMS value
kb.misc.forcedDbms = None
# Reset forced back-end DBMS value
backend.flushForcedDbms()
# If the injection test was successful feed the injection
# object with the test's details
@@ -481,7 +481,7 @@ def checkSqlInjection(place, parameter, value):
if inp == injection.dbms:
break
elif inp == dValue:
kb.dbms = aliasToDbmsEnum(inp)
backend.setDbms(inp)
injection.dbms = aliasToDbmsEnum(inp)
injection.dbms_version = None
break
@@ -489,10 +489,10 @@ def checkSqlInjection(place, parameter, value):
warnMsg = "invalid value"
logger.warn(warnMsg)
elif dKey == "dbms" and injection.dbms is None:
kb.dbms = aliasToDbmsEnum(dValue)
backend.setDbms(dValue)
injection.dbms = aliasToDbmsEnum(dValue)
elif dKey == "dbms_version" and injection.dbms_version is None:
kb.dbmsVersion = [ dValue ]
backend.setVersion(dValue)
injection.dbms_version = dValue
elif dKey == "os" and injection.os is None:
injection.os = dValue
@@ -558,7 +558,7 @@ def heuristicCheckSqlInjection(place, parameter):
infoMsg += "parameter '%s' might " % parameter
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)
else:
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
"""
from lib.core.common import getIdentifiedDBMS
from lib.core.common import backend
from lib.core.common import popValue
from lib.core.common import pushValue
from lib.core.data import conf
@@ -63,11 +63,11 @@ def setHandler():
( SYBASE_ALIASES, SybaseMap, SybaseConn ),
]
if getIdentifiedDBMS() is not None:
if backend.getIdentifiedDbms() is not None:
for i in xrange(len(dbmsObj)):
dbmsAliases, _, _ = dbmsObj[i]
if getIdentifiedDBMS().lower() in dbmsAliases:
if backend.getIdentifiedDbms().lower() in dbmsAliases:
if i > 0:
pushValue(dbmsObj[i])
dbmsObj.remove(dbmsObj[i])
@@ -94,12 +94,12 @@ def setHandler():
conf.dbmsConnector.connect()
if handler.checkDbms():
kb.dbmsDetected = True
conf.dbmsHandler = handler
break
else:
conf.dbmsConnector = None
# At this point proper back-end DBMS is fingerprinted (kb.dbms)
kb.misc.forcedDbms = None
# At this point back-end DBMS is correctly fingerprinted, no need
# to enforce it anymore
backend.flushForcedDbms()

View File

@@ -11,9 +11,8 @@ import re
from xml.etree import ElementTree as ET
from lib.core.common import backend
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 isTechniqueAvailable
from lib.core.common import randomInt
@@ -206,8 +205,8 @@ class Agent:
payload = payload.replace("[ORIGVALUE]", origvalue)
if "[INFERENCE]" in payload:
if getIdentifiedDBMS() is not None:
inference = queries[getIdentifiedDBMS()].inference
if backend.getIdentifiedDbms() is not None:
inference = queries[backend.getIdentifiedDbms()].inference
if "dbms_version" in inference:
if isDBMSVersionAtLeast(inference.dbms_version):
@@ -265,17 +264,17 @@ class Agent:
# SQLite version 2 does not support neither CAST() nor IFNULL(),
# introduced only in SQLite version 3
if getIdentifiedDBMS() == DBMS.SQLITE:
if backend.getIdentifiedDbms() == DBMS.SQLITE:
return field
if field.startswith("(CASE"):
nulledCastedField = field
else:
nulledCastedField = queries[getIdentifiedDBMS()].cast.query % field
if getIdentifiedDBMS() == DBMS.ACCESS:
nulledCastedField = queries[getIdentifiedDBMS()].isnull.query % (nulledCastedField, nulledCastedField)
nulledCastedField = queries[backend.getIdentifiedDbms()].cast.query % field
if backend.getIdentifiedDbms() == DBMS.ACCESS:
nulledCastedField = queries[backend.getIdentifiedDbms()].isnull.query % (nulledCastedField, nulledCastedField)
else:
nulledCastedField = queries[getIdentifiedDBMS()].isnull.query % nulledCastedField
nulledCastedField = queries[backend.getIdentifiedDbms()].isnull.query % nulledCastedField
return nulledCastedField
@@ -309,12 +308,12 @@ class Agent:
@rtype: C{str}
"""
if not kb.dbmsDetected:
if not backend.getDbms():
return fields
fields = fields.replace(", ", ",")
fieldsSplitted = fields.split(",")
dbmsDelimiter = queries[getIdentifiedDBMS()].delimiter.query
dbmsDelimiter = queries[backend.getIdentifiedDbms()].delimiter.query
nulledCastedFields = []
for field in fieldsSplitted:
@@ -377,13 +376,13 @@ class Agent:
def simpleConcatQuery(self, query1, query2):
concatenatedQuery = ""
if getIdentifiedDBMS() == DBMS.MYSQL:
if backend.getIdentifiedDbms() == DBMS.MYSQL:
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)
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
concatenatedQuery = "%s+%s" % (query1, query2)
return concatenatedQuery
@@ -425,7 +424,7 @@ class Agent:
concatenatedQuery = query
fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsSelectCase, _, fieldsToCastStr, fieldsExists = self.getFields(query)
if getIdentifiedDBMS() == DBMS.MYSQL:
if backend.getIdentifiedDbms() == DBMS.MYSQL:
if fieldsExists:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % kb.misc.start, 1)
concatenatedQuery += ",'%s')" % kb.misc.stop
@@ -438,7 +437,7 @@ class Agent:
elif fieldsNoSelect:
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:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.misc.start, 1)
concatenatedQuery += "||'%s'" % kb.misc.stop
@@ -451,10 +450,10 @@ class Agent:
elif fieldsNoSelect:
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"
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
if fieldsExists:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.misc.start, 1)
concatenatedQuery += "+'%s'" % kb.misc.stop
@@ -520,8 +519,8 @@ class Agent:
intoRegExp = intoRegExp.group(1)
query = query[:query.index(intoRegExp)]
if getIdentifiedDBMS() in FROM_TABLE and inbandQuery.endswith(FROM_TABLE[getIdentifiedDBMS()]):
inbandQuery = inbandQuery[:-len(FROM_TABLE[getIdentifiedDBMS()])]
if backend.getIdentifiedDbms() in FROM_TABLE and inbandQuery.endswith(FROM_TABLE[backend.getIdentifiedDbms()]):
inbandQuery = inbandQuery[:-len(FROM_TABLE[backend.getIdentifiedDbms()])]
for element in range(count):
if element > 0:
@@ -540,9 +539,9 @@ class Agent:
conditionIndex = query.index(" FROM ")
inbandQuery += query[conditionIndex:]
if getIdentifiedDBMS() in FROM_TABLE:
if backend.getIdentifiedDbms() in FROM_TABLE:
if " FROM " not in inbandQuery:
inbandQuery += FROM_TABLE[getIdentifiedDBMS()]
inbandQuery += FROM_TABLE[backend.getIdentifiedDbms()]
if intoRegExp:
inbandQuery += intoRegExp
@@ -559,8 +558,8 @@ class Agent:
else:
inbandQuery += char
if getIdentifiedDBMS() in FROM_TABLE:
inbandQuery += FROM_TABLE[getIdentifiedDBMS()]
if backend.getIdentifiedDbms() in FROM_TABLE:
inbandQuery += FROM_TABLE[backend.getIdentifiedDbms()]
inbandQuery = self.suffixQuery(inbandQuery, comment, suffix)
@@ -589,21 +588,21 @@ class Agent:
"""
limitedQuery = query
limitStr = queries[getIdentifiedDBMS()].limit.query
limitStr = queries[backend.getIdentifiedDbms()].limit.query
fromIndex = limitedQuery.index(" FROM ")
untilFrom = limitedQuery[:fromIndex]
fromFrom = limitedQuery[fromIndex+1:]
orderBy = False
if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE):
limitStr = queries[getIdentifiedDBMS()].limit.query % (num, 1)
if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE):
limitStr = queries[backend.getIdentifiedDbms()].limit.query % (num, 1)
limitedQuery += " %s" % limitStr
elif getIdentifiedDBMS() == DBMS.FIREBIRD:
limitStr = queries[getIdentifiedDBMS()].limit.query % (num+1, num+1)
elif backend.getIdentifiedDbms() == DBMS.FIREBIRD:
limitStr = queries[backend.getIdentifiedDbms()].limit.query % (num+1, num+1)
limitedQuery += " %s" % limitStr
elif getIdentifiedDBMS() == DBMS.ORACLE:
elif backend.getIdentifiedDbms() == DBMS.ORACLE:
if " ORDER BY " in limitedQuery and "(SELECT " in limitedQuery:
orderBy = limitedQuery[limitedQuery.index(" ORDER BY "):]
limitedQuery = limitedQuery[:limitedQuery.index(" ORDER BY ")]
@@ -615,7 +614,7 @@ class Agent:
limitedQuery = limitedQuery % fromFrom
limitedQuery += "=%d" % (num + 1)
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
forgeNotIn = True
if " ORDER BY " in limitedQuery:
@@ -629,7 +628,7 @@ class Agent:
limitedQuery = limitedQuery.replace("DISTINCT %s" % notDistinct, notDistinct)
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:
topNums = topNums.groups()
@@ -675,8 +674,8 @@ class Agent:
@rtype: C{str}
"""
if getIdentifiedDBMS() is not None and hasattr(queries[getIdentifiedDBMS()], "case"):
return queries[getIdentifiedDBMS()].case.query % expression
if backend.getIdentifiedDbms() is not None and hasattr(queries[backend.getIdentifiedDbms()], "case"):
return queries[backend.getIdentifiedDbms()].case.query % expression
else:
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_STDEV_COEFF
from lib.core.settings import DYNAMICITY_MARK_LENGTH
from lib.core.settings import UNKNOWN_DBMS_VERSION
from lib.core.threads import getCurrentThreadData
class UnicodeRawConfigParser(RawConfigParser):
"""
RawConfigParser with unicode writing support
"""
def write(self, fp):
"""
Write an .ini-format representation of the configuration state.
@@ -109,10 +111,10 @@ class UnicodeRawConfigParser(RawConfigParser):
fp.write("\n")
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):
@@ -121,7 +123,6 @@ class DynamicContentItem:
self.lineContentBefore = lineContentBefore
self.lineContentAfter = lineContentAfter
def paramToDict(place, parameters=None):
"""
Split the parameters into names and values, check if these parameters
@@ -203,110 +204,6 @@ def paramToDict(place, parameters=None):
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):
docRoot = None
pagePath = directoryPath(conf.path)
@@ -626,14 +523,14 @@ def parsePasswordHash(password):
if not password or password == " ":
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
password = "%s\n" % hexPassword
password += "%sheader: %s\n" % (blank, hexPassword[:6])
password += "%ssalt: %s\n" % (blank, hexPassword[6:14])
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:])
return password
@@ -927,25 +824,25 @@ def parseUnionPage(output, expression, partial=False, condition=None, sort=True)
def getDelayQuery(andCond=False):
query = None
if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL):
if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
if not kb.data.banner:
conf.dbmsHandler.getVersionFromBanner()
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"):
query = queries[getIdentifiedDBMS()].timedelay.query % conf.timeSec
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[backend.getIdentifiedDbms()].timedelay.query % conf.timeSec
else:
query = queries[getIdentifiedDBMS()].timedelay.query2 % conf.timeSec
elif getIdentifiedDBMS() == DBMS.FIREBIRD:
query = queries[getIdentifiedDBMS()].timedelay.query
query = queries[backend.getIdentifiedDbms()].timedelay.query2 % conf.timeSec
elif backend.getIdentifiedDbms() == DBMS.FIREBIRD:
query = queries[backend.getIdentifiedDbms()].timedelay.query
else:
query = queries[getIdentifiedDBMS()].timedelay.query % conf.timeSec
query = queries[backend.getIdentifiedDbms()].timedelay.query % conf.timeSec
if andCond:
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.SQLITE ):
if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.SQLITE ):
query = query.replace("SELECT ", "")
elif getIdentifiedDBMS() == DBMS.FIREBIRD:
elif backend.getIdentifiedDbms() == DBMS.FIREBIRD:
query = "(%s)>0" % query
return query
@@ -1524,7 +1421,6 @@ def getUnicode(value, encoding=None):
else:
return unicode(value) # encoding ignored for non-basestring instances
# http://boredzo.org/blog/archives/2007-01-06/longest-common-prefix-in-python-2
def longestCommonPrefix(*sequences):
if len(sequences) == 1:
@@ -1902,8 +1798,8 @@ def isDBMSVersionAtLeast(version):
retVal = None
if kb.dbmsVersion and kb.dbmsVersion[0] != UNKNOWN_DBMS_VERSION and kb.dbmsVersion[0] != None:
value = kb.dbmsVersion[0].replace(" ", "").rstrip('.')
if backend.getVersion() and backend.getVersion() != UNKNOWN_DBMS_VERSION:
value = backend.getVersion().replace(" ", "").rstrip('.')
while True:
index = value.find('.', value.find('.') + 1)
@@ -2004,7 +1900,7 @@ def arrayizeValue(value):
return value
def getInjectionTests():
def getSortedInjectionTests():
"""
Returns prioritized test list by eventually detected DBMS from error
messages
@@ -2019,14 +1915,14 @@ def getInjectionTests():
retVal = SORTORDER.LAST
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
else:
retVal = SORTORDER.THIRD
return retVal
if getErrorParsedDBMSes():
if backend.getErrorParsedDBMSes():
retVal = sorted(retVal, key=priorityFunction)
return retVal
@@ -2064,34 +1960,218 @@ def unicodeToSafeHTMLValue(value):
return retVal
def getErrorParsedDBMSes():
"""
Returns array with parsed DBMS names till now
class format:
@staticmethod
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.
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.
"""
# Get methods
@staticmethod
def getDbms(versions=None):
"""
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():
dbms = None
if versions is None and backend.getVersionList():
versions = backend.getVersionList()
if kb.misc.forcedDbms is not None:
dbms = kb.misc.forcedDbms
elif kb.dbms is not None:
dbms = kb.dbms
elif conf.dbms is not None:
dbms = conf.dbms
elif len(getErrorParsedDBMSes()) > 0:
dbms = getErrorParsedDBMSes()[0]
if versions is None:
return backend.getDbms()
else:
return "%s %s" % (backend.getDbms(), " and ".join([v for v in versions]))
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():
"""

View File

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

View File

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

View File

@@ -12,7 +12,7 @@ import os
import rlcompleter
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 paths
from lib.core.data import queries
@@ -30,7 +30,7 @@ def loadHistory():
def queriesForAutoCompletion():
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':
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
"""
from lib.core.common import getIdentifiedDBMS
from lib.core.common import backend
from lib.core.datatype import advancedDict
class Unescaper(advancedDict):
def unescape(self, expression, quote=True, dbms=None):
identifiedDbms = getIdentifiedDBMS()
identifiedDbms = backend.getIdentifiedDbms()
if identifiedDbms is not None:
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 getCompiledRegex
from lib.core.common import getIdentifiedDBMS
from lib.core.common import backend
from lib.core.common import parseXmlFile
from lib.core.common import sanitizeStr
from lib.core.data import kb
@@ -97,13 +97,13 @@ def bannerParser(banner):
xmlfile = None
if getIdentifiedDBMS() == DBMS.MSSQL:
if backend.getIdentifiedDbms() == DBMS.MSSQL:
xmlfile = paths.MSSQL_XML
elif getIdentifiedDBMS() == DBMS.MYSQL:
elif backend.getIdentifiedDbms() == DBMS.MYSQL:
xmlfile = paths.MYSQL_XML
elif getIdentifiedDBMS() == DBMS.ORACLE:
elif backend.getIdentifiedDbms() == DBMS.ORACLE:
xmlfile = paths.ORACLE_XML
elif getIdentifiedDBMS() == DBMS.PGSQL:
elif backend.getIdentifiedDbms() == DBMS.PGSQL:
xmlfile = paths.PGSQL_XML
if not xmlfile:
@@ -111,7 +111,7 @@ def bannerParser(banner):
checkFile(xmlfile)
if getIdentifiedDBMS() == DBMS.MSSQL:
if backend.getIdentifiedDbms() == DBMS.MSSQL:
handler = MSSQLBannerHandler(banner, kb.bannerFp)
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.common import dataToSessionFile
from lib.core.common import getIdentifiedDBMS
from lib.core.common import backend
from lib.core.common import getUnicode
from lib.core.convert import base64pickle
from lib.core.convert import base64unpickle
@@ -26,7 +26,7 @@ def direct(query, content=True):
select = False
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
for sqlTitle, sqlStatements in SQL_STATEMENTS.items():

View File

@@ -11,11 +11,11 @@ import re
import time
from lib.core.agent import agent
from lib.core.common import backend
from lib.core.common import calculateDeltaSeconds
from lib.core.common import cleanQuery
from lib.core.common import dataToSessionFile
from lib.core.common import expandAsteriskForColumns
from lib.core.common import getIdentifiedDBMS
from lib.core.common import getPublicTypeMembers
from lib.core.common import initTechnique
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))
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)
else:
length = None
@@ -137,186 +137,183 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
if not unpack:
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)
if rdbRegExp and getIdentifiedDBMS() == DBMS.FIREBIRD:
expressionFieldsList = [expressionFields]
rdbRegExp = re.search("RDB\$GET_CONTEXT\([^)]+\)", expression, re.I)
if rdbRegExp and backend.getIdentifiedDbms() == DBMS.FIREBIRD:
expressionFieldsList = [expressionFields]
if len(expressionFieldsList) > 1:
infoMsg = "the SQL query provided has more than a field. "
infoMsg += "sqlmap will now unpack it into distinct queries "
infoMsg += "to be able to retrieve the output even if we "
infoMsg += "are going blind"
logger.info(infoMsg)
if len(expressionFieldsList) > 1:
infoMsg = "the SQL query provided has more than a field. "
infoMsg += "sqlmap will now unpack it into distinct queries "
infoMsg += "to be able to retrieve the output even if we "
infoMsg += "are going blind"
logger.info(infoMsg)
# 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
# forge the SQL limiting the query output one entry per time
# NOTE: I assume that only queries that get data from a table
# 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()]))):
limitRegExp = re.search(queries[getIdentifiedDBMS()].limitregexp.query, expression, re.I)
topLimit = re.search("TOP\s+([\d]+)\s+", expression, re.I)
# 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
# forge the SQL limiting the query output one entry per time
# NOTE: I assume that only queries that get data from a table
# can return multiple entries
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[backend.getIdentifiedDbms()].limitregexp.query, 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 getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL):
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query
if limitRegExp or (backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit):
if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
limitGroupStart = queries[backend.getIdentifiedDbms()].limitgroupstart.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():
startLimit = int(limitRegExp.group(int(limitGroupStart)))
stopLimit = limitRegExp.group(int(limitGroupStop))
limitCond = int(stopLimit) > 1
elif topLimit:
startLimit = 0
stopLimit = int(topLimit.group(1))
limitCond = int(stopLimit) > 1
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
if limitRegExp:
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query
elif backend.getIdentifiedDbms() == DBMS.ORACLE:
limitCond = False
else:
limitCond = True
if limitGroupStart.isdigit():
startLimit = int(limitRegExp.group(int(limitGroupStart)))
# I assume that only queries NOT containing a "LIMIT #, 1"
# (or similar depending on the back-end DBMS) can return
# multiple entries
if limitCond:
if limitRegExp:
stopLimit = int(stopLimit)
stopLimit = limitRegExp.group(int(limitGroupStop))
limitCond = int(stopLimit) > 1
elif topLimit:
startLimit = 0
stopLimit = int(topLimit.group(1))
limitCond = int(stopLimit) > 1
# From now on we need only the expression until the " LIMIT "
# (or similar, depending on the back-end DBMS) word
if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
stopLimit += startLimit
untilLimitChar = expression.index(queries[backend.getIdentifiedDbms()].limitstring.query)
expression = expression[:untilLimitChar]
elif getIdentifiedDBMS() == DBMS.ORACLE:
limitCond = False
else:
limitCond = True
elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
stopLimit += startLimit
# I assume that only queries NOT containing a "LIMIT #, 1"
# (or similar depending on the back-end DBMS) can return
# multiple entries
if limitCond:
if limitRegExp:
stopLimit = int(stopLimit)
if not stopLimit or stopLimit <= 1:
if backend.getIdentifiedDbms() in FROM_TABLE and expression.upper().endswith(FROM_TABLE[backend.getIdentifiedDbms()]):
test = False
else:
test = True
# From now on we need only the expression until the " LIMIT "
# (or similar, depending on the back-end DBMS) word
if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL):
stopLimit += startLimit
untilLimitChar = expression.index(queries[getIdentifiedDBMS()].limitstring.query)
expression = expression[:untilLimitChar]
if test:
# Count the number of SQL query entries output
countFirstField = queries[backend.getIdentifiedDbms()].count.query % expressionFieldsList[0]
countedExpression = expression.replace(expressionFields, countFirstField, 1)
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
stopLimit += startLimit
if re.search(" ORDER BY ", expression, re.I):
untilOrderChar = countedExpression.index(" ORDER BY ")
countedExpression = countedExpression[:untilOrderChar]
if not stopLimit or stopLimit <= 1:
if getIdentifiedDBMS() in FROM_TABLE and expression.upper().endswith(FROM_TABLE[getIdentifiedDBMS()]):
test = False
else:
test = True
if resumeValue:
count = resume(countedExpression, payload)
if test:
# Count the number of SQL query entries output
countFirstField = queries[getIdentifiedDBMS()].count.query % expressionFieldsList[0]
countedExpression = expression.replace(expressionFields, countFirstField, 1)
if not stopLimit:
if not count or not count.isdigit():
count = __goInference(payload, countedExpression, 2, firstChar, lastChar)
if re.search(" ORDER BY ", expression, re.I):
untilOrderChar = countedExpression.index(" ORDER BY ")
countedExpression = countedExpression[:untilOrderChar]
if isNumPosStrValue(count):
count = int(count)
if resumeValue:
count = resume(countedExpression, payload)
if batch:
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 count or not count.isdigit():
count = __goInference(payload, countedExpression, 2, firstChar, lastChar)
if isNumPosStrValue(count):
count = int(count)
if batch:
if not test or test[0] in ("a", "A"):
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"):
stopLimit = count
elif test[0] in ("q", "Q"):
raise sqlmapUserQuitException
elif test[0] in ("q", "Q"):
raise sqlmapUserQuitException
elif test.isdigit() and int(test) > 0 and int(test) <= count:
stopLimit = int(test)
elif test.isdigit() and int(test) > 0 and int(test) <= count:
stopLimit = int(test)
infoMsg = "sqlmap is now going to retrieve the "
infoMsg += "first %d query output entries" % stopLimit
logger.info(infoMsg)
infoMsg = "sqlmap is now going to retrieve the "
infoMsg += "first %d query output entries" % stopLimit
logger.info(infoMsg)
elif test[0] in ("#", "s", "S"):
message = "how many? "
stopLimit = readInput(message, default="10")
elif test[0] in ("#", "s", "S"):
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:
if not stopLimit.isdigit():
errMsg = "invalid choice"
logger.error(errMsg)
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)
else:
stopLimit = int(stopLimit)
stopLimit = 1
else:
errMsg = "invalid choice"
logger.error(errMsg)
elif (not count or int(count) == 0):
warnMsg = "the SQL query provided does not "
warnMsg += "return any output"
logger.warn(warnMsg)
return None
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 += "return any output"
logger.warn(warnMsg)
return None
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 (not count or int(count) == 0) and (not stopLimit or stopLimit == 0):
warnMsg = "the SQL query provided does not "
warnMsg += "return any output"
logger.warn(warnMsg)
except KeyboardInterrupt:
print
warnMsg = "Ctrl+C detected in dumping phase"
logger.warn(warnMsg)
return None
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():
expression += FROM_TABLE[getIdentifiedDBMS()]
except KeyboardInterrupt:
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)
returnValue = ", ".join([output for output in outputs])
else:
returnValue = __goInference(payload, expression, charsetType, firstChar, lastChar)
return outputs
elif backend.getIdentifiedDbms() in FROM_TABLE and expression.upper().startswith("SELECT ") and " FROM " not in expression.upper():
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
@@ -495,7 +492,7 @@ def goStacked(expression, silent=False):
if conf.direct:
return direct(expression), None
comment = queries[getIdentifiedDBMS()].comment.query
comment = queries[backend.getIdentifiedDbms()].comment.query
query = agent.prefixQuery("; %s" % expression)
query = agent.suffixQuery("%s;%s" % (query, comment))
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 getIdentifiedDBMS
from lib.core.common import backend
from lib.core.common import isTechniqueAvailable
from lib.core.common import readInput
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):
self.webBackdoorRunCmd(cmd)
elif getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ):
elif backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
self.udfExecCmd(cmd, silent=silent)
elif getIdentifiedDBMS() == DBMS.MSSQL:
elif backend.getIdentifiedDbms() == DBMS.MSSQL:
self.xpCmdshellExecCmd(cmd, silent=silent)
else:
@@ -55,10 +55,10 @@ class Abstraction(Web, UDF, xp_cmdshell):
if self.webBackdoorUrl and not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED):
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)
elif getIdentifiedDBMS() == DBMS.MSSQL:
elif backend.getIdentifiedDbms() == DBMS.MSSQL:
return self.xpCmdshellEvalCmd(cmd, first, last)
else:
@@ -93,13 +93,13 @@ class Abstraction(Web, UDF, xp_cmdshell):
logger.info(infoMsg)
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 += "user-defined functions for operating system "
infoMsg += "command execution"
logger.info(infoMsg)
elif getIdentifiedDBMS() == DBMS.MSSQL:
elif backend.getIdentifiedDbms() == DBMS.MSSQL:
infoMsg = "going to use xp_cmdshell extended procedure for "
infoMsg += "operating system command execution"
logger.info(infoMsg)
@@ -151,9 +151,9 @@ class Abstraction(Web, UDF, xp_cmdshell):
warnMsg += "the session user is not a database administrator"
logger.warn(warnMsg)
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ):
if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
self.udfInjectSys()
elif getIdentifiedDBMS() == DBMS.MSSQL:
elif backend.getIdentifiedDbms() == DBMS.MSSQL:
if mandatory:
self.xpCmdshellInit()
else:

View File

@@ -19,7 +19,7 @@ from subprocess import PIPE
from subprocess import Popen as execute
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 getRemoteIP
from lib.core.common import getUnicode
@@ -187,13 +187,13 @@ class Metasploit:
if __payloadStr == "windows/vncinject":
choose = False
if getIdentifiedDBMS() == DBMS.MYSQL:
if backend.getIdentifiedDbms() == DBMS.MYSQL:
debugMsg = "by default MySQL on Windows runs as SYSTEM "
debugMsg += "user, it is likely that the the VNC "
debugMsg += "injection will be successful"
logger.debug(debugMsg)
elif getIdentifiedDBMS() == DBMS.PGSQL:
elif backend.getIdentifiedDbms() == DBMS.PGSQL:
choose = True
warnMsg = "by default PostgreSQL on Windows runs as "
@@ -201,12 +201,12 @@ class Metasploit:
warnMsg += "injection will be successful"
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
warnMsg = "it is unlikely that the VNC injection will be "
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"
logger.warn(warnMsg)
@@ -230,12 +230,12 @@ class Metasploit:
break
elif choice == "1":
if getIdentifiedDBMS() == DBMS.PGSQL:
if backend.getIdentifiedDbms() == DBMS.PGSQL:
logger.warn("beware that the VNC injection might not work")
break
elif getIdentifiedDBMS() == DBMS.MSSQL and kb.dbmsVersion[0] in ( "2005", "2008" ):
elif backend.getIdentifiedDbms() == DBMS.MSSQL and backend.isVersionWithin(("2005", "2008")):
break
elif not choice.isdigit():
@@ -555,7 +555,7 @@ class Metasploit:
# This is useful for sqlmap because on PostgreSQL it is not
# possible to write files bigger than 8192 bytes abusing the
# lo_export() feature implemented in sqlmap.
if getIdentifiedDBMS() == DBMS.PGSQL:
if backend.getIdentifiedDbms() == DBMS.PGSQL:
self.__fileFormat = "exe-small"
else:
self.__fileFormat = "exe"
@@ -657,7 +657,7 @@ class Metasploit:
self.__forgeMsfConsoleResource()
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)
else:
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.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 readInput
from lib.core.data import conf
@@ -51,7 +51,7 @@ class UDF:
def __checkExistUdf(self, 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)
if exists == "1":
@@ -104,7 +104,7 @@ class UDF:
return output
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")
if not conf.osPwn:
@@ -143,9 +143,9 @@ class UDF:
if udf in self.udfToCreate and udf not in self.createdUdf:
self.udfCreateFromSharedLib(udf, inpRet)
if getIdentifiedDBMS() == DBMS.MYSQL:
if backend.getIdentifiedDbms() == DBMS.MYSQL:
supportTblType = "longtext"
elif getIdentifiedDBMS() == DBMS.PGSQL:
elif backend.getIdentifiedDbms() == DBMS.PGSQL:
supportTblType = "text"
self.udfCreateSupportTbl(supportTblType)
@@ -156,8 +156,8 @@ class UDF:
self.udfInjectCore(self.sysUdfs)
def udfInjectCustom(self):
if getIdentifiedDBMS() not in ( DBMS.MYSQL, DBMS.PGSQL ):
errMsg = "UDF injection feature is not yet implemented on %s" % getIdentifiedDBMS()
if backend.getIdentifiedDbms() not in ( DBMS.MYSQL, DBMS.PGSQL ):
errMsg = "UDF injection feature is not yet implemented on %s" % backend.getIdentifiedDbms()
raise sqlmapUnsupportedFeatureException(errMsg)
if not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and not conf.direct:
@@ -236,9 +236,9 @@ class UDF:
else:
logger.warn("you need to specify the name of the UDF")
if getIdentifiedDBMS() == DBMS.MYSQL:
if backend.getIdentifiedDbms() == DBMS.MYSQL:
defaultType = "string"
elif getIdentifiedDBMS() == DBMS.PGSQL:
elif backend.getIdentifiedDbms() == DBMS.PGSQL:
defaultType = "text"
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
"""
from lib.core.common import backend
from lib.core.common import randomStr
from lib.core.common import readInput
from lib.core.common import wasLastRequestDelayed
@@ -29,7 +30,7 @@ class xp_cmdshell:
def __xpCmdshellCreate(self):
cmd = ""
if kb.dbmsVersion[0] in ( "2005", "2008" ):
if backend.isVersionWithin(("2005", "2008")):
logger.debug("activating sp_OACreate")
cmd += "EXEC master..sp_configure 'show advanced options', 1; "
@@ -48,7 +49,7 @@ class xp_cmdshell:
cmd += "EXEC sp_OADestroy @ID'; "
cmd += "EXEC master..sp_executesql @%s;" % self.__randStr
if kb.dbmsVersion[0] in ( "2005", "2008" ):
if backend.isVersionWithin(("2005", "2008")):
cmd += " RECONFIGURE WITH OVERRIDE;"
inject.goStacked(cmd)
@@ -80,7 +81,7 @@ class xp_cmdshell:
return cmd
def __xpCmdshellConfigure(self, mode):
if kb.dbmsVersion[0] in ( "2005", "2008" ):
if backend.isVersionWithin(("2005", "2008")):
cmd = self.__xpCmdshellConfigure2005(mode)
else:
cmd = self.__xpCmdshellConfigure2000(mode)

View File

@@ -12,12 +12,13 @@ import time
import traceback
from lib.core.agent import agent
from lib.core.common import backend
from lib.core.common import dataToSessionFile
from lib.core.common import dataToStdout
from lib.core.common import decodeIntToUnicode
from lib.core.common import filterControlChars
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 getPartRun
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):
lastChar = int(lastChar)
if kb.dbmsDetected:
if backend.getDbms():
_, _, _, _, _, _, fieldToCastStr, _ = agent.getFields(expression)
nulledCastedField = agent.nullAndCastField(fieldToCastStr)
expressionReplaced = expression.replace(fieldToCastStr, nulledCastedField, 1)
@@ -125,7 +126,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
hintlock.release()
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]
else:
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
if commonPattern is not None:
# 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)
query = agent.prefixQuery(safeStringFormat("AND (%s) = %s", (subquery, testValue)))
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 filterListValue
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 popValue
from lib.core.common import pushValue
@@ -32,7 +32,7 @@ from lib.core.session import safeFormatString
from lib.request import inject
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 = []
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 dataToSessionFile
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 isNumPosStrValue
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)
nulledCastedField = agent.nullAndCastField(field)
if getIdentifiedDBMS() == DBMS.MYSQL:
if backend.getIdentifiedDbms() == DBMS.MYSQL:
# Fix for MySQL odd behaviour ('Subquery returns more than 1 row')
nulledCastedField = nulledCastedField.replace("AS CHAR)", "AS CHAR(100))")
@@ -142,14 +142,14 @@ def errorUse(expression, expected=None, resumeValue=True, dump=False):
# entry per time
# NOTE: I assume that only queries that get data from a table can
# 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():
limitRegExp = re.search(queries[getIdentifiedDBMS()].limitregexp.query, expression, re.I)
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[backend.getIdentifiedDbms()].limitregexp.query, 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 getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL):
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query
if limitRegExp or (backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit):
if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
limitGroupStart = queries[backend.getIdentifiedDbms()].limitgroupstart.query
limitGroupStop = queries[backend.getIdentifiedDbms()].limitgroupstop.query
if limitGroupStart.isdigit():
startLimit = int(limitRegExp.group(int(limitGroupStart)))
@@ -157,10 +157,10 @@ def errorUse(expression, expected=None, resumeValue=True, dump=False):
stopLimit = limitRegExp.group(int(limitGroupStop))
limitCond = int(stopLimit) > 1
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
if limitRegExp:
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query
limitGroupStart = queries[backend.getIdentifiedDbms()].limitgroupstart.query
limitGroupStop = queries[backend.getIdentifiedDbms()].limitgroupstop.query
if limitGroupStart.isdigit():
startLimit = int(limitRegExp.group(int(limitGroupStart)))
@@ -172,7 +172,7 @@ def errorUse(expression, expected=None, resumeValue=True, dump=False):
stopLimit = int(topLimit.group(1))
limitCond = int(stopLimit) > 1
elif getIdentifiedDBMS() == DBMS.ORACLE:
elif backend.getIdentifiedDbms() == DBMS.ORACLE:
limitCond = False
else:
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 "
# (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
untilLimitChar = expression.index(queries[getIdentifiedDBMS()].limitstring.query)
untilLimitChar = expression.index(queries[backend.getIdentifiedDbms()].limitstring.query)
expression = expression[:untilLimitChar]
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
stopLimit += startLimit
elif dump:
if conf.limitStart:
@@ -200,14 +200,14 @@ def errorUse(expression, expected=None, resumeValue=True, dump=False):
stopLimit = conf.limitStop
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
else:
test = True
if test:
# 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)
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.common import clearConsoleLine
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 parseUnionPage
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)
for count in range(conf.uColsStart, conf.uColsStop+1):
if getIdentifiedDBMS() in FROM_TABLE and query.endswith(FROM_TABLE[getIdentifiedDBMS()]):
query = query[:-len(FROM_TABLE[getIdentifiedDBMS()])]
if backend.getIdentifiedDbms() in FROM_TABLE and query.endswith(FROM_TABLE[backend.getIdentifiedDbms()]):
query = query[:-len(FROM_TABLE[backend.getIdentifiedDbms()])]
if count:
query += ", %s" % conf.uChar
if getIdentifiedDBMS() in FROM_TABLE:
query += FROM_TABLE[getIdentifiedDBMS()]
if backend.getIdentifiedDbms() in FROM_TABLE:
query += FROM_TABLE[backend.getIdentifiedDbms()]
status = "%d/%d" % (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 clearConsoleLine
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 initTechnique
from lib.core.common import isNumPosStrValue
@@ -103,14 +103,14 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
# entry per time
# NOTE: I assume that only queries that get data from a table can
# 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():
limitRegExp = re.search(queries[getIdentifiedDBMS()].limitregexp.query, expression, re.I)
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[backend.getIdentifiedDbms()].limitregexp.query, 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 getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL):
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query
if limitRegExp or (backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit):
if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
limitGroupStart = queries[backend.getIdentifiedDbms()].limitgroupstart.query
limitGroupStop = queries[backend.getIdentifiedDbms()].limitgroupstop.query
if limitGroupStart.isdigit():
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))
limitCond = int(stopLimit) > 1
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
if limitRegExp:
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query
limitGroupStart = queries[backend.getIdentifiedDbms()].limitgroupstart.query
limitGroupStop = queries[backend.getIdentifiedDbms()].limitgroupstop.query
if limitGroupStart.isdigit():
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))
limitCond = int(stopLimit) > 1
elif getIdentifiedDBMS() == DBMS.ORACLE:
elif backend.getIdentifiedDbms() == DBMS.ORACLE:
limitCond = False
else:
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 "
# (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
untilLimitChar = expression.index(queries[getIdentifiedDBMS()].limitstring.query)
untilLimitChar = expression.index(queries[backend.getIdentifiedDbms()].limitstring.query)
expression = expression[:untilLimitChar]
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
stopLimit += startLimit
elif dump:
if conf.limitStart:
@@ -161,14 +161,14 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
stopLimit = conf.limitStop
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
else:
test = True
if test:
# 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)
if re.search(" ORDER BY ", expression, re.I):
@@ -216,9 +216,9 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
try:
for num in xrange(startLimit, stopLimit):
if getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
if backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
field = expressionFieldsList[0]
elif getIdentifiedDBMS() == DBMS.ORACLE:
elif backend.getIdentifiedDbms() == DBMS.ORACLE:
field = expressionFieldsList
else:
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 getCompiledRegex
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 getUnicode
from lib.core.common import paths
@@ -270,9 +270,9 @@ def hashRecognition(value):
if value:
for name, regex in getPublicTypeMembers(HASH):
# 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
elif getIdentifiedDBMS() == DBMS.MYSQL and regex == HASH.ORACLE_OLD:
elif backend.getIdentifiedDbms() == DBMS.MYSQL and regex == HASH.ORACLE_OLD:
continue
elif getCompiledRegex(regex).match(value):
retVal = regex

View File

@@ -13,7 +13,7 @@ import time
from lib.core.common import calculateDeltaSeconds
from lib.core.common import dataToSessionFile
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 randomStr
from lib.core.common import replaceNewlineTabs
@@ -34,7 +34,7 @@ def queryOutputLength(expression, payload):
Returns the query output length.
"""
lengthQuery = queries[getIdentifiedDBMS()].length.query
lengthQuery = queries[backend.getIdentifiedDbms()].length.query
select = re.search("\ASELECT\s+", 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)
@@ -60,7 +60,7 @@ def queryOutputLength(expression, payload):
if selectDistinctExpr:
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)
elif select:
lengthExpr = expression.replace(regExpr, lengthQuery % regExpr, 1)
@@ -142,10 +142,10 @@ def resume(expression, payload):
if not payload:
return None
if not getIdentifiedDBMS():
if not backend.getIdentifiedDbms():
return None
substringQuery = queries[getIdentifiedDBMS()].substring.query
substringQuery = queries[backend.getIdentifiedDbms()].substring.query
select = re.search("\ASELECT ", expression, re.I)
_, length, regExpr = queryOutputLength(expression, payload)