diff --git a/lib/controller/controller.py b/lib/controller/controller.py index 1b2c0c422..cf621f37a 100644 --- a/lib/controller/controller.py +++ b/lib/controller/controller.py @@ -47,6 +47,7 @@ from lib.core.exception import sqlmapSilentQuitException from lib.core.exception import sqlmapValueException from lib.core.exception import sqlmapUserQuitException from lib.core.session import setInjection +from lib.core.settings import DEFAULT_GET_POST_DELIMITER from lib.core.settings import EMPTY_FORM_FIELDS_REGEX from lib.core.settings import IGNORE_PARAMETERS from lib.core.settings import LOW_TEXT_PERCENT @@ -157,8 +158,8 @@ def __randomFillBlankFields(value): if not test or test[0] in ("y", "Y"): while extractRegexResult(EMPTY_FORM_FIELDS_REGEX, retVal): item = extractRegexResult(EMPTY_FORM_FIELDS_REGEX, retVal) - if item[-1] == '&': - retVal = retVal.replace(item, "%s%s&" % (item[:-1], randomStr())) + if item[-1] == DEFAULT_GET_POST_DELIMITER: + retVal = retVal.replace(item, "%s%s%s" % (item[:-1], randomStr(), DEFAULT_GET_POST_DELIMITER)) else: retVal = retVal.replace(item, "%s%s" % (item, randomStr())) @@ -288,7 +289,7 @@ def start(): message = "Edit POST data [default: %s]%s: " % (urlencode(conf.data) if conf.data else "None", " (Warning: blank fields detected)" if conf.data and extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data) else "") conf.data = readInput(message, default=conf.data) conf.data = __randomFillBlankFields(conf.data) - conf.data = urldecode(conf.data) + conf.data = urldecode(conf.data) if conf.data and urlencode(DEFAULT_GET_POST_DELIMITER, None) not in conf.data else conf.data elif conf.method == HTTPMETHOD.GET: if targetUrl.find("?") > -1: diff --git a/lib/core/common.py b/lib/core/common.py index 5e4086d78..45633849a 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -74,6 +74,8 @@ from lib.core.exception import sqlmapMissingDependence from lib.core.exception import sqlmapSyntaxException from lib.core.optiondict import optDict from lib.core.settings import BIGARRAY_CHUNK_LENGTH +from lib.core.settings import DEFAULT_COOKIE_DELIMITER +from lib.core.settings import DEFAULT_GET_POST_DELIMITER from lib.core.settings import INFERENCE_UNKNOWN_CHAR from lib.core.settings import UNICODE_ENCODING from lib.core.settings import DBMS_DICT @@ -658,7 +660,7 @@ def paramToDict(place, parameters=None): if place != PLACE.SOAP: parameters = parameters.replace(", ", ",") - splitParams = parameters.split(conf.pDel or (";" if place == PLACE.COOKIE else "&")) + splitParams = parameters.split(conf.pDel or (DEFAULT_COOKIE_DELIMITER if place == PLACE.COOKIE else DEFAULT_GET_POST_DELIMITER)) for element in splitParams: elem = element.split("=") @@ -1270,7 +1272,7 @@ def parseTargetUrl(): conf.port = 80 if __urlSplit[3]: - conf.parameters[PLACE.GET] = urldecode(__urlSplit[3]) + conf.parameters[PLACE.GET] = urldecode(__urlSplit[3]) if __urlSplit[3] and urlencode(DEFAULT_GET_POST_DELIMITER, None) not in __urlSplit[3] else __urlSplit[3] conf.url = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, conf.path) conf.url = conf.url.replace(URI_QUESTION_MARKER, '?') @@ -3109,7 +3111,8 @@ def findPageForms(content, url, raise_=False, addToTargets=False): request = form.click() url = urldecode(request.get_full_url(), kb.pageEncoding) method = request.get_method() - data = urldecode(request.get_data(), kb.pageEncoding) if request.has_data() else None + data = request if request.has_data() else None + data = urldecode(data, kb.pageEncoding) if data and urlencode(DEFAULT_GET_POST_DELIMITER, None) not in data else data if not data and method and method.upper() == HTTPMETHOD.POST: debugMsg = "invalid POST form with blank data detected" logger.debug(debugMsg) diff --git a/lib/core/option.py b/lib/core/option.py index f9707113d..02ad9dfe8 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -50,6 +50,7 @@ from lib.core.common import sanitizeStr from lib.core.common import setOptimize from lib.core.common import UnicodeRawConfigParser from lib.core.convert import urldecode +from lib.core.convert import urlencode from lib.core.data import conf from lib.core.data import kb from lib.core.data import logger @@ -77,6 +78,7 @@ from lib.core.exception import sqlmapUnsupportedDBMSException from lib.core.exception import sqlmapUserQuitException from lib.core.optiondict import optDict from lib.core.settings import CODECS_LIST_PAGE +from lib.core.settings import DEFAULT_GET_POST_DELIMITER from lib.core.settings import DEFAULT_PAGE_ENCODING from lib.core.settings import DEFAULT_TOR_PORTS from lib.core.settings import GENERAL_IP_ADDRESS_REGEX @@ -307,7 +309,7 @@ def __feedTargetsDict(reqFile, addedTargetUrls): port = None if not kb.targetUrls or url not in addedTargetUrls: - kb.targetUrls.add((url, method, urldecode(data), cookie)) + kb.targetUrls.add((url, method, urldecode(data) if data and urlencode(DEFAULT_GET_POST_DELIMITER, None) not in data else data, cookie)) addedTargetUrls.add(url) fp = openFile(reqFile, "rb") @@ -1297,10 +1299,10 @@ def __cleanupOptions(): if re.search(r'%[0-9a-f]{2}', conf.data, re.I): original = conf.data class _(unicode): pass - conf.data = _(urldecode(conf.data)) + conf.data = _(urldecode(conf.data) if conf.data and urlencode(DEFAULT_GET_POST_DELIMITER, None) not in conf.data else conf.data) setattr(conf.data, UNENCODED_ORIGINAL_VALUE, original) else: - conf.data = urldecode(conf.data) + conf.data = urldecode(conf.data) if conf.data and urlencode(DEFAULT_GET_POST_DELIMITER, None) not in conf.data else conf.data if conf.os: conf.os = conf.os.capitalize() diff --git a/lib/core/settings.py b/lib/core/settings.py index e49d15671..3a47ce057 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -408,4 +408,10 @@ UNION_CHAR_REGEX = r'\A\w+\Z' UNENCODED_ORIGINAL_VALUE = 'original' # Common column names containing usernames (used for hash cracking in some cases) -COMMON_USER_COLUMNS = ('user', 'username', 'user_name', 'benutzername', 'benutzer', 'utilisateur', 'usager', 'consommateur', 'utente', 'utilizzatore', 'usufrutuario', 'korisnik', 'usuario', 'consumidor') \ No newline at end of file +COMMON_USER_COLUMNS = ('user', 'username', 'user_name', 'benutzername', 'benutzer', 'utilisateur', 'usager', 'consommateur', 'utente', 'utilizzatore', 'usufrutuario', 'korisnik', 'usuario', 'consumidor') + +# Default delimiter in GET/POST values +DEFAULT_GET_POST_DELIMITER = '&' + +# Default delimiter in cookie values +DEFAULT_COOKIE_DELIMITER = ';' \ No newline at end of file