Fixes #3515 (and reimplements #1062)

This commit is contained in:
Miroslav Stampar 2019-03-05 12:24:41 +01:00
parent 59d97968a7
commit 3f6b53f5f3
4 changed files with 26 additions and 29 deletions

View File

@ -16,6 +16,7 @@ import hashlib
import httplib import httplib
import inspect import inspect
import json import json
import keyword
import locale import locale
import logging import logging
import ntpath import ntpath
@ -115,6 +116,7 @@ from lib.core.settings import DEV_EMAIL_ADDRESS
from lib.core.settings import DUMMY_USER_INJECTION from lib.core.settings import DUMMY_USER_INJECTION
from lib.core.settings import DYNAMICITY_BOUNDARY_LENGTH from lib.core.settings import DYNAMICITY_BOUNDARY_LENGTH
from lib.core.settings import ERROR_PARSING_REGEXES from lib.core.settings import ERROR_PARSING_REGEXES
from lib.core.settings import EVALCODE_ENCODED_PREFIX
from lib.core.settings import FILE_PATH_REGEXES from lib.core.settings import FILE_PATH_REGEXES
from lib.core.settings import FORCE_COOKIE_EXPIRATION_TIME from lib.core.settings import FORCE_COOKIE_EXPIRATION_TIME
from lib.core.settings import FORM_SEARCH_REGEX from lib.core.settings import FORM_SEARCH_REGEX
@ -4816,21 +4818,27 @@ 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("foo bar") >>> safeVariableNaming("class.id")
'foo__SAFE__20bar' 'EVAL_636c6173732e6964'
""" """
return re.sub(r"[^\w]", lambda match: "%s%02x" % (SAFE_VARIABLE_MARKER, ord(match.group(0))), 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"))
return value
def unsafeVariableNaming(value): def unsafeVariableNaming(value):
""" """
Returns unescaped safe-representation of a given variable name Returns unescaped safe-representation of a given variable name
>>> unsafeVariableNaming("foo__SAFE__20bar") >>> unsafeVariableNaming("EVAL_636c6173732e6964")
'foo bar' u'class.id'
""" """
return re.sub(r"%s([0-9a-f]{2})" % SAFE_VARIABLE_MARKER, lambda match: match.group(1).decode("hex"), value) if value.startswith(EVALCODE_ENCODED_PREFIX):
value = value[len(EVALCODE_ENCODED_PREFIX):].decode("hex").decode(UNICODE_ENCODING)
return value
def firstNotNone(*args): def firstNotNone(*args):
""" """

View File

@ -19,7 +19,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.3.4" VERSION = "1.3.3.5"
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)
@ -761,8 +761,8 @@ METASPLOIT_SESSION_TIMEOUT = 120
# Reference: http://www.postgresql.org/docs/9.0/static/catalog-pg-largeobject.html # Reference: http://www.postgresql.org/docs/9.0/static/catalog-pg-largeobject.html
LOBLKSIZE = 2048 LOBLKSIZE = 2048
# Suffix used to mark variables having keyword names # Prefix used to mark special variables (e.g. keywords, having special chars, etc.)
EVALCODE_KEYWORD_SUFFIX = "_KEYWORD" EVALCODE_ENCODED_PREFIX = "EVAL_"
# Reference: http://www.cookiecentral.com/faq/#3.5 # Reference: http://www.cookiecentral.com/faq/#3.5
NETSCAPE_FORMAT_HEADER_COOKIES = "# Netscape HTTP Cookie File." NETSCAPE_FORMAT_HEADER_COOKIES = "# Netscape HTTP Cookie File."

View File

@ -8,7 +8,6 @@ See the file 'LICENSE' for copying permission
import binascii import binascii
import compiler import compiler
import httplib import httplib
import keyword
import logging import logging
import re import re
import socket import socket
@ -92,7 +91,7 @@ from lib.core.settings import DEFAULT_CONTENT_TYPE
from lib.core.settings import DEFAULT_COOKIE_DELIMITER from lib.core.settings import DEFAULT_COOKIE_DELIMITER
from lib.core.settings import DEFAULT_GET_POST_DELIMITER from lib.core.settings import DEFAULT_GET_POST_DELIMITER
from lib.core.settings import DEFAULT_USER_AGENT from lib.core.settings import DEFAULT_USER_AGENT
from lib.core.settings import EVALCODE_KEYWORD_SUFFIX from lib.core.settings import EVALCODE_ENCODED_PREFIX
from lib.core.settings import HTTP_ACCEPT_HEADER_VALUE from lib.core.settings import HTTP_ACCEPT_HEADER_VALUE
from lib.core.settings import HTTP_ACCEPT_ENCODING_HEADER_VALUE from lib.core.settings import HTTP_ACCEPT_ENCODING_HEADER_VALUE
from lib.core.settings import MAX_CONNECTION_CHUNK_SIZE from lib.core.settings import MAX_CONNECTION_CHUNK_SIZE
@ -1070,7 +1069,6 @@ class Connect(object):
delimiter = conf.paramDel or DEFAULT_GET_POST_DELIMITER delimiter = conf.paramDel or DEFAULT_GET_POST_DELIMITER
variables = {"uri": uri, "lastPage": threadData.lastPage, "_locals": locals()} variables = {"uri": uri, "lastPage": threadData.lastPage, "_locals": locals()}
originals = {} originals = {}
keywords = keyword.kwlist
if not get and PLACE.URI in conf.parameters: if not get and PLACE.URI in conf.parameters:
query = urlparse.urlsplit(uri).query or "" query = urlparse.urlsplit(uri).query or ""
@ -1085,8 +1083,6 @@ class Connect(object):
if safeVariableNaming(name) != name: if safeVariableNaming(name) != name:
conf.evalCode = re.sub(r"\b%s\b" % re.escape(name), safeVariableNaming(name), conf.evalCode) conf.evalCode = re.sub(r"\b%s\b" % re.escape(name), safeVariableNaming(name), conf.evalCode)
name = safeVariableNaming(name) name = safeVariableNaming(name)
elif name in keywords:
name = "%s%s" % (name, EVALCODE_KEYWORD_SUFFIX)
value = urldecode(value, convall=True, spaceplus=(item == post and kb.postSpaceToPlus)) value = urldecode(value, convall=True, spaceplus=(item == post and kb.postSpaceToPlus))
variables[name] = value variables[name] = value
@ -1098,8 +1094,6 @@ class Connect(object):
if safeVariableNaming(name) != name: if safeVariableNaming(name) != name:
conf.evalCode = re.sub(r"\b%s\b" % re.escape(name), safeVariableNaming(name), conf.evalCode) conf.evalCode = re.sub(r"\b%s\b" % re.escape(name), safeVariableNaming(name), conf.evalCode)
name = safeVariableNaming(name) name = safeVariableNaming(name)
elif name in keywords:
name = "%s%s" % (name, EVALCODE_KEYWORD_SUFFIX)
value = urldecode(value, convall=True) value = urldecode(value, convall=True)
variables[name] = value variables[name] = value
@ -1109,20 +1103,20 @@ class Connect(object):
except SyntaxError as ex: except SyntaxError as ex:
if ex.text: if ex.text:
original = replacement = ex.text.strip() original = replacement = ex.text.strip()
if '=' in original: if '=' in original:
name, value = original.split('=', 1) name, value = original.split('=', 1)
name = name.strip() name = name.strip()
if safeVariableNaming(name) != name: if safeVariableNaming(name) != name:
replacement = re.sub(r"\b%s\b" % re.escape(name), safeVariableNaming(name), replacement) replacement = re.sub(r"\b%s\b" % re.escape(name), safeVariableNaming(name), replacement)
elif name in keywords:
replacement = re.sub(r"\b%s\b" % re.escape(name), "%s%s" % (name, EVALCODE_KEYWORD_SUFFIX), replacement)
else: else:
for _ in re.findall(r"[A-Za-z_]+", original)[::-1]: for _ in re.findall(r"[A-Za-z_]+", original)[::-1]:
if _ in keywords: if safeVariableNaming(_) != _:
replacement = replacement.replace(_, "%s%s" % (_, EVALCODE_KEYWORD_SUFFIX)) replacement = replacement.replace(_, safeVariableNaming(_))
break break
if original == replacement: if original == replacement:
conf.evalCode = conf.evalCode.replace(EVALCODE_KEYWORD_SUFFIX, "") conf.evalCode = conf.evalCode.replace(EVALCODE_ENCODED_PREFIX, "")
break break
else: else:
conf.evalCode = conf.evalCode.replace(getUnicode(ex.text.strip(), UNICODE_ENCODING), replacement) conf.evalCode = conf.evalCode.replace(getUnicode(ex.text.strip(), UNICODE_ENCODING), replacement)
@ -1135,11 +1129,6 @@ class Connect(object):
evaluateCode(conf.evalCode, variables) evaluateCode(conf.evalCode, variables)
for variable in list(variables.keys()): for variable in list(variables.keys()):
if variable.endswith(EVALCODE_KEYWORD_SUFFIX):
value = variables[variable]
del variables[variable]
variables[variable.replace(EVALCODE_KEYWORD_SUFFIX, "")] = value
if unsafeVariableNaming(variable) != variable: if unsafeVariableNaming(variable) != variable:
value = variables[variable] value = variables[variable]
del variables[variable] del variables[variable]

View File

@ -30,7 +30,7 @@ c1da277517c7ec4c23e953a51b51e203 lib/controller/handler.py
fb6be55d21a70765e35549af2484f762 lib/controller/__init__.py fb6be55d21a70765e35549af2484f762 lib/controller/__init__.py
ed7874be0d2d3802f3d20184f2b280d5 lib/core/agent.py ed7874be0d2d3802f3d20184f2b280d5 lib/core/agent.py
a932126e7d80e545c5d44af178d0bc0c lib/core/bigarray.py a932126e7d80e545c5d44af178d0bc0c lib/core/bigarray.py
9deec4762d61e057b6e069b2538bdcf8 lib/core/common.py 8996b4b377b859dc69de323416615f2f lib/core/common.py
de8d27ae6241163ff9e97aa9e7c51a18 lib/core/convert.py de8d27ae6241163ff9e97aa9e7c51a18 lib/core/convert.py
abcb1121eb56d3401839d14e8ed06b6e lib/core/data.py abcb1121eb56d3401839d14e8ed06b6e lib/core/data.py
00828c4455321b6987e3f882f4ef4f92 lib/core/datatype.py 00828c4455321b6987e3f882f4ef4f92 lib/core/datatype.py
@ -50,7 +50,7 @@ d5ef43fe3cdd6c2602d7db45651f9ceb lib/core/readlineng.py
7d8a22c582ad201f65b73225e4456170 lib/core/replication.py 7d8a22c582ad201f65b73225e4456170 lib/core/replication.py
3179d34f371e0295dd4604568fb30bcd lib/core/revision.py 3179d34f371e0295dd4604568fb30bcd lib/core/revision.py
d6269c55789f78cf707e09a0f5b45443 lib/core/session.py d6269c55789f78cf707e09a0f5b45443 lib/core/session.py
918a8651a9872a33ddb04f82ac3360c3 lib/core/settings.py 1cd62a025c607338eb55d673375b4444 lib/core/settings.py
4483b4a5b601d8f1c4281071dff21ecc lib/core/shell.py 4483b4a5b601d8f1c4281071dff21ecc lib/core/shell.py
10fd19b0716ed261e6d04f311f6f527c lib/core/subprocessng.py 10fd19b0716ed261e6d04f311f6f527c lib/core/subprocessng.py
43772ea73e9e3d446f782af591cb4eda lib/core/target.py 43772ea73e9e3d446f782af591cb4eda lib/core/target.py
@ -72,7 +72,7 @@ adcecd2d6a8667b22872a563eb83eac0 lib/parse/payloads.py
e4ea70bcd461f5176867dcd89d372386 lib/request/basicauthhandler.py e4ea70bcd461f5176867dcd89d372386 lib/request/basicauthhandler.py
b23163d485e0dbc038cbf1ba80be11da lib/request/basic.py b23163d485e0dbc038cbf1ba80be11da lib/request/basic.py
fc25d951217077fe655ed2a3a81552ae lib/request/comparison.py fc25d951217077fe655ed2a3a81552ae lib/request/comparison.py
3925fef5710ac4e96b85c808df1c2f6a lib/request/connect.py d2e7673ed4838a321b825ea1854ea2c0 lib/request/connect.py
43005bd6a78e9cf0f3ed2283a1cb122e lib/request/direct.py 43005bd6a78e9cf0f3ed2283a1cb122e lib/request/direct.py
2b7509ba38a667c61cefff036ec4ca6f lib/request/dns.py 2b7509ba38a667c61cefff036ec4ca6f lib/request/dns.py
ceac6b3bf1f726f8ff43c6814e9d7281 lib/request/httpshandler.py ceac6b3bf1f726f8ff43c6814e9d7281 lib/request/httpshandler.py