changes regarding EXISTS feature

This commit is contained in:
Miroslav Stampar 2010-09-30 12:35:45 +00:00
parent 51beafc32c
commit cf8e92699c
6 changed files with 120 additions and 21 deletions

View File

@ -27,6 +27,7 @@ from lib.core.common import getHtmlErrorFp
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
from lib.core.data import paths
from lib.core.exception import sqlmapUnsupportedDBMSException from lib.core.exception import sqlmapUnsupportedDBMSException
from lib.core.settings import SUPPORTED_DBMS from lib.core.settings import SUPPORTED_DBMS
from lib.techniques.blind.timebased import timeTest from lib.techniques.blind.timebased import timeTest
@ -111,6 +112,12 @@ def action():
if conf.getTables: if conf.getTables:
conf.dumper.dbTables(conf.dbmsHandler.getTables()) conf.dumper.dbTables(conf.dbmsHandler.getTables())
if conf.cExists:
conf.dumper.dbTables(conf.dbmsHandler.tableExists(paths.COMMON_TABLES))
if conf.tableFile:
conf.dumper.dbTables(conf.dbmsHandler.tableExists(conf.tableFile))
if conf.getColumns: if conf.getColumns:
conf.dumper.dbTableColumns(conf.dbmsHandler.getColumns()) conf.dumper.dbTableColumns(conf.dbmsHandler.getColumns())

View File

@ -411,8 +411,8 @@ def filePathToString(filePath):
return strRepl return strRepl
def dataToStdout(data): def dataToStdout(data, forceOutput=False):
if conf.verbose > 0: if conf.verbose > 0 or forceOutput:
try: try:
sys.stdout.write(data) sys.stdout.write(data)
sys.stdout.flush() sys.stdout.flush()
@ -657,6 +657,8 @@ def setPaths():
# sqlmap files # sqlmap files
paths.SQLMAP_HISTORY = os.path.join(paths.SQLMAP_ROOT_PATH, ".sqlmap_history") paths.SQLMAP_HISTORY = os.path.join(paths.SQLMAP_ROOT_PATH, ".sqlmap_history")
paths.SQLMAP_CONFIG = os.path.join(paths.SQLMAP_ROOT_PATH, "sqlmap-%s.conf" % randomStr()) paths.SQLMAP_CONFIG = os.path.join(paths.SQLMAP_ROOT_PATH, "sqlmap-%s.conf" % randomStr())
paths.COMMON_OUTPUTS = os.path.join(paths.SQLMAP_TXT_PATH, 'common-outputs.txt')
paths.COMMON_TABLES = os.path.join(paths.SQLMAP_TXT_PATH, "common-tables.txt")
paths.FUZZ_VECTORS = os.path.join(paths.SQLMAP_TXT_PATH, "fuzz_vectors.txt") paths.FUZZ_VECTORS = os.path.join(paths.SQLMAP_TXT_PATH, "fuzz_vectors.txt")
paths.DETECTION_RULES_XML = os.path.join(paths.SQLMAP_XML_PATH, "detection.xml") paths.DETECTION_RULES_XML = os.path.join(paths.SQLMAP_XML_PATH, "detection.xml")
paths.ERRORS_XML = os.path.join(paths.SQLMAP_XML_PATH, "errors.xml") paths.ERRORS_XML = os.path.join(paths.SQLMAP_XML_PATH, "errors.xml")
@ -1233,8 +1235,7 @@ def initCommonOutputs():
kb.commonOutputs = {} kb.commonOutputs = {}
key = None key = None
fileName = os.path.join(paths.SQLMAP_TXT_PATH, 'common-outputs.txt') cfile = codecs.open(paths.COMMON_OUTPUTS, 'r', conf.dataEncoding)
cfile = codecs.open(fileName, 'r', conf.dataEncoding)
for line in cfile.readlines(): # xreadlines doesn't return unicode strings when codec.open() is used for line in cfile.readlines(): # xreadlines doesn't return unicode strings when codec.open() is used
if line.find('#') != -1: if line.find('#') != -1:
@ -1254,6 +1255,21 @@ def initCommonOutputs():
cfile.close() cfile.close()
def getFileItems(filename):
retVal = []
checkFile(filename)
file = codecs.open(filename, 'r', conf.dataEncoding)
for line in file.readlines(): # xreadlines doesn't return unicode strings when codec.open() is used
if line.find('#') != -1:
line = line[:line.find('#')]
line = line.strip()
if line:
retVal.append(line)
return retVal
def goGoodSamaritan(prevValue, originalCharset): def goGoodSamaritan(prevValue, originalCharset):
""" """
Function for retrieving parameters needed for common prediction (good Function for retrieving parameters needed for common prediction (good
@ -1412,3 +1428,9 @@ def replaceSpaces(query):
return query if conf.space is None else query.replace(' ', conf.space) return query if conf.space is None else query.replace(' ', conf.space)
else: else:
return query return query
def pushValue(value):
kb.valueStack.append(value)
def popValue():
return kb.valueStack.pop()

View File

@ -157,37 +157,58 @@ class Dump:
self.lister("available databases", dbs) self.lister("available databases", dbs)
def dbTables(self, dbTables): def dbTables(self, dbTables):
if not isinstance(dbTables, dict): if isinstance(dbTables, list):
self.string("tables", dbTables) maxlength = 0
return for table in dbTables:
maxlength = 0
for tables in dbTables.values():
for table in tables:
maxlength = max(maxlength, len(table)) maxlength = max(maxlength, len(table))
lines = "-" * (int(maxlength) + 2) lines = "-" * (int(maxlength) + 2)
for db, tables in dbTables.items(): dbTables.sort(key=lambda x: x.lower())
tables.sort(key=lambda x: x.lower())
self.__write("Database: %s" % db) if len(dbTables) == 1:
if len(tables) == 1:
self.__write("[1 table]") self.__write("[1 table]")
else: else:
self.__write("[%d tables]" % len(tables)) self.__write("[%d tables]" % len(dbTables))
self.__write("+%s+" % lines) self.__write("+%s+" % lines)
for table in tables: for table in dbTables:
blank = " " * (maxlength - len(table)) blank = " " * (maxlength - len(table))
self.__write("| %s%s |" % (table, blank)) self.__write("| %s%s |" % (table, blank))
self.__write("+%s+\n" % lines) self.__write("+%s+\n" % lines)
elif isinstance(dbTables, dict):
maxlength = 0
for tables in dbTables.values():
for table in tables:
maxlength = max(maxlength, len(table))
lines = "-" * (int(maxlength) + 2)
for db, tables in dbTables.items():
tables.sort(key=lambda x: x.lower())
self.__write("Database: %s" % db)
if len(tables) == 1:
self.__write("[1 table]")
else:
self.__write("[%d tables]" % len(tables))
self.__write("+%s+" % lines)
for table in tables:
blank = " " * (maxlength - len(table))
self.__write("| %s%s |" % (table, blank))
self.__write("+%s+\n" % lines)
else:
self.string("tables", dbTables)
def dbTableColumns(self, tableColumns): def dbTableColumns(self, tableColumns):
for db, tables in tableColumns.items(): for db, tables in tableColumns.items():
if not db: if not db:

View File

@ -1031,6 +1031,7 @@ def __setKnowledgeBaseAttributes():
kb.unionPosition = None kb.unionPosition = None
kb.unionNegative = False kb.unionNegative = False
kb.unionFalseCond = False kb.unionFalseCond = False
kb.valueStack = []
def __saveCmdline(): def __saveCmdline():
""" """

View File

@ -332,6 +332,12 @@ def cmdLineParser():
action="store_true", default=False, action="store_true", default=False,
help="Prompt for an interactive SQL shell") help="Prompt for an interactive SQL shell")
enumeration.add_option("--common-exists", dest="cExists", action="store_true",
default=False, help="Check existence of common tables")
enumeration.add_option("--exists", dest="tableFile",
help="Check existence of user specified tables")
# User-defined function options # User-defined function options
udf = OptionGroup(parser, "User-defined function injection", "These " udf = OptionGroup(parser, "User-defined function injection", "These "
"options can be used to create custom user-defined " "options can be used to create custom user-defined "

View File

@ -23,12 +23,18 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import re import re
import time
from lib.core.agent import agent from lib.core.agent import agent
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 getFileItems
from lib.core.common import getUnicode from lib.core.common import getUnicode
from lib.core.common import parsePasswordHash from lib.core.common import parsePasswordHash
from lib.core.common import popValue
from lib.core.common import pushValue
from lib.core.common import readInput from lib.core.common import readInput
from lib.core.common import safeStringFormat from lib.core.common import safeStringFormat
from lib.core.convert import urlencode from lib.core.convert import urlencode
@ -47,6 +53,7 @@ from lib.core.shell import autoCompletion
from lib.core.unescaper import unescaper from lib.core.unescaper import unescaper
from lib.parse.banner import bannerParser from lib.parse.banner import bannerParser
from lib.request import inject from lib.request import inject
from lib.request.connect import Connect as Request
from lib.techniques.inband.union.test import unionTest from lib.techniques.inband.union.test import unionTest
from lib.techniques.outband.stacked import stackedTest from lib.techniques.outband.stacked import stackedTest
@ -801,6 +808,41 @@ class Enumeration:
return kb.data.cachedTables return kb.data.cachedTables
def tableExists(self, tableFile):
tables = getFileItems(tableFile)
retVal = []
infoMsg = "checking tables existence using items from '%s'" % tableFile
logger.info(infoMsg)
pushValue(conf.verbose)
conf.verbose = 0
count = 0
length = len(tables)
for table in tables:
query = agent.prefixQuery(" %s" % safeStringFormat("AND EXISTS(SELECT 1 FROM %s)", table))
query = agent.postfixQuery(query)
result = Request.queryPage(urlencode(agent.payload(newValue=query)))
if result:
infoMsg = "\r[%s] [INFO] retrieved: %s" % (time.strftime("%X"), table)
infoMsg = "%s%s\n" % (infoMsg, " "*(getConsoleWidth()-1-len(infoMsg)))
dataToStdout(infoMsg, True)
retVal.append(table)
count += 1
status = '%d/%d (%d%s)' % (count, length, round(100.0*count/length), '%')
dataToStdout("\r[%s] [INFO] complete: %s" % (time.strftime("%X"), status), True)
conf.verbose = popValue()
dataToStdout("\r%s\n" % (" "*(getConsoleWidth()-1)), True)
if not retVal:
warnMsg = "no table found"
logger.warn(warnMsg)
return retVal
def getColumns(self, onlyColNames=False): def getColumns(self, onlyColNames=False):
if kb.dbms == "MySQL" and not kb.data.has_information_schema: if kb.dbms == "MySQL" and not kb.data.has_information_schema:
errMsg = "information_schema not available, " errMsg = "information_schema not available, "