diff --git a/lib/core/option.py b/lib/core/option.py index ebad2b6c2..7f38508e9 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -104,6 +104,7 @@ from lib.core.settings import LOCALHOST from lib.core.settings import MAX_NUMBER_OF_THREADS from lib.core.settings import PARAMETER_SPLITTING_REGEX from lib.core.settings import TIME_DELAY_CANDIDATES +from lib.core.settings import UNENCODED_ORIGINAL_VALUE from lib.core.settings import UNION_CHAR_REGEX from lib.core.settings import UNKNOWN_DBMS_VERSION from lib.core.settings import WEBSCARAB_SPLITTER @@ -1322,7 +1323,13 @@ def __cleanupOptions(): setOptimize() if conf.data: - conf.data = urldecode(conf.data) + if re.search(r'%[0-9a-f]{2}', conf.data, re.I): + original = conf.data + class _(unicode): pass + conf.data = _(urldecode(conf.data)) + setattr(conf.data, UNENCODED_ORIGINAL_VALUE, original) + else: + conf.data = urldecode(conf.data) if conf.os: conf.os = conf.os.capitalize() diff --git a/lib/core/settings.py b/lib/core/settings.py index 1f56cfae9..ba004c92e 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -400,3 +400,6 @@ PARAMETER_SPLITTING_REGEX = r'[,|;]' # Regular expression describing possible union char value (e.g. used in --union-char) UNION_CHAR_REGEX = r'\A\w+\Z' + +# Attribute used for storing original parameter value in special cases (e.g. POST) +UNENCODED_ORIGINAL_VALUE = 'original' \ No newline at end of file diff --git a/lib/core/target.py b/lib/core/target.py index 391b1539d..6e7ee339a 100644 --- a/lib/core/target.py +++ b/lib/core/target.py @@ -36,6 +36,7 @@ from lib.core.session import resumeConfKb from lib.core.settings import REFERER_ALIASES from lib.core.settings import RESULTS_FILE_FORMAT from lib.core.settings import SOAP_REGEX +from lib.core.settings import UNENCODED_ORIGINAL_VALUE from lib.core.settings import UNICODE_ENCODING from lib.core.settings import URI_INJECTABLE_REGEX from lib.core.settings import URI_INJECTION_MARK_CHAR @@ -71,7 +72,12 @@ def __setRequestParams(): raise sqlmapSyntaxException, errMsg if conf.data: - conf.data = conf.data.replace("\n", " ") + if hasattr(conf.data, UNENCODED_ORIGINAL_VALUE): + original = getattr(conf.data, UNENCODED_ORIGINAL_VALUE) + conf.data = type(conf.data)(conf.data.replace("\n", " ")) + setattr(conf.data, UNENCODED_ORIGINAL_VALUE, original) + else: + conf.data = conf.data.replace("\n", " ") # Check if POST data is in xml syntax if re.match(SOAP_REGEX, conf.data, re.I | re.M): diff --git a/lib/request/connect.py b/lib/request/connect.py index 2512689bf..2c91ec4b3 100644 --- a/lib/request/connect.py +++ b/lib/request/connect.py @@ -53,6 +53,7 @@ from lib.core.settings import META_REFRESH_REGEX from lib.core.settings import IS_WIN from lib.core.settings import MIN_TIME_RESPONSES from lib.core.settings import WARN_TIME_STDEV +from lib.core.settings import UNENCODED_ORIGINAL_VALUE from lib.core.settings import URI_HTTP_HEADER from lib.core.threads import getCurrentThreadData from lib.request.basic import decodePage @@ -600,7 +601,10 @@ class Connect: cookie = _randomizeParameter(cookie, randomParameter) get = urlencode(get, limit=True) - post = urlencode(post) + if post and place != PLACE.POST and hasattr(post, UNENCODED_ORIGINAL_VALUE): + post = getattr(post, UNENCODED_ORIGINAL_VALUE) + else: + post = urlencode(post) if timeBasedCompare: if len(kb.responseTimes) < MIN_TIME_RESPONSES: