mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2024-11-25 11:03:47 +03:00
Implements #2908
This commit is contained in:
parent
c938d77be9
commit
aa9b5e4e0c
1641
data/txt/common-files.txt
Normal file
1641
data/txt/common-files.txt
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -17,6 +17,7 @@ from lib.core.exception import SqlmapNoneDataException
|
||||||
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.utils.brute import columnExists
|
from lib.utils.brute import columnExists
|
||||||
|
from lib.utils.brute import fileExists
|
||||||
from lib.utils.brute import tableExists
|
from lib.utils.brute import tableExists
|
||||||
|
|
||||||
def action():
|
def action():
|
||||||
|
@ -199,6 +200,14 @@ def action():
|
||||||
if conf.fileWrite:
|
if conf.fileWrite:
|
||||||
conf.dbmsHandler.writeFile(conf.fileWrite, conf.fileDest, conf.fileWriteType)
|
conf.dbmsHandler.writeFile(conf.fileWrite, conf.fileDest, conf.fileWriteType)
|
||||||
|
|
||||||
|
if conf.commonFiles:
|
||||||
|
try:
|
||||||
|
conf.dumper.rFile(fileExists(paths.COMMON_FILES))
|
||||||
|
except SqlmapNoneDataException as ex:
|
||||||
|
logger.critical(ex)
|
||||||
|
except:
|
||||||
|
raise
|
||||||
|
|
||||||
# Operating system options
|
# Operating system options
|
||||||
if conf.osCmd:
|
if conf.osCmd:
|
||||||
conf.dbmsHandler.osCmd()
|
conf.dbmsHandler.osCmd()
|
||||||
|
|
|
@ -1346,6 +1346,7 @@ def setPaths(rootPath):
|
||||||
|
|
||||||
# sqlmap files
|
# sqlmap files
|
||||||
paths.COMMON_COLUMNS = os.path.join(paths.SQLMAP_TXT_PATH, "common-columns.txt")
|
paths.COMMON_COLUMNS = os.path.join(paths.SQLMAP_TXT_PATH, "common-columns.txt")
|
||||||
|
paths.COMMON_FILES = os.path.join(paths.SQLMAP_TXT_PATH, "common-files.txt")
|
||||||
paths.COMMON_TABLES = os.path.join(paths.SQLMAP_TXT_PATH, "common-tables.txt")
|
paths.COMMON_TABLES = os.path.join(paths.SQLMAP_TXT_PATH, "common-tables.txt")
|
||||||
paths.COMMON_OUTPUTS = os.path.join(paths.SQLMAP_TXT_PATH, 'common-outputs.txt')
|
paths.COMMON_OUTPUTS = os.path.join(paths.SQLMAP_TXT_PATH, 'common-outputs.txt')
|
||||||
paths.SQL_KEYWORDS = os.path.join(paths.SQLMAP_TXT_PATH, "keywords.txt")
|
paths.SQL_KEYWORDS = os.path.join(paths.SQLMAP_TXT_PATH, "keywords.txt")
|
||||||
|
@ -4637,6 +4638,8 @@ def decodeDbmsHexValue(value, raw=False):
|
||||||
def _(value):
|
def _(value):
|
||||||
retVal = value
|
retVal = value
|
||||||
if value and isinstance(value, six.string_types):
|
if value and isinstance(value, six.string_types):
|
||||||
|
value = value.strip()
|
||||||
|
|
||||||
if len(value) % 2 != 0:
|
if len(value) % 2 != 0:
|
||||||
retVal = (decodeHex(value[:-1]) + b'?') if len(value) > 1 else value
|
retVal = (decodeHex(value[:-1]) + b'?') if len(value) > 1 else value
|
||||||
singleTimeWarnMessage("there was a problem decoding value '%s' from expected hexadecimal form" % value)
|
singleTimeWarnMessage("there was a problem decoding value '%s' from expected hexadecimal form" % value)
|
||||||
|
|
|
@ -160,6 +160,7 @@ optDict = {
|
||||||
"Brute": {
|
"Brute": {
|
||||||
"commonTables": "boolean",
|
"commonTables": "boolean",
|
||||||
"commonColumns": "boolean",
|
"commonColumns": "boolean",
|
||||||
|
"commonFiles": "boolean",
|
||||||
},
|
},
|
||||||
|
|
||||||
"User-defined function": {
|
"User-defined function": {
|
||||||
|
|
|
@ -18,7 +18,7 @@ from lib.core.enums import OS
|
||||||
from thirdparty.six import unichr as _unichr
|
from thirdparty.six import unichr as _unichr
|
||||||
|
|
||||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||||
VERSION = "1.3.6.56"
|
VERSION = "1.3.6.57"
|
||||||
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
||||||
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
|
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
|
||||||
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
|
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
|
||||||
|
|
|
@ -586,7 +586,7 @@ def _createFilesDir():
|
||||||
Create the file directory.
|
Create the file directory.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not conf.fileRead:
|
if not any((conf.fileRead, conf.commonFiles)):
|
||||||
return
|
return
|
||||||
|
|
||||||
conf.filePath = paths.SQLMAP_FILES_PATH % conf.hostname
|
conf.filePath = paths.SQLMAP_FILES_PATH % conf.hostname
|
||||||
|
|
|
@ -204,7 +204,6 @@ def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardExceptio
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
kb.bruteMode = False
|
|
||||||
kb.threadContinue = True
|
kb.threadContinue = True
|
||||||
kb.threadException = False
|
kb.threadException = False
|
||||||
|
|
||||||
|
|
|
@ -502,6 +502,9 @@ def cmdLineParser(argv=None):
|
||||||
brute.add_argument("--common-columns", dest="commonColumns", action="store_true",
|
brute.add_argument("--common-columns", dest="commonColumns", action="store_true",
|
||||||
help="Check existence of common columns")
|
help="Check existence of common columns")
|
||||||
|
|
||||||
|
brute.add_argument("--common-files", dest="commonFiles", action="store_true",
|
||||||
|
help="Check existence of common files")
|
||||||
|
|
||||||
# User-defined function options
|
# User-defined function options
|
||||||
udf = parser.add_argument_group("User-defined function injection", "These options can be used to create custom user-defined functions")
|
udf = parser.add_argument_group("User-defined function injection", "These options can be used to create custom user-defined functions")
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,7 @@ class UDF(object):
|
||||||
return output
|
return output
|
||||||
|
|
||||||
def udfCheckNeeded(self):
|
def udfCheckNeeded(self):
|
||||||
if (not conf.fileRead or (conf.fileRead and not Backend.isDbms(DBMS.PGSQL))) and "sys_fileread" in self.sysUdfs:
|
if (not any((conf.fileRead, conf.commonFiles)) or (any((conf.fileRead, conf.commonFiles)) and not Backend.isDbms(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:
|
||||||
|
|
|
@ -43,6 +43,7 @@ from lib.core.dicts import FROM_DUMMY_TABLE
|
||||||
from lib.core.enums import DBMS
|
from lib.core.enums import DBMS
|
||||||
from lib.core.enums import HASHDB_KEYS
|
from lib.core.enums import HASHDB_KEYS
|
||||||
from lib.core.enums import HTTP_HEADER
|
from lib.core.enums import HTTP_HEADER
|
||||||
|
from lib.core.enums import PAYLOAD
|
||||||
from lib.core.exception import SqlmapDataException
|
from lib.core.exception import SqlmapDataException
|
||||||
from lib.core.settings import CHECK_ZERO_COLUMNS_THRESHOLD
|
from lib.core.settings import CHECK_ZERO_COLUMNS_THRESHOLD
|
||||||
from lib.core.settings import MAX_ERROR_CHUNK_LENGTH
|
from lib.core.settings import MAX_ERROR_CHUNK_LENGTH
|
||||||
|
@ -123,7 +124,7 @@ def _oneShotErrorUse(expression, field=None, chunkTest=False):
|
||||||
nulledCastedField = queries[Backend.getIdentifiedDbms()].substring.query % (nulledCastedField, offset, kb.errorChunkLength)
|
nulledCastedField = queries[Backend.getIdentifiedDbms()].substring.query % (nulledCastedField, offset, kb.errorChunkLength)
|
||||||
|
|
||||||
# Forge the error-based SQL injection request
|
# Forge the error-based SQL injection request
|
||||||
vector = kb.injection.data[kb.technique].vector
|
vector = kb.injection.data[PAYLOAD.TECHNIQUE.ERROR].vector
|
||||||
query = agent.prefixQuery(vector)
|
query = agent.prefixQuery(vector)
|
||||||
query = agent.suffixQuery(query)
|
query = agent.suffixQuery(query)
|
||||||
injExpression = expression.replace(field, nulledCastedField, 1) if field else expression
|
injExpression = expression.replace(field, nulledCastedField, 1) if field else expression
|
||||||
|
@ -134,7 +135,7 @@ def _oneShotErrorUse(expression, field=None, chunkTest=False):
|
||||||
# Perform the request
|
# Perform the request
|
||||||
page, headers, _ = Request.queryPage(payload, content=True, raise404=False)
|
page, headers, _ = Request.queryPage(payload, content=True, raise404=False)
|
||||||
|
|
||||||
incrementCounter(kb.technique)
|
incrementCounter(PAYLOAD.TECHNIQUE.ERROR)
|
||||||
|
|
||||||
if page and conf.noEscape:
|
if page and conf.noEscape:
|
||||||
page = re.sub(r"('|\%%27)%s('|\%%27).*?('|\%%27)%s('|\%%27)" % (kb.chars.start, kb.chars.stop), "", page)
|
page = re.sub(r"('|\%%27)%s('|\%%27).*?('|\%%27)%s('|\%%27)" % (kb.chars.start, kb.chars.stop), "", page)
|
||||||
|
@ -247,7 +248,7 @@ def _errorFields(expression, expressionFields, expressionFieldsList, num=None, e
|
||||||
if not kb.threadContinue:
|
if not kb.threadContinue:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if not suppressOutput:
|
if not any((suppressOutput, kb.bruteMode)):
|
||||||
if kb.fileReadMode and output and output.strip():
|
if kb.fileReadMode and output and output.strip():
|
||||||
print()
|
print()
|
||||||
elif output is not None and not (threadData.resumed and kb.suppressResumeInfo) and not (emptyFields and field in emptyFields):
|
elif output is not None and not (threadData.resumed and kb.suppressResumeInfo) and not (emptyFields and field in emptyFields):
|
||||||
|
@ -298,7 +299,7 @@ def errorUse(expression, dump=False):
|
||||||
SQL injection vulnerability on the affected parameter.
|
SQL injection vulnerability on the affected parameter.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
initTechnique(kb.technique)
|
initTechnique(PAYLOAD.TECHNIQUE.ERROR)
|
||||||
|
|
||||||
abortedFlag = False
|
abortedFlag = False
|
||||||
count = None
|
count = None
|
||||||
|
@ -460,7 +461,7 @@ def errorUse(expression, dump=False):
|
||||||
duration = calculateDeltaSeconds(start)
|
duration = calculateDeltaSeconds(start)
|
||||||
|
|
||||||
if not kb.bruteMode:
|
if not kb.bruteMode:
|
||||||
debugMsg = "performed %d queries in %.2f seconds" % (kb.counters[kb.technique], duration)
|
debugMsg = "performed %d queries in %.2f seconds" % (kb.counters[PAYLOAD.TECHNIQUE.ERROR], duration)
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
|
@ -312,6 +312,7 @@ def _unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix)
|
||||||
|
|
||||||
return validPayload, vector
|
return validPayload, vector
|
||||||
|
|
||||||
|
@stackedmethod
|
||||||
def unionTest(comment, place, parameter, value, prefix, suffix):
|
def unionTest(comment, place, parameter, value, prefix, suffix):
|
||||||
"""
|
"""
|
||||||
This method tests if the target URL is affected by an union
|
This method tests if the target URL is affected by an union
|
||||||
|
|
|
@ -376,7 +376,7 @@ def unionUse(expression, unpack=True, dump=False):
|
||||||
threadData.shared.value.extend(arrayizeValue(_))
|
threadData.shared.value.extend(arrayizeValue(_))
|
||||||
del threadData.shared.buffered[0]
|
del threadData.shared.buffered[0]
|
||||||
|
|
||||||
if conf.verbose == 1 and not (threadData.resumed and kb.suppressResumeInfo) and not threadData.shared.showEta:
|
if conf.verbose == 1 and not (threadData.resumed and kb.suppressResumeInfo) and not threadData.shared.showEta and not kb.bruteMode:
|
||||||
_ = ','.join("'%s'" % _ for _ in (flattenValue(arrayizeValue(items)) if not isinstance(items, six.string_types) else [items]))
|
_ = ','.join("'%s'" % _ for _ in (flattenValue(arrayizeValue(items)) if not isinstance(items, six.string_types) else [items]))
|
||||||
status = "[%s] [INFO] %s: %s" % (time.strftime("%X"), "resumed" if threadData.resumed else "retrieved", _ if kb.safeCharEncode else safecharencode(_))
|
status = "[%s] [INFO] %s: %s" % (time.strftime("%X"), "resumed" if threadData.resumed else "retrieved", _ if kb.safeCharEncode else safecharencode(_))
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ See the file 'LICENSE' for copying permission
|
||||||
|
|
||||||
from __future__ import division
|
from __future__ import division
|
||||||
|
|
||||||
|
import logging
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from lib.core.common import Backend
|
from lib.core.common import Backend
|
||||||
|
@ -16,20 +17,26 @@ from lib.core.common import filterListValue
|
||||||
from lib.core.common import getFileItems
|
from lib.core.common import getFileItems
|
||||||
from lib.core.common import getPageWordSet
|
from lib.core.common import getPageWordSet
|
||||||
from lib.core.common import hashDBWrite
|
from lib.core.common import hashDBWrite
|
||||||
|
from lib.core.common import isNoneValue
|
||||||
|
from lib.core.common import popValue
|
||||||
|
from lib.core.common import pushValue
|
||||||
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 readInput
|
from lib.core.common import readInput
|
||||||
from lib.core.common import safeSQLIdentificatorNaming
|
from lib.core.common import safeSQLIdentificatorNaming
|
||||||
from lib.core.common import safeStringFormat
|
from lib.core.common import safeStringFormat
|
||||||
|
from lib.core.common import unArrayizeValue
|
||||||
from lib.core.common import unsafeSQLIdentificatorNaming
|
from lib.core.common import unsafeSQLIdentificatorNaming
|
||||||
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
|
||||||
|
from lib.core.decorators import stackedmethod
|
||||||
from lib.core.enums import DBMS
|
from lib.core.enums import DBMS
|
||||||
from lib.core.enums import HASHDB_KEYS
|
from lib.core.enums import HASHDB_KEYS
|
||||||
from lib.core.enums import PAYLOAD
|
from lib.core.enums import PAYLOAD
|
||||||
from lib.core.exception import SqlmapDataException
|
from lib.core.exception import SqlmapDataException
|
||||||
from lib.core.exception import SqlmapMissingMandatoryOptionException
|
from lib.core.exception import SqlmapMissingMandatoryOptionException
|
||||||
|
from lib.core.exception import SqlmapNoneDataException
|
||||||
from lib.core.settings import BRUTE_COLUMN_EXISTS_TEMPLATE
|
from lib.core.settings import BRUTE_COLUMN_EXISTS_TEMPLATE
|
||||||
from lib.core.settings import BRUTE_TABLE_EXISTS_TEMPLATE
|
from lib.core.settings import BRUTE_TABLE_EXISTS_TEMPLATE
|
||||||
from lib.core.settings import METADB_SUFFIX
|
from lib.core.settings import METADB_SUFFIX
|
||||||
|
@ -136,7 +143,6 @@ def tableExists(tableFile, regex=None):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
runThreads(conf.threads, tableExistsThread, threadChoice=True)
|
runThreads(conf.threads, tableExistsThread, threadChoice=True)
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
warnMsg = "user aborted during table existence "
|
warnMsg = "user aborted during table existence "
|
||||||
warnMsg += "check. sqlmap will display partial output"
|
warnMsg += "check. sqlmap will display partial output"
|
||||||
|
@ -252,11 +258,12 @@ def columnExists(columnFile, regex=None):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
runThreads(conf.threads, columnExistsThread, threadChoice=True)
|
runThreads(conf.threads, columnExistsThread, threadChoice=True)
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
warnMsg = "user aborted during column existence "
|
warnMsg = "user aborted during column existence "
|
||||||
warnMsg += "check. sqlmap will display partial output"
|
warnMsg += "check. sqlmap will display partial output"
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
finally:
|
||||||
|
kb.bruteMode = False
|
||||||
|
|
||||||
clearConsoleLine(True)
|
clearConsoleLine(True)
|
||||||
dataToStdout("\n")
|
dataToStdout("\n")
|
||||||
|
@ -287,3 +294,81 @@ def columnExists(columnFile, regex=None):
|
||||||
hashDBWrite(HASHDB_KEYS.KB_BRUTE_COLUMNS, kb.brute.columns, True)
|
hashDBWrite(HASHDB_KEYS.KB_BRUTE_COLUMNS, kb.brute.columns, True)
|
||||||
|
|
||||||
return kb.data.cachedColumns
|
return kb.data.cachedColumns
|
||||||
|
|
||||||
|
@stackedmethod
|
||||||
|
def fileExists(pathFile):
|
||||||
|
retVal = []
|
||||||
|
paths = getFileItems(pathFile, unique=True)
|
||||||
|
|
||||||
|
kb.bruteMode = True
|
||||||
|
|
||||||
|
try:
|
||||||
|
conf.dbmsHandler.readFile(randomStr())
|
||||||
|
except SqlmapNoneDataException:
|
||||||
|
pass
|
||||||
|
except:
|
||||||
|
kb.bruteMode = False
|
||||||
|
raise
|
||||||
|
|
||||||
|
threadData = getCurrentThreadData()
|
||||||
|
threadData.shared.count = 0
|
||||||
|
threadData.shared.limit = len(paths)
|
||||||
|
threadData.shared.value = []
|
||||||
|
|
||||||
|
def fileExistsThread():
|
||||||
|
threadData = getCurrentThreadData()
|
||||||
|
|
||||||
|
while kb.threadContinue:
|
||||||
|
kb.locks.count.acquire()
|
||||||
|
if threadData.shared.count < threadData.shared.limit:
|
||||||
|
path = paths[threadData.shared.count]
|
||||||
|
threadData.shared.count += 1
|
||||||
|
kb.locks.count.release()
|
||||||
|
else:
|
||||||
|
kb.locks.count.release()
|
||||||
|
break
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = unArrayizeValue(conf.dbmsHandler.readFile(path))
|
||||||
|
except SqlmapNoneDataException:
|
||||||
|
result = None
|
||||||
|
|
||||||
|
kb.locks.io.acquire()
|
||||||
|
|
||||||
|
if not isNoneValue(result):
|
||||||
|
threadData.shared.value.append(result)
|
||||||
|
|
||||||
|
if conf.verbose in (1, 2) and not conf.api:
|
||||||
|
clearConsoleLine(True)
|
||||||
|
infoMsg = "[%s] [INFO] retrieved: '%s'\n" % (time.strftime("%X"), path)
|
||||||
|
dataToStdout(infoMsg, True)
|
||||||
|
|
||||||
|
if conf.verbose in (1, 2):
|
||||||
|
status = '%d/%d items (%d%%)' % (threadData.shared.count, threadData.shared.limit, round(100.0 * threadData.shared.count / threadData.shared.limit))
|
||||||
|
dataToStdout("\r[%s] [INFO] tried %s" % (time.strftime("%X"), status), True)
|
||||||
|
|
||||||
|
kb.locks.io.release()
|
||||||
|
|
||||||
|
try:
|
||||||
|
pushValue(logger.getEffectiveLevel())
|
||||||
|
logger.setLevel(logging.CRITICAL)
|
||||||
|
|
||||||
|
runThreads(conf.threads, fileExistsThread, threadChoice=True)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
warnMsg = "user aborted during file existence "
|
||||||
|
warnMsg += "check. sqlmap will display partial output"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
finally:
|
||||||
|
kb.bruteMode = False
|
||||||
|
logger.setLevel(popValue())
|
||||||
|
|
||||||
|
clearConsoleLine(True)
|
||||||
|
dataToStdout("\n")
|
||||||
|
|
||||||
|
if not threadData.shared.value:
|
||||||
|
warnMsg = "no file(s) found"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
else:
|
||||||
|
retVal = threadData.shared.value
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
|
|
@ -78,7 +78,6 @@ from lib.core.enums import HASH
|
||||||
from lib.core.enums import MKSTEMP_PREFIX
|
from lib.core.enums import MKSTEMP_PREFIX
|
||||||
from lib.core.exception import SqlmapDataException
|
from lib.core.exception import SqlmapDataException
|
||||||
from lib.core.exception import SqlmapUserQuitException
|
from lib.core.exception import SqlmapUserQuitException
|
||||||
from lib.core.patch import resolveCrossReferences
|
|
||||||
from lib.core.settings import COMMON_PASSWORD_SUFFIXES
|
from lib.core.settings import COMMON_PASSWORD_SUFFIXES
|
||||||
from lib.core.settings import COMMON_USER_COLUMNS
|
from lib.core.settings import COMMON_USER_COLUMNS
|
||||||
from lib.core.settings import DEV_EMAIL_ADDRESS
|
from lib.core.settings import DEV_EMAIL_ADDRESS
|
||||||
|
|
|
@ -18,6 +18,7 @@ from lib.core.compat import xrange
|
||||||
from lib.core.convert import encodeBase64
|
from lib.core.convert import encodeBase64
|
||||||
from lib.core.convert import encodeHex
|
from lib.core.convert import encodeHex
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
from lib.core.enums import CHARSET_TYPE
|
from lib.core.enums import CHARSET_TYPE
|
||||||
from lib.core.enums import EXPECTED
|
from lib.core.enums import EXPECTED
|
||||||
|
@ -82,8 +83,9 @@ class Filesystem(GenericFilesystem):
|
||||||
return chunkName
|
return chunkName
|
||||||
|
|
||||||
def stackedReadFile(self, remoteFile):
|
def stackedReadFile(self, remoteFile):
|
||||||
infoMsg = "fetching file: '%s'" % remoteFile
|
if not kb.bruteMode:
|
||||||
logger.info(infoMsg)
|
infoMsg = "fetching file: '%s'" % remoteFile
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
txtTbl = self.fileTblName
|
txtTbl = self.fileTblName
|
||||||
|
|
|
@ -31,16 +31,18 @@ from plugins.generic.filesystem import Filesystem as GenericFilesystem
|
||||||
|
|
||||||
class Filesystem(GenericFilesystem):
|
class Filesystem(GenericFilesystem):
|
||||||
def nonStackedReadFile(self, rFile):
|
def nonStackedReadFile(self, rFile):
|
||||||
infoMsg = "fetching file: '%s'" % rFile
|
if not kb.bruteMode:
|
||||||
logger.info(infoMsg)
|
infoMsg = "fetching file: '%s'" % rFile
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
result = inject.getValue("HEX(LOAD_FILE('%s'))" % rFile, charsetType=CHARSET_TYPE.HEXADECIMAL)
|
result = inject.getValue("HEX(LOAD_FILE('%s'))" % rFile, charsetType=CHARSET_TYPE.HEXADECIMAL)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def stackedReadFile(self, remoteFile):
|
def stackedReadFile(self, remoteFile):
|
||||||
infoMsg = "fetching file: '%s'" % remoteFile
|
if not kb.bruteMode:
|
||||||
logger.info(infoMsg)
|
infoMsg = "fetching file: '%s'" % remoteFile
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
self.createSupportTbl(self.fileTblName, self.tblField, "longtext")
|
self.createSupportTbl(self.fileTblName, self.tblField, "longtext")
|
||||||
self.getRemoteTempPath()
|
self.getRemoteTempPath()
|
||||||
|
@ -64,8 +66,9 @@ class Filesystem(GenericFilesystem):
|
||||||
warnMsg += "file '%s'" % remoteFile
|
warnMsg += "file '%s'" % remoteFile
|
||||||
|
|
||||||
if conf.direct or isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION):
|
if conf.direct or isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION):
|
||||||
warnMsg += ", going to fall-back to simpler UNION technique"
|
if not kb.bruteMode:
|
||||||
logger.warn(warnMsg)
|
warnMsg += ", going to fall-back to simpler UNION technique"
|
||||||
|
logger.warn(warnMsg)
|
||||||
result = self.nonStackedReadFile(remoteFile)
|
result = self.nonStackedReadFile(remoteFile)
|
||||||
else:
|
else:
|
||||||
raise SqlmapNoneDataException(warnMsg)
|
raise SqlmapNoneDataException(warnMsg)
|
||||||
|
|
|
@ -32,8 +32,9 @@ class Filesystem(GenericFilesystem):
|
||||||
Request.queryPage(payload, content=False, raise404=False, silent=True, noteResponseTime=False)
|
Request.queryPage(payload, content=False, raise404=False, silent=True, noteResponseTime=False)
|
||||||
|
|
||||||
for remoteFile in remoteFile.split(','):
|
for remoteFile in remoteFile.split(','):
|
||||||
infoMsg = "fetching file: '%s'" % remoteFile
|
if not kb.bruteMode:
|
||||||
logger.info(infoMsg)
|
infoMsg = "fetching file: '%s'" % remoteFile
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
kb.fileReadMode = True
|
kb.fileReadMode = True
|
||||||
fileContent = inject.getValue("SELECT RAWTOHEX(OSREADFILE('%s')) FROM DUAL" % remoteFile, charsetType=CHARSET_TYPE.HEXADECIMAL)
|
fileContent = inject.getValue("SELECT RAWTOHEX(OSREADFILE('%s')) FROM DUAL" % remoteFile, charsetType=CHARSET_TYPE.HEXADECIMAL)
|
||||||
|
@ -42,10 +43,11 @@ class Filesystem(GenericFilesystem):
|
||||||
if not isNoneValue(fileContent):
|
if not isNoneValue(fileContent):
|
||||||
fileContent = decodeDbmsHexValue(fileContent, True)
|
fileContent = decodeDbmsHexValue(fileContent, True)
|
||||||
|
|
||||||
if fileContent:
|
if fileContent.strip():
|
||||||
localFilePath = dataToOutFile(remoteFile, fileContent)
|
localFilePath = dataToOutFile(remoteFile, fileContent)
|
||||||
localFilePaths.append(localFilePath)
|
localFilePaths.append(localFilePath)
|
||||||
else:
|
|
||||||
|
elif not kb.bruteMode:
|
||||||
errMsg = "no data retrieved"
|
errMsg = "no data retrieved"
|
||||||
logger.error(errMsg)
|
logger.error(errMsg)
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import os
|
||||||
|
|
||||||
from lib.core.common import randomInt
|
from lib.core.common import randomInt
|
||||||
from lib.core.compat import xrange
|
from lib.core.compat import xrange
|
||||||
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
from lib.core.exception import SqlmapUnsupportedFeatureException
|
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||||
from lib.core.settings import LOBLKSIZE
|
from lib.core.settings import LOBLKSIZE
|
||||||
|
@ -23,8 +24,9 @@ class Filesystem(GenericFilesystem):
|
||||||
GenericFilesystem.__init__(self)
|
GenericFilesystem.__init__(self)
|
||||||
|
|
||||||
def stackedReadFile(self, remoteFile):
|
def stackedReadFile(self, remoteFile):
|
||||||
infoMsg = "fetching file: '%s'" % remoteFile
|
if not kb.bruteMode:
|
||||||
logger.info(infoMsg)
|
infoMsg = "fetching file: '%s'" % remoteFile
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
self.initEnv()
|
self.initEnv()
|
||||||
|
|
||||||
|
|
|
@ -174,12 +174,13 @@ class Filesystem(object):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def askCheckReadFile(self, localFile, remoteFile):
|
def askCheckReadFile(self, localFile, remoteFile):
|
||||||
message = "do you want confirmation that the remote file '%s' " % remoteFile
|
if not kb.bruteMode:
|
||||||
message += "has been successfully downloaded from the back-end "
|
message = "do you want confirmation that the remote file '%s' " % remoteFile
|
||||||
message += "DBMS file system? [Y/n] "
|
message += "has been successfully downloaded from the back-end "
|
||||||
|
message += "DBMS file system? [Y/n] "
|
||||||
|
|
||||||
if readInput(message, default='Y', boolean=True):
|
if readInput(message, default='Y', boolean=True):
|
||||||
return self._checkFileLength(localFile, remoteFile, True)
|
return self._checkFileLength(localFile, remoteFile, True)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -255,7 +256,7 @@ class Filesystem(object):
|
||||||
if fileContent is not None:
|
if fileContent is not None:
|
||||||
fileContent = decodeDbmsHexValue(fileContent, True)
|
fileContent = decodeDbmsHexValue(fileContent, True)
|
||||||
|
|
||||||
if fileContent:
|
if fileContent.strip():
|
||||||
localFilePath = dataToOutFile(remoteFile, fileContent)
|
localFilePath = dataToOutFile(remoteFile, fileContent)
|
||||||
|
|
||||||
if not Backend.isDbms(DBMS.PGSQL):
|
if not Backend.isDbms(DBMS.PGSQL):
|
||||||
|
@ -269,7 +270,7 @@ class Filesystem(object):
|
||||||
localFilePath += " (size differs from remote file)"
|
localFilePath += " (size differs from remote file)"
|
||||||
|
|
||||||
localFilePaths.append(localFilePath)
|
localFilePaths.append(localFilePath)
|
||||||
else:
|
elif not kb.bruteMode:
|
||||||
errMsg = "no data retrieved"
|
errMsg = "no data retrieved"
|
||||||
logger.error(errMsg)
|
logger.error(errMsg)
|
||||||
|
|
||||||
|
|
|
@ -572,6 +572,10 @@ commonTables = False
|
||||||
# Valid: True or False
|
# Valid: True or False
|
||||||
commonColumns = False
|
commonColumns = False
|
||||||
|
|
||||||
|
# Check existence of common files.
|
||||||
|
# Valid: True or False
|
||||||
|
commonFiles = False
|
||||||
|
|
||||||
|
|
||||||
# These options can be used to create custom user-defined functions.
|
# These options can be used to create custom user-defined functions.
|
||||||
[User-defined function]
|
[User-defined function]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user