Update (drei)

This commit is contained in:
Miroslav Stampar 2019-04-30 13:20:31 +02:00
parent 70168855f9
commit 1e03b23ccb
11 changed files with 104 additions and 98 deletions

View File

@ -315,7 +315,10 @@ class Agent(object):
("[HASH_REPLACE]", kb.chars.hash_),
("[GENERIC_SQL_COMMENT]", GENERIC_SQL_COMMENT)
)
payload = reduce(lambda x, y: x.replace(y[0], y[1]), replacements, payload)
for value in re.findall(r"\[[A-Z_]+\]", payload):
if value in replacements:
payload = payload.replace(value, replacements[value])
for _ in set(re.findall(r"(?i)\[RANDNUM(?:\d+)?\]", payload)):
payload = payload.replace(_, str(randomInt()))

View File

@ -950,16 +950,11 @@ def dataToStdout(data, forceOutput=False, bold=False, content_type=None, status=
if multiThreadMode:
logging._acquireLock()
if isinstance(data, six.text_type):
message = stdoutencode(data)
else:
message = data
try:
if conf.get("api"):
sys.stdout.write(clearColors(message), status, content_type)
sys.stdout.write(stdoutencode(clearColors(data)), status, content_type)
else:
sys.stdout.write(setColor(message, bold=bold))
sys.stdout.write(stdoutencode(setColor(data, bold=bold)))
sys.stdout.flush()
except IOError:
@ -1069,7 +1064,7 @@ def readInput(message, default=None, checkBatch=True, boolean=False):
elif default:
options = getUnicode(default, UNICODE_ENCODING)
else:
options = unicode()
options = six.text_type()
dataToStdout("%s%s\n" % (message, options), forceOutput=not kb.wizardMode, bold=True)
@ -1113,9 +1108,8 @@ def randomRange(start=0, stop=1000, seed=None):
"""
Returns random integer value in given range
>>> random.seed(0)
>>> randomRange(1, 500)
423
>>> randomRange(1, 500, seed=0)
9
"""
if seed is not None:
@ -1131,9 +1125,8 @@ def randomInt(length=4, seed=None):
"""
Returns random integer value with provided number of digits
>>> random.seed(0)
>>> randomInt(6)
874254
>>> randomInt(6, seed=0)
181911
"""
if seed is not None:
@ -1149,9 +1142,8 @@ def randomStr(length=4, lowercase=False, alphabet=None, seed=None):
"""
Returns random string value with provided number of characters
>>> random.seed(0)
>>> randomStr(6)
'RNvnAv'
>>> randomStr(6, seed=0)
'aUfWgj'
"""
if seed is not None:
@ -1174,8 +1166,8 @@ def sanitizeStr(value):
"""
Sanitizes string value in respect to newline and line-feed characters
>>> sanitizeStr('foo\\n\\rbar')
u'foo bar'
>>> sanitizeStr('foo\\n\\rbar') == 'foo bar'
True
"""
return getUnicode(value).replace("\n", " ").replace("\r", "")
@ -2096,8 +2088,8 @@ def shellExec(cmd):
"""
Executes arbitrary shell command
>>> shellExec('echo 1').strip()
'1'
>>> shellExec('echo 1').strip() == b'1'
True
"""
try:
@ -2420,12 +2412,10 @@ def getUnicode(value, encoding=None, noneToNull=False):
"""
Return the unicode representation of the supplied value:
>>> getUnicode(u'test')
u'test'
>>> getUnicode('test')
u'test'
>>> getUnicode(1)
u'1'
>>> getUnicode('test') == u'test'
True
>>> getUnicode(1) == u'1'
True
"""
if noneToNull and value is None:
@ -2436,11 +2426,11 @@ def getUnicode(value, encoding=None, noneToNull=False):
elif isinstance(value, six.binary_type):
# Heuristics (if encoding not explicitly specified)
candidates = filterNone((encoding, kb.get("pageEncoding") if kb.get("originalPage") else None, conf.get("encoding"), UNICODE_ENCODING, sys.getfilesystemencoding()))
if all(_ in value for _ in ('<', '>')):
if all(_ in value for _ in (b'<', b'>')):
pass
elif any(_ in value for _ in (":\\", '/', '.')) and '\n' not in value:
elif any(_ in value for _ in (b":\\", b'/', b'.')) and b'\n' not in value:
candidates = filterNone((encoding, sys.getfilesystemencoding(), kb.get("pageEncoding") if kb.get("originalPage") else None, UNICODE_ENCODING, conf.get("encoding")))
elif conf.get("encoding") and '\n' not in value:
elif conf.get("encoding") and b'\n' not in value:
candidates = filterNone((encoding, conf.get("encoding"), kb.get("pageEncoding") if kb.get("originalPage") else None, sys.getfilesystemencoding(), UNICODE_ENCODING))
for candidate in candidates:
@ -2708,6 +2698,8 @@ def urldecode(value, encoding=None, unsafe="%%&=;+%s" % CUSTOM_INJECTION_MARK_CH
>>> urldecode('AND%201%3E%282%2B3%29%23', convall=True)
u'AND 1>(2+3)#'
>>> urldecode('AND%201%3E%282%2B3%29%23', convall=False)
u'AND 1>(2%2B3)#'
"""
result = value
@ -2722,17 +2714,19 @@ def urldecode(value, encoding=None, unsafe="%%&=;+%s" % CUSTOM_INJECTION_MARK_CH
if convall:
result = _urllib.parse.unquote_plus(value) if spaceplus else _urllib.parse.unquote(value)
else:
result = value
charset = set(string.printable) - set(unsafe)
def _(match):
charset = reduce(lambda x, y: x.replace(y, ""), unsafe, string.printable)
char = chr(ord(match.group(1).decode("hex")))
return char if char in charset else match.group(0)
result = value
if spaceplus:
result = result.replace('+', ' ') # plus sign has a special meaning in URL encoded data (hence the usage of _urllib.parse.unquote_plus in convall case)
result = re.sub(r"%([0-9a-fA-F]{2})", _, result)
if isinstance(result, str):
result = unicode(result, encoding or UNICODE_ENCODING, "replace")
result = getUnicode(result, encoding or UNICODE_ENCODING)
return result
@ -2893,8 +2887,8 @@ def extractTextTagContent(page):
"""
Returns list containing content from "textual" tags
>>> extractTextTagContent(u'<html><head><title>Title</title></head><body><pre>foobar</pre><a href="#link">Link</a></body></html>')
[u'Title', u'foobar']
>>> extractTextTagContent('<html><head><title>Title</title></head><body><pre>foobar</pre><a href="#link">Link</a></body></html>')
['Title', 'foobar']
"""
page = page or ""
@ -2911,8 +2905,8 @@ def trimAlphaNum(value):
"""
Trims alpha numeric characters from start and ending of a given value
>>> trimAlphaNum(u'AND 1>(2+3)-- foobar')
u' 1>(2+3)-- '
>>> trimAlphaNum('AND 1>(2+3)-- foobar')
' 1>(2+3)-- '
"""
while value and value[-1].isalnum():
@ -3043,8 +3037,8 @@ def filterStringValue(value, charRegex, replacement=""):
Returns string value consisting only of chars satisfying supplied
regular expression (note: it has to be in form [...])
>>> filterStringValue(u'wzydeadbeef0123#', r'[0-9a-f]')
u'deadbeef0123'
>>> filterStringValue('wzydeadbeef0123#', r'[0-9a-f]')
'deadbeef0123'
"""
retVal = value
@ -3058,8 +3052,8 @@ def filterControlChars(value, replacement=' '):
"""
Returns string value with control chars being supstituted with replacement character
>>> filterControlChars(u'AND 1>(2+3)\\n--')
u'AND 1>(2+3) --'
>>> filterControlChars('AND 1>(2+3)\\n--')
'AND 1>(2+3) --'
"""
return filterStringValue(value, PRINTABLE_CHAR_REGEX, replacement)
@ -3281,8 +3275,8 @@ def arrayizeValue(value):
"""
Makes a list out of value if it is not already a list or tuple itself
>>> arrayizeValue(u'1')
[u'1']
>>> arrayizeValue('1')
['1']
"""
if not isListLike(value):
@ -3294,8 +3288,8 @@ def unArrayizeValue(value):
"""
Makes a value out of iterable if it is a list or tuple itself
>>> unArrayizeValue([u'1'])
u'1'
>>> unArrayizeValue(['1'])
'1'
"""
if isListLike(value):
@ -3313,8 +3307,8 @@ def flattenValue(value):
"""
Returns an iterator representing flat representation of a given value
>>> [_ for _ in flattenValue([[u'1'], [[u'2'], u'3']])]
[u'1', u'2', u'3']
>>> [_ for _ in flattenValue([['1'], [['2'], '3']])]
['1', '2', '3']
"""
for i in iter(value):
@ -3330,7 +3324,7 @@ def isListLike(value):
>>> isListLike([1, 2, 3])
True
>>> isListLike(u'2')
>>> isListLike('2')
False
"""
@ -3373,7 +3367,7 @@ def filterListValue(value, regex):
"""
if isinstance(value, list) and regex:
retVal = filter(lambda _: re.search(regex, _, re.I), value)
retVal = [_ for _ in value if re.search(regex, _, re.I)]
else:
retVal = value
@ -3416,10 +3410,10 @@ def decodeIntToUnicode(value):
"""
Decodes inferenced integer value to an unicode character
>>> decodeIntToUnicode(35)
u'#'
>>> decodeIntToUnicode(64)
u'@'
>>> decodeIntToUnicode(35) == '#'
True
>>> decodeIntToUnicode(64) == '@'
True
"""
retVal = value
@ -3818,8 +3812,8 @@ def normalizeUnicode(value):
# Reference: http://www.peterbe.com/plog/unicode-to-ascii
>>> normalizeUnicode(u'\u0161u\u0107uraj')
'sucuraj'
>>> normalizeUnicode(u'\u0161u\u0107uraj') == b'sucuraj'
True
"""
return unicodedata.normalize("NFKD", value).encode("ascii", "ignore") if isinstance(value, six.text_type) else value
@ -4017,10 +4011,10 @@ def safeCSValue(value):
# Reference: http://tools.ietf.org/html/rfc4180
>>> safeCSValue(u'foo, bar')
u'"foo, bar"'
>>> safeCSValue(u'foobar')
u'foobar'
>>> safeCSValue('foo, bar')
'"foo, bar"'
>>> safeCSValue('foobar')
'foobar'
"""
retVal = value
@ -4043,7 +4037,7 @@ def filterPairValues(values):
retVal = []
if not isNoneValue(values) and hasattr(values, '__iter__'):
retVal = filter(lambda x: isinstance(x, (tuple, list, set)) and len(x) == 2, values)
retVal = [value for value in values if isinstance(value, (tuple, list, set)) and len(value) == 2]
return retVal
@ -4469,10 +4463,10 @@ def decodeHexValue(value, raw=False):
"""
Returns value decoded from DBMS specific hexadecimal representation
>>> decodeHexValue('3132332031')
u'123 1'
>>> decodeHexValue(['0x31', '0x32'])
[u'1', u'2']
>>> decodeHexValue('3132332031') == u'123 1'
True
>>> decodeHexValue(['0x31', '0x32']) == [u'1', u'2']
True
"""
retVal = value
@ -4930,8 +4924,8 @@ def getSafeExString(ex, encoding=None):
Safe way how to get the proper exception represtation as a string
(Note: errors to be avoided: 1) "%s" % Exception(u'\u0161') and 2) "%s" % str(Exception(u'\u0161'))
>>> getSafeExString(SqlmapBaseException('foobar'))
u'foobar'
>>> getSafeExString(SqlmapBaseException('foobar')) == 'foobar'
True
"""
retVal = None

View File

@ -163,8 +163,10 @@ def htmlunescape(value):
retVal = value
if value and isinstance(value, six.string_types):
codes = (("&lt;", '<'), ("&gt;", '>'), ("&quot;", '"'), ("&nbsp;", ' '), ("&amp;", '&'), ("&apos;", "'"))
retVal = reduce(lambda x, y: x.replace(y[0], y[1]), codes, retVal)
replacements = (("&lt;", '<'), ("&gt;", '>'), ("&quot;", '"'), ("&nbsp;", ' '), ("&amp;", '&'), ("&apos;", "'"))
for code, value in replacements:
retVal = retVal.replace(code, value)
try:
retVal = re.sub(r"&#x([^ ;]+);", lambda match: unichr(int(match.group(1), 16)), retVal)
except ValueError:
@ -177,25 +179,26 @@ def singleTimeWarnMessage(message): # Cross-referenced function
sys.stdout.flush()
def stdoutencode(data):
retVal = None
retVal = data
try:
retVal = unicodeencode(data or "", sys.stdout.encoding)
if six.PY2:
try:
retVal = unicodeencode(data or "", sys.stdout.encoding)
# Reference: http://bugs.python.org/issue1602
if IS_WIN:
if '?' in retVal and '?' not in retVal:
warnMsg = "cannot properly display Unicode characters "
warnMsg += "inside Windows OS command prompt "
warnMsg += "(http://bugs.python.org/issue1602). All "
warnMsg += "unhandled occurrences will result in "
warnMsg += "replacement with '?' character. Please, find "
warnMsg += "proper character representation inside "
warnMsg += "corresponding output files. "
singleTimeWarnMessage(warnMsg)
# Reference: http://bugs.python.org/issue1602
if IS_WIN:
if '?' in retVal and '?' not in retVal:
warnMsg = "cannot properly display Unicode characters "
warnMsg += "inside Windows OS command prompt "
warnMsg += "(http://bugs.python.org/issue1602). All "
warnMsg += "unhandled occurrences will result in "
warnMsg += "replacement with '?' character. Please, find "
warnMsg += "proper character representation inside "
warnMsg += "corresponding output files. "
singleTimeWarnMessage(warnMsg)
except:
retVal = unicodeencode(data or "")
except:
retVal = unicodeencode(data or "")
return retVal

View File

@ -10,6 +10,7 @@ import hashlib
import threading
from lib.core.settings import MAX_CACHE_ITEMS
from lib.core.settings import UNICODE_ENCODING
from lib.core.datatype import LRUDict
from lib.core.threads import getCurrentThreadData
@ -24,7 +25,7 @@ def cachedmethod(f, cache=LRUDict(capacity=MAX_CACHE_ITEMS)):
@functools.wraps(f)
def _(*args, **kwargs):
key = int(hashlib.md5("|".join(str(_) for _ in (f, args, kwargs))).hexdigest(), 16) & 0x7fffffffffffffff
key = int(hashlib.md5("|".join(str(_) for _ in (f, args, kwargs)).encode(UNICODE_ENCODING)).hexdigest(), 16) & 0x7fffffffffffffff
try:
with _lock:

View File

@ -17,7 +17,7 @@ from lib.core.enums import DBMS_DIRECTORY_NAME
from lib.core.enums import OS
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
VERSION = "1.3.4.47"
VERSION = "1.3.4.48"
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
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)

View File

@ -73,6 +73,8 @@ def vulnTest():
("--technique=T --fresh-queries --sql-query='SELECT 1234'", (": '1234'",)),
):
output = shellExec("python %s -u http://%s:%d/?id=1 --batch %s" % (os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.py"), address, port, options))
output = getUnicode(output)
if not all(check in output for check in checks):
retVal = False

View File

@ -762,7 +762,7 @@ def cmdLineParser(argv=None):
return retVal
parser.formatter._format_option_strings = parser.formatter.format_option_strings
parser.formatter.format_option_strings = type(parser.formatter.format_option_strings)(_, parser, type(parser))
parser.formatter.format_option_strings = type(parser.formatter.format_option_strings)(_, parser)
# Dirty hack for making a short option '-hh'
option = parser.get_option("--hh")

View File

@ -12,19 +12,19 @@ class xrange(object):
Advanced (re)implementation of xrange (supports slice/copy/etc.)
Reference: http://code.activestate.com/recipes/521885-a-pythonic-implementation-of-xrange/
>>> list(xrange(1, 9)) == range(1, 9)
>>> list(xrange(1, 9)) == list(range(1, 9))
True
>>> list(xrange(8, 0, -16)) == range(8, 0, -16)
>>> list(xrange(8, 0, -16)) == list(range(8, 0, -16))
True
>>> list(xrange(0, 8, 16)) == range(0, 8, 16)
>>> list(xrange(0, 8, 16)) == list(range(0, 8, 16))
True
>>> list(xrange(0, 4, 5)) == range(0, 4, 5)
>>> list(xrange(0, 4, 5)) == list(range(0, 4, 5))
True
>>> list(xrange(4, 0, 3)) == range(4, 0, 3)
>>> list(xrange(4, 0, 3)) == list(range(4, 0, 3))
True
>>> list(xrange(0, -3)) == range(0, -3)
>>> list(xrange(0, -3)) == list(range(0, -3))
True
>>> list(xrange(0, 7, 2)) == range(0, 7, 2)
>>> list(xrange(0, 7, 2)) == list(range(0, 7, 2))
True
>>> foobar = xrange(1, 10)
>>> 7 in foobar

View File

@ -408,6 +408,9 @@ if __name__ == "__main__":
main()
except KeyboardInterrupt:
pass
except:
if int(os.environ.get("SQLMAP_DREI", 0)):
traceback.print_exc()
finally:
# Reference: http://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program
if threading.activeCount() > 1:

View File

@ -32,6 +32,6 @@ def tamper(payload, **kwargs):
hints = kwargs.get("hints", {})
delimiter = kwargs.get("delimiter", DEFAULT_GET_POST_DELIMITER)
hints[HINT.PREPEND] = delimiter.join("%s=" % "".join(random.sample(string.letters + string.digits, 2)) for _ in xrange(500))
hints[HINT.PREPEND] = delimiter.join("%s=" % "".join(random.sample(string.ascii_letters + string.digits, 2)) for _ in xrange(500))
return payload

View File

@ -573,7 +573,7 @@ In practice, you would read the password using something like the
getpass module, and generate the salt randomly:
>>> import random, string
>>> saltchars = string.letters + string.digits + './'
>>> saltchars = string.ascii_letters + string.digits + './'
>>> salt = random.choice(saltchars) + random.choice(saltchars)
Note that other ASCII characters are accepted in the salt, but the