More drei stuff

This commit is contained in:
Miroslav Stampar 2019-05-02 16:54:54 +02:00
parent 2791ea51ea
commit ff968c2331
13 changed files with 113 additions and 94 deletions

View File

@ -64,7 +64,9 @@ def safecharencode(value):
for char in SAFE_ENCODE_SLASH_REPLACEMENTS: for char in SAFE_ENCODE_SLASH_REPLACEMENTS:
retVal = retVal.replace(char, repr(char).strip('\'')) retVal = retVal.replace(char, repr(char).strip('\''))
retVal = reduce(lambda x, y: x + (y if (y in string.printable or isinstance(value, text_type) and ord(y) >= 160) else '\\x%02x' % ord(y)), retVal, type(value)()) for char in set(retVal):
if not (char in string.printable or isinstance(value, text_type) and ord(char) >= 160):
retVal = retVal.replace(char, '\\x%02x' % ord(char))
retVal = retVal.replace(SLASH_MARKER, "\\\\") retVal = retVal.replace(SLASH_MARKER, "\\\\")
retVal = retVal.replace(HEX_ENCODED_PREFIX_MARKER, HEX_ENCODED_PREFIX) retVal = retVal.replace(HEX_ENCODED_PREFIX_MARKER, HEX_ENCODED_PREFIX)

View File

@ -1377,7 +1377,7 @@ def checkWaf():
conf.timeout = IDS_WAF_CHECK_TIMEOUT conf.timeout = IDS_WAF_CHECK_TIMEOUT
try: try:
retVal = Request.queryPage(place=place, value=value, getRatioValue=True, noteResponseTime=False, silent=True, disableTampering=True)[1] < IDS_WAF_CHECK_RATIO retVal = (Request.queryPage(place=place, value=value, getRatioValue=True, noteResponseTime=False, silent=True, disableTampering=True)[1] or 0) < IDS_WAF_CHECK_RATIO
except SqlmapConnectionException: except SqlmapConnectionException:
retVal = True retVal = True
finally: finally:

View File

@ -11,6 +11,7 @@ import collections
import contextlib import contextlib
import copy import copy
import distutils import distutils
import functools
import getpass import getpass
import hashlib import hashlib
import inspect import inspect
@ -1849,7 +1850,7 @@ def safeFilepathEncode(filepath):
retVal = filepath retVal = filepath
if filepath and isinstance(filepath, six.text_type): if filepath and six.PY2 and isinstance(filepath, six.text_type):
retVal = filepath.encode(sys.getfilesystemencoding() or UNICODE_ENCODING) retVal = filepath.encode(sys.getfilesystemencoding() or UNICODE_ENCODING)
return retVal return retVal
@ -1929,8 +1930,8 @@ def getFilteredPageContent(page, onlyText=True, split=" "):
Returns filtered page content without script, style and/or comments Returns filtered page content without script, style and/or comments
or all HTML tags or all HTML tags
>>> getFilteredPageContent(u'<html><title>foobar</title><body>test</body></html>') >>> getFilteredPageContent(u'<html><title>foobar</title><body>test</body></html>') == "foobar test"
u'foobar test' True
""" """
retVal = page retVal = page
@ -1947,8 +1948,8 @@ def getPageWordSet(page):
""" """
Returns word set used in page content Returns word set used in page content
>>> sorted(getPageWordSet(u'<html><title>foobar</title><body>test</body></html>')) >>> sorted(getPageWordSet(u'<html><title>foobar</title><body>test</body></html>')) == [u'foobar', u'test']
[u'foobar', u'test'] True
""" """
retVal = set() retVal = set()
@ -2459,13 +2460,13 @@ def decodeHex(value):
True True
""" """
return bytes.fromhex(value) if hasattr(bytes, "fromhex") else value.decode("hex") return bytes.fromhex(getUnicode(value)) if hasattr(bytes, "fromhex") else value.decode("hex")
def getBytes(value, encoding=UNICODE_ENCODING, errors="strict"): def getBytes(value, encoding=UNICODE_ENCODING, errors="strict"):
""" """
Returns byte representation of provided Unicode value Returns byte representation of provided Unicode value
>>> getBytes(getUnicode("foo\x01\x83\xffbar")) == b"foo\x01\x83\xffbar" >>> getBytes(getUnicode(b"foo\\x01\\x83\\xffbar")) == b"foo\\x01\\x83\\xffbar"
True True
""" """
@ -2488,9 +2489,9 @@ def getOrds(value):
""" """
Returns ORD(...) representation of provided string value Returns ORD(...) representation of provided string value
>>> getOrds(u'fo\xf6bar') >>> getOrds(u'fo\\xf6bar')
[102, 111, 246, 98, 97, 114] [102, 111, 246, 98, 97, 114]
>>> getOrds(b"fo\xc3\xb6bar") >>> getOrds(b"fo\\xc3\\xb6bar")
[102, 111, 195, 182, 98, 97, 114] [102, 111, 195, 182, 98, 97, 114]
""" """
@ -2642,8 +2643,8 @@ def extractErrorMessage(page):
""" """
Returns reported error message from page if it founds one Returns reported error message from page if it founds one
>>> extractErrorMessage(u'<html><title>Test</title>\\n<b>Warning</b>: oci_parse() [function.oci-parse]: ORA-01756: quoted string not properly terminated<br><p>Only a test page</p></html>') >>> extractErrorMessage(u'<html><title>Test</title>\\n<b>Warning</b>: oci_parse() [function.oci-parse]: ORA-01756: quoted string not properly terminated<br><p>Only a test page</p></html>') == u'oci_parse() [function.oci-parse]: ORA-01756: quoted string not properly terminated'
u'oci_parse() [function.oci-parse]: ORA-01756: quoted string not properly terminated' True
""" """
retVal = None retVal = None
@ -2716,10 +2717,10 @@ def urldecode(value, encoding=None, unsafe="%%&=;+%s" % CUSTOM_INJECTION_MARK_CH
""" """
URL decodes given value URL decodes given value
>>> urldecode('AND%201%3E%282%2B3%29%23', convall=True) >>> urldecode('AND%201%3E%282%2B3%29%23', convall=True) == 'AND 1>(2+3)#'
u'AND 1>(2+3)#' True
>>> urldecode('AND%201%3E%282%2B3%29%23', convall=False) >>> urldecode('AND%201%3E%282%2B3%29%23', convall=False) == 'AND 1>(2%2B3)#'
u'AND 1>(2%2B3)#' True
""" """
result = value result = value
@ -2738,7 +2739,7 @@ def urldecode(value, encoding=None, unsafe="%%&=;+%s" % CUSTOM_INJECTION_MARK_CH
charset = set(string.printable) - set(unsafe) charset = set(string.printable) - set(unsafe)
def _(match): def _(match):
char = chr(ord(match.group(1).decode("hex"))) char = getUnicode(decodeHex(match.group(1)))
return char if char in charset else match.group(0) return char if char in charset else match.group(0)
if spaceplus: if spaceplus:
@ -3020,13 +3021,15 @@ def findDynamicContent(firstPage, secondPage):
prefix = prefix[-DYNAMICITY_BOUNDARY_LENGTH:] prefix = prefix[-DYNAMICITY_BOUNDARY_LENGTH:]
suffix = suffix[:DYNAMICITY_BOUNDARY_LENGTH] suffix = suffix[:DYNAMICITY_BOUNDARY_LENGTH]
infix = max(re.search(r"(?s)%s(.+)%s" % (re.escape(prefix), re.escape(suffix)), _) for _ in (firstPage, secondPage)).group(1) for _ in (firstPage, secondPage):
match = re.search(r"(?s)%s(.+)%s" % (re.escape(prefix), re.escape(suffix)), _)
if infix[0].isalnum(): if match:
prefix = trimAlphaNum(prefix) infix = match.group(1)
if infix[0].isalnum():
if infix[-1].isalnum(): prefix = trimAlphaNum(prefix)
suffix = trimAlphaNum(suffix) if infix[-1].isalnum():
suffix = trimAlphaNum(suffix)
break
kb.dynamicMarkings.append((prefix if prefix else None, suffix if suffix else None)) kb.dynamicMarkings.append((prefix if prefix else None, suffix if suffix else None))
@ -3557,7 +3560,7 @@ def getLatestRevision():
req = _urllib.request.Request(url="https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/lib/core/settings.py") req = _urllib.request.Request(url="https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/lib/core/settings.py")
try: try:
content = _urllib.request.urlopen(req).read() content = getUnicode(_urllib.request.urlopen(req).read())
retVal = extractRegexResult(r"VERSION\s*=\s*[\"'](?P<result>[\d.]+)", content) retVal = extractRegexResult(r"VERSION\s*=\s*[\"'](?P<result>[\d.]+)", content)
except: except:
pass pass
@ -4423,12 +4426,8 @@ def serializeObject(object_):
""" """
Serializes given object Serializes given object
>>> serializeObject([1, 2, 3, ('a', 'b')]) >>> type(serializeObject([1, 2, 3, ('a', 'b')])) == six.binary_type
'gAJdcQEoSwFLAksDVQFhVQFihnECZS4=' True
>>> serializeObject(None)
'gAJOLg=='
>>> serializeObject('foobar')
'gAJVBmZvb2JhcnEBLg=='
""" """
return base64pickle(object_) return base64pickle(object_)
@ -4668,7 +4667,10 @@ def prioritySortColumns(columns):
def _(column): def _(column):
return column and "id" in column.lower() return column and "id" in column.lower()
return sorted(sorted(columns, key=len), lambda x, y: -1 if _(x) and not _(y) else 1 if not _(x) and _(y) else 0) if six.PY2:
return sorted(sorted(columns, key=len), lambda x, y: -1 if _(x) and not _(y) else 1 if not _(x) and _(y) else 0)
else:
return sorted(sorted(columns, key=len), key=functools.cmp_to_key(lambda x, y: -1 if _(x) and not _(y) else 1 if not _(x) and _(y) else 0))
def getRequestHeader(request, name): def getRequestHeader(request, name):
""" """
@ -4975,12 +4977,12 @@ def safeVariableNaming(value):
""" """
Returns escaped safe-representation of a given variable name that can be used in Python evaluated code Returns escaped safe-representation of a given variable name that can be used in Python evaluated code
>>> safeVariableNaming("class.id") >>> safeVariableNaming("class.id") == "EVAL_636c6173732e6964"
'EVAL_636c6173732e6964' True
""" """
if value in keyword.kwlist or re.search(r"\A[^a-zA-Z]|[^\w]", value): if value in keyword.kwlist or re.search(r"\A[^a-zA-Z]|[^\w]", value):
value = "%s%s" % (EVALCODE_ENCODED_PREFIX, value.encode(UNICODE_ENCODING).encode("hex")) value = "%s%s" % (EVALCODE_ENCODED_PREFIX, getUnicode(binascii.hexlify(getBytes(value))))
return value return value
@ -4988,12 +4990,12 @@ def unsafeVariableNaming(value):
""" """
Returns unescaped safe-representation of a given variable name Returns unescaped safe-representation of a given variable name
>>> unsafeVariableNaming("EVAL_636c6173732e6964") >>> unsafeVariableNaming("EVAL_636c6173732e6964") == "class.id"
u'class.id' True
""" """
if value.startswith(EVALCODE_ENCODED_PREFIX): if value.startswith(EVALCODE_ENCODED_PREFIX):
value = value[len(EVALCODE_ENCODED_PREFIX):].decode("hex").decode(UNICODE_ENCODING) value = getUnicode(decodeHex(value[len(EVALCODE_ENCODED_PREFIX):]))
return value return value

View File

@ -162,6 +162,10 @@ class WichmannHill(random.Random):
z = (z + a) % 256 or 1 z = (z + a) % 256 or 1
self.__whseed(x, y, z) self.__whseed(x, y, z)
def patchHeaders(headers):
if not hasattr(headers, "headers"):
headers.headers = ["%s: %s\r\n" % (header, headers[header]) for header in headers]
# Reference: https://github.com/urllib3/urllib3/blob/master/src/urllib3/filepost.py # Reference: https://github.com/urllib3/urllib3/blob/master/src/urllib3/filepost.py
def choose_boundary(): def choose_boundary():
return uuid.uuid4().hex return uuid.uuid4().hex

View File

@ -11,6 +11,7 @@ except:
import pickle import pickle
import base64 import base64
import binascii
import json import json
import re import re
import sys import sys
@ -24,8 +25,8 @@ def base64decode(value):
""" """
Decodes string value from Base64 to plain format Decodes string value from Base64 to plain format
>>> base64decode('Zm9vYmFy') >>> base64decode('Zm9vYmFy') == b'foobar'
'foobar' True
""" """
return base64.b64decode(unicodeencode(value)) return base64.b64decode(unicodeencode(value))
@ -34,8 +35,8 @@ def base64encode(value):
""" """
Encodes string value from plain to Base64 format Encodes string value from plain to Base64 format
>>> base64encode('foobar') >>> base64encode('foobar') == b'Zm9vYmFy'
'Zm9vYmFy' True
""" """
return base64.b64encode(unicodeencode(value)) return base64.b64encode(unicodeencode(value))
@ -44,8 +45,8 @@ def base64pickle(value):
""" """
Serializes (with pickle) and encodes to Base64 format supplied (binary) value Serializes (with pickle) and encodes to Base64 format supplied (binary) value
>>> base64pickle('foobar') >>> base64unpickle(base64pickle([1, 2, 3])) == [1, 2, 3]
'gAJVBmZvb2JhcnEBLg==' True
""" """
retVal = None retVal = None
@ -68,8 +69,8 @@ def base64unpickle(value):
""" """
Decodes value from Base64 to plain format and deserializes (with pickle) its content Decodes value from Base64 to plain format and deserializes (with pickle) its content
>>> base64unpickle('gAJVBmZvb2JhcnEBLg==') >>> type(base64unpickle('gAJjX19idWlsdGluX18Kb2JqZWN0CnEBKYFxAi4=')) == object
'foobar' True
""" """
retVal = None retVal = None
@ -85,8 +86,8 @@ def hexdecode(value):
""" """
Decodes string value from hex to plain format Decodes string value from hex to plain format
>>> hexdecode('666f6f626172') >>> hexdecode('666f6f626172') == b'foobar'
'foobar' True
""" """
value = value.lower() value = value.lower()
@ -103,16 +104,12 @@ def hexencode(value, encoding=None):
""" """
Encodes string value from plain to hex format Encodes string value from plain to hex format
>>> hexencode('foobar') >>> hexencode('foobar') == b'666f6f626172'
'666f6f626172' True
""" """
retVal = unicodeencode(value, encoding) retVal = unicodeencode(value, encoding)
retVal = binascii.hexlify(retVal)
if six.PY2:
retVal = retVal.encode("hex")
else:
retVal = retVal.hex()
return retVal return retVal
@ -120,8 +117,8 @@ def unicodeencode(value, encoding=None):
""" """
Returns 8-bit string representation of the supplied unicode value Returns 8-bit string representation of the supplied unicode value
>>> unicodeencode(u'foobar') >>> unicodeencode(u'foobar') == b'foobar'
'foobar' True
""" """
retVal = value retVal = value
@ -138,8 +135,8 @@ def utf8encode(value):
""" """
Returns 8-bit string representation of the supplied UTF-8 value Returns 8-bit string representation of the supplied UTF-8 value
>>> utf8encode(u'foobar') >>> utf8encode(u'foobar') == b'foobar'
'foobar' True
""" """
return unicodeencode(value, "utf-8") return unicodeencode(value, "utf-8")
@ -148,11 +145,16 @@ def utf8decode(value):
""" """
Returns UTF-8 representation of the supplied 8-bit string representation Returns UTF-8 representation of the supplied 8-bit string representation
>>> utf8decode('foobar') >>> utf8decode(b'foobar')
u'foobar' u'foobar'
""" """
return value.decode("utf-8") retVal = value
if isinstance(value, six.binary_type):
retVal = value.decode("utf-8")
return retVal
def htmlunescape(value): def htmlunescape(value):
""" """
@ -217,8 +219,8 @@ def dejsonize(data):
""" """
Returns JSON deserialized data Returns JSON deserialized data
>>> dejsonize('{\\n "foo": "bar"\\n}') >>> dejsonize('{\\n "foo": "bar"\\n}') == {u'foo': u'bar'}
{u'foo': u'bar'} True
""" """
return json.loads(data) return json.loads(data)

View File

@ -1765,7 +1765,8 @@ def _cleanupOptions():
conf.string = decodeStringEscape(conf.string) conf.string = decodeStringEscape(conf.string)
if conf.getAll: if conf.getAll:
map(lambda _: conf.__setitem__(_, True), WIZARD.ALL) for _ in WIZARD.ALL:
conf.__setitem__(_, True)
if conf.noCast: if conf.noCast:
for _ in list(DUMP_REPLACEMENTS.keys()): for _ in list(DUMP_REPLACEMENTS.keys()):

View File

@ -17,7 +17,7 @@ from lib.core.enums import DBMS_DIRECTORY_NAME
from lib.core.enums import OS from lib.core.enums import OS
# sqlmap version (<major>.<minor>.<month>.<monthly commit>) # sqlmap version (<major>.<minor>.<month>.<monthly commit>)
VERSION = "1.3.5.3" VERSION = "1.3.5.4"
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)
@ -839,8 +839,8 @@ for key, value in os.environ.items():
def _reversible(ex): def _reversible(ex):
if isinstance(ex, UnicodeDecodeError): if isinstance(ex, UnicodeDecodeError):
if INVALID_UNICODE_PRIVATE_AREA: if INVALID_UNICODE_PRIVATE_AREA:
return ("".join(unichr(int('000f00%2x' % ord(_), 16)) for _ in ex.object[ex.start:ex.end]), ex.end) return (u"".join(unichr(int('000f00%2x' % (_ if isinstance(_, int) else ord(_)), 16)) for _ in ex.object[ex.start:ex.end]), ex.end)
else: else:
return ("".join(INVALID_UNICODE_CHAR_FORMAT % ord(_) for _ in ex.object[ex.start:ex.end]).decode(UNICODE_ENCODING), ex.end) return (u"".join(INVALID_UNICODE_CHAR_FORMAT % (_ if isinstance(_, int) else ord(_)) for _ in ex.object[ex.start:ex.end]), ex.end)
codecs.register_error("reversible", _reversible) codecs.register_error("reversible", _reversible)

View File

@ -58,6 +58,7 @@ from lib.core.common import wasLastResponseDelayed
from lib.core.common import unsafeVariableNaming from lib.core.common import unsafeVariableNaming
from lib.core.common import urldecode from lib.core.common import urldecode
from lib.core.common import urlencode from lib.core.common import urlencode
from lib.core.compat import patchHeaders
from lib.core.compat import xrange from lib.core.compat import xrange
from lib.core.data import conf from lib.core.data import conf
from lib.core.data import kb from lib.core.data import kb
@ -517,6 +518,7 @@ class Connect(object):
code = (code or conn.code) if conn.code == kb.originalCode else conn.code # do not override redirection code (for comparison purposes) code = (code or conn.code) if conn.code == kb.originalCode else conn.code # do not override redirection code (for comparison purposes)
responseHeaders = conn.info() responseHeaders = conn.info()
responseHeaders[URI_HTTP_HEADER] = conn.geturl() responseHeaders[URI_HTTP_HEADER] = conn.geturl()
patchHeaders(responseHeaders)
kb.serverHeader = responseHeaders.get(HTTP_HEADER.SERVER, kb.serverHeader) kb.serverHeader = responseHeaders.get(HTTP_HEADER.SERVER, kb.serverHeader)
else: else:
code = None code = None
@ -592,6 +594,7 @@ class Connect(object):
page = ex.read() if not skipRead else None page = ex.read() if not skipRead else None
responseHeaders = ex.info() responseHeaders = ex.info()
responseHeaders[URI_HTTP_HEADER] = ex.geturl() responseHeaders[URI_HTTP_HEADER] = ex.geturl()
patchHeaders(responseHeaders)
page = decodePage(page, responseHeaders.get(HTTP_HEADER.CONTENT_ENCODING), responseHeaders.get(HTTP_HEADER.CONTENT_TYPE)) page = decodePage(page, responseHeaders.get(HTTP_HEADER.CONTENT_ENCODING), responseHeaders.get(HTTP_HEADER.CONTENT_TYPE))
except socket.timeout: except socket.timeout:
warnMsg = "connection timed out while trying " warnMsg = "connection timed out while trying "
@ -1349,8 +1352,7 @@ class Connect(object):
kb.permissionFlag = True kb.permissionFlag = True
singleTimeWarnMessage("potential permission problems detected ('%s')" % message) singleTimeWarnMessage("potential permission problems detected ('%s')" % message)
if not hasattr(headers, "headers"): patchHeaders(headers)
headers.headers = ["%s: %s\r\n" % (header, headers[header]) for header in headers]
if content or response: if content or response:
return page, headers, code return page, headers, code

View File

@ -158,7 +158,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
length = None length = None
showEta = conf.eta and isinstance(length, int) showEta = conf.eta and isinstance(length, int)
numThreads = min(conf.threads, length) or 1 numThreads = min(conf.threads or 0, length or 0) or 1
if showEta: if showEta:
progress = ProgressBar(maxValue=length) progress = ProgressBar(maxValue=length)
@ -198,8 +198,10 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
else: else:
posValue = ord(hintValue[idx - 1]) posValue = ord(hintValue[idx - 1])
markingValue = "'%s'" % CHAR_INFERENCE_MARK
unescapedCharValue = unescaper.escape("'%s'" % decodeIntToUnicode(posValue))
forgedPayload = agent.extractPayload(payload) forgedPayload = agent.extractPayload(payload)
forgedPayload = safeStringFormat(forgedPayload.replace(INFERENCE_GREATER_CHAR, INFERENCE_EQUALS_CHAR), (expressionUnescaped, idx, posValue)) forgedPayload = safeStringFormat(forgedPayload.replace(INFERENCE_GREATER_CHAR, INFERENCE_EQUALS_CHAR), (expressionUnescaped, idx, posValue)).replace(markingValue, unescapedCharValue)
result = Request.queryPage(agent.replacePayload(payload, forgedPayload), timeBasedCompare=timeBasedCompare, raise404=False) result = Request.queryPage(agent.replacePayload(payload, forgedPayload), timeBasedCompare=timeBasedCompare, raise404=False)
incrementCounter(kb.technique) incrementCounter(kb.technique)
@ -293,12 +295,13 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
lastChar = [_ for _ in threadData.shared.value if _ is not None][-1] lastChar = [_ for _ in threadData.shared.value if _ is not None][-1]
except IndexError: except IndexError:
lastChar = None lastChar = None
if 'a' <= lastChar <= 'z': else:
position = charTbl.index(ord('a') - 1) # 96 if 'a' <= lastChar <= 'z':
elif 'A' <= lastChar <= 'Z': position = charTbl.index(ord('a') - 1) # 96
position = charTbl.index(ord('A') - 1) # 64 elif 'A' <= lastChar <= 'Z':
elif '0' <= lastChar <= '9': position = charTbl.index(ord('A') - 1) # 64
position = charTbl.index(ord('0') - 1) # 47 elif '0' <= lastChar <= '9':
position = charTbl.index(ord('0') - 1) # 47
except ValueError: except ValueError:
pass pass
finally: finally:
@ -633,7 +636,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
dataToStdout(filterControlChars(val)) dataToStdout(filterControlChars(val))
# some DBMSes (e.g. Firebird, DB2, etc.) have issues with trailing spaces # some DBMSes (e.g. Firebird, DB2, etc.) have issues with trailing spaces
if len(partialValue) > INFERENCE_BLANK_BREAK and partialValue[-INFERENCE_BLANK_BREAK:].isspace(): if Backend.getIdentifiedDbms() in (DBMS.FIREBIRD, DBMS.DB2, DBMS.MAXDB) and len(partialValue) > INFERENCE_BLANK_BREAK and partialValue[-INFERENCE_BLANK_BREAK:].isspace():
finalValue = partialValue[:-INFERENCE_BLANK_BREAK] finalValue = partialValue[:-INFERENCE_BLANK_BREAK]
break break
elif charsetType and partialValue[-1:].isspace(): elif charsetType and partialValue[-1:].isspace():

View File

@ -724,19 +724,20 @@ def attackDumpedTable():
def hashRecognition(value): def hashRecognition(value):
retVal = None retVal = None
isOracle, isMySQL = Backend.isDbms(DBMS.ORACLE), Backend.isDbms(DBMS.MYSQL) if six.PY2: # currently only supported on Python2
isOracle, isMySQL = Backend.isDbms(DBMS.ORACLE), Backend.isDbms(DBMS.MYSQL)
if isinstance(value, six.string_types): if isinstance(value, six.string_types):
for name, regex in getPublicTypeMembers(HASH): for name, regex in getPublicTypeMembers(HASH):
# Hashes for Oracle and old MySQL look the same hence these checks # Hashes for Oracle and old MySQL look the same hence these checks
if isOracle and regex == HASH.MYSQL_OLD or isMySQL and regex == HASH.ORACLE_OLD: if isOracle and regex == HASH.MYSQL_OLD or isMySQL and regex == HASH.ORACLE_OLD:
continue
elif regex == HASH.CRYPT_GENERIC:
if any((value.lower() == value, value.upper() == value)):
continue continue
elif re.match(regex, value): elif regex == HASH.CRYPT_GENERIC:
retVal = regex if any((value.lower() == value, value.upper() == value)):
break continue
elif re.match(regex, value):
retVal = regex
break
return retVal return retVal

View File

@ -34,6 +34,8 @@ def tamper(payload, **kwargs):
'1 AND A NOT BETWEEN 0 AND B--' '1 AND A NOT BETWEEN 0 AND B--'
>>> tamper('1 AND A = B--') >>> tamper('1 AND A = B--')
'1 AND A BETWEEN B AND B--' '1 AND A BETWEEN B AND B--'
>>> tamper('1 AND LAST_INSERT_ROWID()=LAST_INSERT_ROWID()')
'1 AND LAST_INSERT_ROWID() BETWEEN LAST_INSERT_ROWID() AND LAST_INSERT_ROWID()'
""" """
retVal = payload retVal = payload
@ -48,7 +50,7 @@ def tamper(payload, **kwargs):
retVal = re.sub(r"\s*>\s*(\d+|'[^']+'|\w+\(\d+\))", r" NOT BETWEEN 0 AND \g<1>", payload) retVal = re.sub(r"\s*>\s*(\d+|'[^']+'|\w+\(\d+\))", r" NOT BETWEEN 0 AND \g<1>", payload)
if retVal == payload: if retVal == payload:
match = re.search(r"(?i)(\b(AND|OR)\b\s+)(?!.*\b(AND|OR)\b)([^=]+?)\s*=\s*(\w+)\s*", payload) match = re.search(r"(?i)(\b(AND|OR)\b\s+)(?!.*\b(AND|OR)\b)([^=]+?)\s*=\s*([\w()]+)\s*", payload)
if match: if match:
_ = "%s %s BETWEEN %s AND %s" % (match.group(2), match.group(4), match.group(5), match.group(5)) _ = "%s %s BETWEEN %s AND %s" % (match.group(2), match.group(4), match.group(5), match.group(5))

View File

@ -8,6 +8,7 @@ See the file 'LICENSE' for copying permission
import re import re
from lib.core.common import decodeHex from lib.core.common import decodeHex
from lib.core.common import getOrds
from lib.core.enums import PRIORITY from lib.core.enums import PRIORITY
__priority__ = PRIORITY.NORMAL __priority__ = PRIORITY.NORMAL
@ -37,7 +38,7 @@ def tamper(payload, **kwargs):
if payload: if payload:
for match in re.finditer(r"\b0x([0-9a-f]+)\b", retVal): for match in re.finditer(r"\b0x([0-9a-f]+)\b", retVal):
if len(match.group(1)) > 2: if len(match.group(1)) > 2:
result = "CONCAT(%s)" % ','.join("CHAR(%d)" % ord(_) for _ in decodeHex(match.group(1))) result = "CONCAT(%s)" % ','.join("CHAR(%d)" % _ for _ in getOrds(decodeHex(match.group(1))))
else: else:
result = "CHAR(%d)" % ord(decodeHex(match.group(1))) result = "CHAR(%d)" % ord(decodeHex(match.group(1)))
retVal = retVal.replace(match.group(0), result) retVal = retVal.replace(match.group(0), result)

View File

@ -6,7 +6,6 @@ See the file 'LICENSE' for copying permission
""" """
import re import re
import urllib
from lib.core.enums import PRIORITY from lib.core.enums import PRIORITY
@ -26,6 +25,6 @@ def tamper(payload, **kwargs):
retVal = payload retVal = payload
if payload: if payload:
retVal = re.sub(r"(?i)\bAND\b", urllib.quote("&&"), re.sub(r"(?i)\bOR\b", urllib.quote("||"), payload)) retVal = re.sub(r"(?i)\bAND\b", "%26%26", re.sub(r"(?i)\bOR\b", "%7C%7C", payload))
return retVal return retVal