mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2026-08-04 14:55:40 +00:00
Minor patches
This commit is contained in:
parent
39d22d26c3
commit
3a680be4eb
11 changed files with 42 additions and 28 deletions
|
|
@ -1967,19 +1967,21 @@ def getLimitRange(count, plusOne=False):
|
||||||
|
|
||||||
if kb.dumpTable:
|
if kb.dumpTable:
|
||||||
if conf.limitStart and conf.limitStop and conf.limitStart > conf.limitStop:
|
if conf.limitStart and conf.limitStop and conf.limitStart > conf.limitStop:
|
||||||
limitStop = conf.limitStart
|
limitStop = min(conf.limitStart, count) # a '--start' beyond the table must not request out-of-range offsets (phantom rows)
|
||||||
limitStart = conf.limitStop
|
limitStart = conf.limitStop
|
||||||
reverse = True
|
reverse = True
|
||||||
else:
|
else:
|
||||||
if isinstance(conf.limitStop, int) and conf.limitStop > 0 and conf.limitStop < limitStop:
|
if isinstance(conf.limitStop, int) and conf.limitStop > 0 and conf.limitStop < limitStop:
|
||||||
limitStop = conf.limitStop
|
limitStop = conf.limitStop
|
||||||
|
|
||||||
if isinstance(conf.limitStart, int) and conf.limitStart > 0 and conf.limitStart <= limitStop:
|
# NOTE: no '<= limitStop' gate - a '--start' past the row count must yield an EMPTY range
|
||||||
|
# (correctly skipping past every row), not silently fall back to dumping the whole table
|
||||||
|
if isinstance(conf.limitStart, int) and conf.limitStart > 0:
|
||||||
limitStart = conf.limitStart
|
limitStart = conf.limitStart
|
||||||
|
|
||||||
retVal = xrange(limitStart, limitStop + 1) if plusOne else xrange(limitStart - 1, limitStop)
|
retVal = xrange(limitStart, limitStop + 1) if plusOne else xrange(limitStart - 1, limitStop)
|
||||||
|
|
||||||
if reverse:
|
if reverse and len(retVal): # len() guard: a clamped out-of-range '--start' can leave the range empty
|
||||||
retVal = xrange(retVal[-1], retVal[0] - 1, -1)
|
retVal = xrange(retVal[-1], retVal[0] - 1, -1)
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
|
||||||
|
|
@ -577,7 +577,7 @@ def getUnicode(value, encoding=None, noneToNull=False):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return six.text_type(value, encoding or (kb.get("pageEncoding") if kb.get("originalPage") else None) or UNICODE_ENCODING)
|
return six.text_type(value, encoding or (kb.get("pageEncoding") if kb.get("originalPage") else None) or UNICODE_ENCODING)
|
||||||
except UnicodeDecodeError:
|
except (UnicodeDecodeError, LookupError): # LookupError: an unknown/invalid encoding name must fall back, not crash
|
||||||
return six.text_type(value, UNICODE_ENCODING, errors="reversible")
|
return six.text_type(value, UNICODE_ENCODING, errors="reversible")
|
||||||
elif isListLike(value):
|
elif isListLike(value):
|
||||||
value = list(getUnicode(_, encoding, noneToNull) for _ in value)
|
value = list(getUnicode(_, encoding, noneToNull) for _ in value)
|
||||||
|
|
|
||||||
|
|
@ -520,7 +520,8 @@ def _setOpenApiTargets():
|
||||||
checkFile(conf.openApiFile)
|
checkFile(conf.openApiFile)
|
||||||
infoMsg = "parsing OpenAPI/Swagger specification from '%s'" % conf.openApiFile
|
infoMsg = "parsing OpenAPI/Swagger specification from '%s'" % conf.openApiFile
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
content = openFile(conf.openApiFile).read()
|
with openFile(conf.openApiFile) as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
tags = [_.strip() for _ in re.split(PARAMETER_SPLITTING_REGEX, conf.openApiTags) if _.strip()] if conf.openApiTags else None
|
tags = [_.strip() for _ in re.split(PARAMETER_SPLITTING_REGEX, conf.openApiTags) if _.strip()] if conf.openApiTags else None
|
||||||
if tags:
|
if tags:
|
||||||
|
|
@ -835,7 +836,8 @@ def _listTamperingFunctions():
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
for script in sorted(glob.glob(os.path.join(paths.SQLMAP_TAMPER_PATH, "*.py"))):
|
for script in sorted(glob.glob(os.path.join(paths.SQLMAP_TAMPER_PATH, "*.py"))):
|
||||||
content = openFile(script, 'r').read()
|
with openFile(script, 'r') as f:
|
||||||
|
content = f.read()
|
||||||
match = re.search(r'(?s)__priority__.+"""(.+)"""', content)
|
match = re.search(r'(?s)__priority__.+"""(.+)"""', content)
|
||||||
if match:
|
if match:
|
||||||
comment = match.group(1).strip()
|
comment = match.group(1).strip()
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ from lib.core.enums import OS
|
||||||
from thirdparty import six
|
from thirdparty import six
|
||||||
|
|
||||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||||
VERSION = "1.10.7.242"
|
VERSION = "1.10.7.243"
|
||||||
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)
|
||||||
|
|
@ -533,8 +533,11 @@ ERROR_PARSING_REGEXES = (
|
||||||
r'"(?:errmsg|errorMessage|reason|msg)"\s*:\s*"(?P<result>[^"]+)"' # generic JSON error-message field (NoSQL document/REST back-ends)
|
r'"(?:errmsg|errorMessage|reason|msg)"\s*:\s*"(?P<result>[^"]+)"' # generic JSON error-message field (NoSQL document/REST back-ends)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Regular expression used for parsing charset info from meta html headers
|
# Regular expression used for parsing charset info from meta html headers (Note: the tempered token
|
||||||
META_CHARSET_REGEX = r"""(?si)<head\b[^>]*>.*<meta[^>]+charset\s*=\s*["']?(?P<result>[^"'> ]+).*</head>"""
|
# '(?:(?!</head>).)*?' keeps the meta strictly INSIDE <head> - as the old trailing '.*</head>' did -
|
||||||
|
# while the bounded meta-attr scan '{0,300}?' keeps it LINEAR; the old greedy form went quadratic and
|
||||||
|
# hung for many minutes on an attacker-controlled body full of '<meta' tokens lacking '>'/'</head>')
|
||||||
|
META_CHARSET_REGEX = r"""(?si)<head\b[^>]*>(?:(?!</head>).)*?<meta[^>]{0,300}?charset\s*=\s*["']?(?P<result>[^"'> ]+)"""
|
||||||
|
|
||||||
# Regular expression used for parsing refresh info from meta html headers
|
# Regular expression used for parsing refresh info from meta html headers
|
||||||
META_REFRESH_REGEX = r'(?i)<meta http-equiv="?refresh"?[^>]+content="?[^">]+;\s*(url=)?["\']?(?P<result>[^\'">]+)'
|
META_REFRESH_REGEX = r'(?i)<meta http-equiv="?refresh"?[^>]+content="?[^">]+;\s*(url=)?["\']?(?P<result>[^\'">]+)'
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ def comparison(page, headers, code=None, getRatioValue=False, pageLength=None):
|
||||||
return _
|
return _
|
||||||
|
|
||||||
def _adjust(condition, getRatioValue):
|
def _adjust(condition, getRatioValue):
|
||||||
if not any((conf.string, conf.notString, conf.regexp, conf.code)):
|
if not any((conf.string, conf.notString, conf.regexp, conf.code, conf.lengths)):
|
||||||
# Negative logic approach is used in raw page comparison scheme as that what is "different" than original
|
# Negative logic approach is used in raw page comparison scheme as that what is "different" than original
|
||||||
# PAYLOAD.WHERE.NEGATIVE response is considered as True; in switch based approach negative logic is not
|
# PAYLOAD.WHERE.NEGATIVE response is considered as True; in switch based approach negative logic is not
|
||||||
# applied as that what is by user considered as True is that what is returned by the comparison mechanism
|
# applied as that what is by user considered as True is that what is returned by the comparison mechanism
|
||||||
|
|
|
||||||
|
|
@ -406,7 +406,8 @@ class Connect(object):
|
||||||
errMsg = "problem occurred while loading cookies from file '%s'" % conf.liveCookies
|
errMsg = "problem occurred while loading cookies from file '%s'" % conf.liveCookies
|
||||||
raise SqlmapValueException(errMsg)
|
raise SqlmapValueException(errMsg)
|
||||||
|
|
||||||
cookie = openFile(conf.liveCookies).read().strip()
|
with openFile(conf.liveCookies) as f:
|
||||||
|
cookie = f.read().strip()
|
||||||
cookie = re.sub(r"(?i)\ACookie:\s*", "", cookie)
|
cookie = re.sub(r"(?i)\ACookie:\s*", "", cookie)
|
||||||
|
|
||||||
if multipart:
|
if multipart:
|
||||||
|
|
@ -545,7 +546,8 @@ class Connect(object):
|
||||||
headers = forgeHeaders(auxHeaders, headers)
|
headers = forgeHeaders(auxHeaders, headers)
|
||||||
|
|
||||||
if kb.headersFile:
|
if kb.headersFile:
|
||||||
content = openFile(kb.headersFile, 'r').read()
|
with openFile(kb.headersFile, 'r') as f:
|
||||||
|
content = f.read()
|
||||||
for line in content.split("\n"):
|
for line in content.split("\n"):
|
||||||
line = getText(line.strip())
|
line = getText(line.strip())
|
||||||
if ':' in line:
|
if ':' in line:
|
||||||
|
|
|
||||||
|
|
@ -875,7 +875,8 @@ def download(taskid, target, filename):
|
||||||
|
|
||||||
if os.path.isfile(path):
|
if os.path.isfile(path):
|
||||||
logger.debug("(%s) Retrieved content of file %s" % (taskid, target))
|
logger.debug("(%s) Retrieved content of file %s" % (taskid, target))
|
||||||
content = openFile(path, "rb").read()
|
with openFile(path, "rb") as f:
|
||||||
|
content = f.read()
|
||||||
return jsonize({"success": True, "file": encodeBase64(content, binary=False)})
|
return jsonize({"success": True, "file": encodeBase64(content, binary=False)})
|
||||||
else:
|
else:
|
||||||
logger.warning("[%s] File does not exist %s" % (taskid, target))
|
logger.warning("[%s] File does not exist %s" % (taskid, target))
|
||||||
|
|
|
||||||
|
|
@ -1117,7 +1117,7 @@ def _bruteProcessVariantA(attack_info, hash_regex, suffix, retVal, proc_id, proc
|
||||||
word = word + suffix
|
word = word + suffix
|
||||||
|
|
||||||
try:
|
try:
|
||||||
current = __functions__[hash_regex](password=word, uppercase=False)
|
current = __functions__[hash_regex](password=getBytes(word, unsafe=False), uppercase=False)
|
||||||
|
|
||||||
if current in hashes:
|
if current in hashes:
|
||||||
for item in attack_info[:]:
|
for item in attack_info[:]:
|
||||||
|
|
@ -1195,7 +1195,7 @@ def _bruteProcessVariantB(user, hash_, kwargs, hash_regex, suffix, retVal, found
|
||||||
word = word + suffix
|
word = word + suffix
|
||||||
|
|
||||||
try:
|
try:
|
||||||
current = __functions__[hash_regex](password=word, uppercase=False, **kwargs)
|
current = __functions__[hash_regex](password=getBytes(word, unsafe=False), uppercase=False, **kwargs)
|
||||||
|
|
||||||
if hash_ == current:
|
if hash_ == current:
|
||||||
if hash_regex == HASH.ORACLE_OLD: # only for cosmetic purposes
|
if hash_regex == HASH.ORACLE_OLD: # only for cosmetic purposes
|
||||||
|
|
@ -1285,7 +1285,7 @@ def _bruteProcessVariantSalted(attack_info, hash_regex, suffix, retVal, proc_id,
|
||||||
((user, hash_), kwargs) = item
|
((user, hash_), kwargs) = item
|
||||||
|
|
||||||
try:
|
try:
|
||||||
current = __functions__[hash_regex](password=word, uppercase=False, **kwargs)
|
current = __functions__[hash_regex](password=getBytes(word, unsafe=False), uppercase=False, **kwargs)
|
||||||
|
|
||||||
if hash_ == current:
|
if hash_ == current:
|
||||||
retVal.put((user, hash_, word))
|
retVal.put((user, hash_, word))
|
||||||
|
|
|
||||||
|
|
@ -333,7 +333,9 @@ class Entries(object):
|
||||||
kb.data.dumpedTable[column] = {"length": len(column), "values": BigArray()}
|
kb.data.dumpedTable[column] = {"length": len(column), "values": BigArray()}
|
||||||
|
|
||||||
for entry in entries:
|
for entry in entries:
|
||||||
if entry is None or len(entry) == 0:
|
# skip a missing/empty ROW container, but NOT an empty-string CELL value
|
||||||
|
# (single-column dumps yield bare strings; len("")==0 must not drop the row)
|
||||||
|
if entry is None or (isListLike(entry) and len(entry) == 0):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if isinstance(entry, six.string_types):
|
if isinstance(entry, six.string_types):
|
||||||
|
|
|
||||||
|
|
@ -135,8 +135,9 @@ class Search(object):
|
||||||
query = agent.limitQuery(index, query, dbCond)
|
query = agent.limitQuery(index, query, dbCond)
|
||||||
|
|
||||||
value = unArrayizeValue(inject.getValue(query, union=False, error=False))
|
value = unArrayizeValue(inject.getValue(query, union=False, error=False))
|
||||||
value = safeSQLIdentificatorNaming(value)
|
if not isNoneValue(value): # guard (mirrors searchTable) so a failed retrieval can't push a None/garbage name
|
||||||
foundDbs.append(value)
|
value = safeSQLIdentificatorNaming(value)
|
||||||
|
foundDbs.append(value)
|
||||||
|
|
||||||
conf.dumper.lister("found databases", foundDbs)
|
conf.dumper.lister("found databases", foundDbs)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -627,17 +627,18 @@ class Users(object):
|
||||||
elif Backend.isDbms(DBMS.DB2):
|
elif Backend.isDbms(DBMS.DB2):
|
||||||
privs = privilege.split(',')
|
privs = privilege.split(',')
|
||||||
privilege = privs[0]
|
privilege = privs[0]
|
||||||
privs = privs[1]
|
if len(privs) > 1: # guard a comma-less privilege value (mirrors the inband path)
|
||||||
privs = list(privs.strip())
|
privs = privs[1]
|
||||||
i = 1
|
privs = list(privs.strip())
|
||||||
|
i = 1
|
||||||
|
|
||||||
for priv in privs:
|
for priv in privs:
|
||||||
if priv.upper() in ('Y', 'G'):
|
if priv.upper() in ('Y', 'G'):
|
||||||
for position, db2Priv in DB2_PRIVS.items():
|
for position, db2Priv in DB2_PRIVS.items():
|
||||||
if position == i:
|
if position == i:
|
||||||
privilege += ", " + db2Priv
|
privilege += ", " + db2Priv
|
||||||
|
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
privileges.add(privilege)
|
privileges.add(privilege)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue