From 742b0ef76e7c005a2da0d16053ba49901c809303 Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Tue, 3 May 2011 13:25:20 +0000 Subject: [PATCH] major improvement of ERROR data retrieval on MSSQL --- lib/core/settings.py | 3 +++ lib/techniques/error/use.py | 14 ++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/core/settings.py b/lib/core/settings.py index 45dd13498..24eba1c2e 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -295,6 +295,9 @@ URI_INJECTION_MARK_CHAR = '*' # Maximum length used for retrieving data over MySQL error based payload due to "known" problems with longer result strings MYSQL_ERROR_CHUNK_LENGTH = 50 +# Maximum length used for retrieving data over MSSQL error based payload due to trimming problems with longer result strings +MSSQL_ERROR_CHUNK_LENGTH = 100 + # Do not unescape the injected statement if it contains any of the following SQL words EXCLUDE_UNESCAPE = ("WAITFOR DELAY ", " INTO DUMPFILE ", " INTO OUTFILE ", "CREATE ", "BULK ", "EXEC ", "RECONFIGURE ", "DECLARE ", CHAR_INFERENCE_MARK) diff --git a/lib/techniques/error/use.py b/lib/techniques/error/use.py index 45e0d97d6..6956d9cb0 100644 --- a/lib/techniques/error/use.py +++ b/lib/techniques/error/use.py @@ -35,6 +35,7 @@ from lib.core.enums import PAYLOAD from lib.core.exception import sqlmapConnectionException from lib.core.settings import FROM_TABLE from lib.core.settings import MYSQL_ERROR_CHUNK_LENGTH +from lib.core.settings import MSSQL_ERROR_CHUNK_LENGTH from lib.core.settings import TURN_OFF_RESUME_INFO_LIMIT from lib.core.threads import getCurrentThreadData from lib.core.unescaper import unescaper @@ -50,6 +51,7 @@ def __oneShotErrorUse(expression, field): retVal = None offset = 1 + chunk_length = None while True: check = "%s(?P.*?)%s" % (kb.misc.start, kb.misc.stop) @@ -58,7 +60,11 @@ def __oneShotErrorUse(expression, field): nulledCastedField = agent.nullAndCastField(field) if Backend.isDbms(DBMS.MYSQL): - nulledCastedField = queries[DBMS.MYSQL].substring.query % (nulledCastedField, offset, MYSQL_ERROR_CHUNK_LENGTH) + chunk_length = MYSQL_ERROR_CHUNK_LENGTH + nulledCastedField = queries[DBMS.MYSQL].substring.query % (nulledCastedField, offset, chunk_length) + elif Backend.isDbms(DBMS.MSSQL): + chunk_length = MSSQL_ERROR_CHUNK_LENGTH + nulledCastedField = queries[DBMS.MSSQL].substring.query % (nulledCastedField, offset, chunk_length) # Forge the error-based SQL injection request vector = kb.injection.data[PAYLOAD.TECHNIQUE.ERROR].vector @@ -101,16 +107,16 @@ def __oneShotErrorUse(expression, field): if isinstance(output, basestring): output = htmlunescape(output).replace("
", "\n") - if Backend.isDbms(DBMS.MYSQL): + if any(map(lambda dbms: Backend.isDbms(dbms), [DBMS.MYSQL, DBMS.MSSQL])): if offset == 1: retVal = output else: retVal += output if output else '' - if not (output and len(output) == MYSQL_ERROR_CHUNK_LENGTH): + if not (output and len(output) == chunk_length): break else: - offset += MYSQL_ERROR_CHUNK_LENGTH + offset += chunk_length else: retVal = output break