mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2024-11-22 01:26:42 +03:00
More drei stuff
This commit is contained in:
parent
2791ea51ea
commit
ff968c2331
|
@ -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)
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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()):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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():
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user