mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2024-11-26 03:23:48 +03:00
changes regarding EXISTS feature
This commit is contained in:
parent
51beafc32c
commit
cf8e92699c
|
@ -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())
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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():
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -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 "
|
||||||
|
|
|
@ -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, "
|
||||||
|
|
Loading…
Reference in New Issue
Block a user