diff --git a/lib/controller/checks.py b/lib/controller/checks.py index d19a32d31..44582dbc3 100644 --- a/lib/controller/checks.py +++ b/lib/controller/checks.py @@ -58,6 +58,7 @@ from lib.core.exception import SqlmapConnectionException from lib.core.exception import SqlmapNoneDataException from lib.core.exception import SqlmapSilentQuitException from lib.core.exception import SqlmapUserQuitException +from lib.core.settings import DUMMY_XSS_CHECK_APPENDIX from lib.core.settings import FORMAT_EXCEPTION_STRINGS from lib.core.settings import HEURISTIC_CHECK_ALPHABET from lib.core.settings import SUHOSIN_MAX_VALUE_LENGTH @@ -848,6 +849,20 @@ def heuristicCheckSqlInjection(place, parameter): infoMsg += "not be injectable" logger.warn(infoMsg) + kb.heuristicMode = True + + payload = "%s%s%s" % (prefix, "%s%s%s" % (randomStr(), DUMMY_XSS_CHECK_APPENDIX, randomStr()), suffix) + payload = agent.payload(place, parameter, newValue=payload) + page, _ = Request.queryPage(payload, place, content=True, raise404=False) + + if DUMMY_XSS_CHECK_APPENDIX in (page or ""): + infoMsg = "heuristic (XSS) test shows that %s " % place + infoMsg += "parameter '%s' might " % parameter + infoMsg += "be vulnerable to XSS attacks" + logger.info(infoMsg) + + kb.heuristicMode = False + return kb.heuristicTest def checkDynParam(place, parameter, value): diff --git a/lib/core/common.py b/lib/core/common.py index e99dfa63d..2a30103e8 100755 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -2931,7 +2931,7 @@ def removeReflectiveValues(content, payload, suppressWarning=False): retVal = content - if all([content, payload]) and isinstance(content, unicode) and kb.reflectiveMechanism: + if all([content, payload]) and isinstance(content, unicode) and kb.reflectiveMechanism and not kb.heuristicMode: def _(value): while 2 * REFLECTED_REPLACEMENT_REGEX in value: value = value.replace(2 * REFLECTED_REPLACEMENT_REGEX, REFLECTED_REPLACEMENT_REGEX) @@ -2966,7 +2966,7 @@ def removeReflectiveValues(content, payload, suppressWarning=False): regex = REFLECTED_REPLACEMENT_REGEX.join(parts[1:]) retVal = re.sub(r"(?i)\b%s\b" % regex, REFLECTED_VALUE_MARKER, retVal) - if retVal != content and not kb.heuristicMode: + if retVal != content: kb.reflectiveCounters[REFLECTIVE_COUNTER.HIT] += 1 if not suppressWarning: warnMsg = "reflective value(s) found and filtering out" diff --git a/lib/core/settings.py b/lib/core/settings.py index 4a93fdfa5..66bc20418 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -509,6 +509,9 @@ DNS_BOUNDARIES_ALPHABET = re.sub("[a-fA-F]", "", string.ascii_letters) # Alphabet used for heuristic checks HEURISTIC_CHECK_ALPHABET = ('"', '\'', ')', '(', '[', ']', ',', '.') +# String used for dummy XSS check of a tested parameter value +DUMMY_XSS_CHECK_APPENDIX = "<'\">" + # Connection chunk size (processing large responses in chunks to avoid MemoryError crashes - e.g. large table dump in full UNION injections) MAX_CONNECTION_CHUNK_SIZE = 10 * 1024 * 1024