From aa88361ab1da9ac7cd158e72464dfea0d5e088d8 Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Fri, 25 Feb 2011 09:22:44 +0000 Subject: [PATCH] incorporation of method for neutralization of reflective values --- lib/core/common.py | 19 +++++++++++++++++++ lib/request/connect.py | 6 +++++- lib/techniques/inband/union/test.py | 4 ++++ lib/techniques/inband/union/use.py | 13 ++++++------- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/lib/core/common.py b/lib/core/common.py index cdc2e5ba3..28cd66408 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -81,6 +81,8 @@ from lib.core.settings import DUMP_TAB_MARKER from lib.core.settings import DUMP_START_MARKER from lib.core.settings import DUMP_STOP_MARKER from lib.core.settings import MIN_TIME_RESPONSES +from lib.core.settings import PAYLOAD_DELIMITER +from lib.core.settings import REFLECTED_VALUE_MARKER from lib.core.settings import TIME_DEFAULT_DELAY from lib.core.settings import TIME_STDEV_COEFF from lib.core.settings import DYNAMICITY_MARK_LENGTH @@ -2386,3 +2388,20 @@ def cpuThrottle(value): """ delay = 0.00001 * (value ** 2) time.sleep(delay) + +def removeReflectiveValues(content, payload): + """ + Neutralizes (static/marked) reflective values in a given content based on a payload + (e.g. ?search=sql injection ---> ...value="sql%20injection") + """ + + payload = payload.replace(PAYLOAD_DELIMITER, '') + + regex = filterStringValue(payload, r'[A-Za-z0-9]', r'[^\s]+') + retVal = re.sub(regex, REFLECTED_VALUE_MARKER, content) + + if retVal != content: + warnMsg = "reflective value found and filtered out" + logger.warn(warnMsg) + + return retVal diff --git a/lib/request/connect.py b/lib/request/connect.py index 223047a31..e01c48646 100644 --- a/lib/request/connect.py +++ b/lib/request/connect.py @@ -28,6 +28,7 @@ from lib.core.common import getUnicode from lib.core.common import logHTTPTraffic from lib.core.common import parseTargetUrl from lib.core.common import readInput +from lib.core.common import removeReflectiveValues from lib.core.common import stdev from lib.core.common import wasLastRequestDelayed from lib.core.convert import urlencode @@ -487,7 +488,10 @@ class Connect: if content or response: return page, headers - elif getRatioValue: + + page = removeReflectiveValues(page, value) + + if getRatioValue: return comparison(page, getRatioValue=False, pageLength=pageLength), comparison(page, getRatioValue=True, pageLength=pageLength) elif pageLength or page: return comparison(page, getRatioValue, pageLength) diff --git a/lib/techniques/inband/union/test.py b/lib/techniques/inband/union/test.py index 4fc5aeab6..ff2bd00d9 100644 --- a/lib/techniques/inband/union/test.py +++ b/lib/techniques/inband/union/test.py @@ -23,6 +23,7 @@ from lib.core.common import parseUnionPage from lib.core.common import popValue from lib.core.common import pushValue from lib.core.common import randomStr +from lib.core.common import removeReflectiveValues from lib.core.common import stdev from lib.core.data import conf from lib.core.data import kb @@ -122,6 +123,9 @@ def __unionPosition(comment, place, parameter, value, prefix, suffix, count, whe page, headers = Request.queryPage(payload, place=place, content=True, raise404=False) content = "%s%s" % (page or "", listToStrValue(headers.headers if headers else None) or "") + # Remove possible reflective values from content (especially headers part) + content = removeReflectiveValues(content, payload) + if content and phrase in content: validPayload = payload vector = (position, count, comment, prefix, suffix, conf.uChar, where) diff --git a/lib/techniques/inband/union/use.py b/lib/techniques/inband/union/use.py index 2d2c6ab62..7bf80505d 100644 --- a/lib/techniques/inband/union/use.py +++ b/lib/techniques/inband/union/use.py @@ -19,6 +19,7 @@ from lib.core.common import initTechnique from lib.core.common import isNumPosStrValue from lib.core.common import listToStrValue from lib.core.common import parseUnionPage +from lib.core.common import removeReflectiveValues from lib.core.data import conf from lib.core.data import kb from lib.core.data import logger @@ -27,7 +28,6 @@ from lib.core.enums import DBMS from lib.core.enums import PAYLOAD from lib.core.exception import sqlmapSyntaxException from lib.core.settings import FROM_TABLE -from lib.core.settings import REFLECTED_VALUE_MARKER from lib.core.unescaper import unescaper from lib.request.connect import Connect as Request from lib.utils.resume import resume @@ -55,12 +55,8 @@ def __oneShotUnionUse(expression, unpack=True): page, headers = Request.queryPage(payload, content=True, raise404=False) content = "%s%s" % (page or "", listToStrValue(headers.headers if headers else None) or "") - reflective = filterStringValue(agent.removePayloadDelimiters(payload), r'[A-Za-z0-9]', r'[^\s]+') - filtered = re.sub(reflective, REFLECTED_VALUE_MARKER, content) - if filtered != content: - warnMsg = "reflective value found and filtered" - logger.warn(warnMsg) - content = filtered + # Remove possible reflective values from content (especially headers part) + content = removeReflectiveValues(content, payload) reqCount += 1 @@ -168,6 +164,7 @@ def unionUse(expression, unpack=True, dump=False): stopLimit = limitRegExp.group(int(limitGroupStop)) limitCond = int(stopLimit) > 1 + elif topLimit: startLimit = 0 stopLimit = int(topLimit.group(1)) @@ -225,6 +222,7 @@ def unionUse(expression, unpack=True, dump=False): logger.warn(warnMsg) stopLimit = 1 + elif isNumPosStrValue(count): if isinstance(stopLimit, int) and stopLimit > 0: stopLimit = min(int(count), int(stopLimit)) @@ -234,6 +232,7 @@ def unionUse(expression, unpack=True, dump=False): infoMsg = "the SQL query used returns " infoMsg += "%d entries" % stopLimit logger.info(infoMsg) + try: for num in xrange(startLimit, stopLimit): if Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):