Implementation for an Issue #377

This commit is contained in:
Miroslav Stampar 2013-01-25 12:34:57 +01:00
parent e150316d97
commit 194a9e7b88
4 changed files with 46 additions and 7 deletions

View File

@ -22,6 +22,7 @@ from lib.core.common import extractTextTagContent
from lib.core.common import findDynamicContent from lib.core.common import findDynamicContent
from lib.core.common import Format from lib.core.common import Format
from lib.core.common import getLastRequestHTTPError from lib.core.common import getLastRequestHTTPError
from lib.core.common import getPublicTypeMembers
from lib.core.common import getSortedInjectionTests from lib.core.common import getSortedInjectionTests
from lib.core.common import getUnicode from lib.core.common import getUnicode
from lib.core.common import intersect from lib.core.common import intersect
@ -42,6 +43,8 @@ from lib.core.data import kb
from lib.core.data import logger from lib.core.data import logger
from lib.core.datatype import AttribDict from lib.core.datatype import AttribDict
from lib.core.datatype import InjectionDict from lib.core.datatype import InjectionDict
from lib.core.dicts import FROM_DUMMY_TABLE
from lib.core.enums import DBMS
from lib.core.enums import HEURISTIC_TEST from lib.core.enums import HEURISTIC_TEST
from lib.core.enums import HTTPHEADER from lib.core.enums import HTTPHEADER
from lib.core.enums import HTTPMETHOD from lib.core.enums import HTTPMETHOD
@ -55,7 +58,7 @@ from lib.core.exception import SqlmapUserQuitException
from lib.core.settings import FORMAT_EXCEPTION_STRINGS from lib.core.settings import FORMAT_EXCEPTION_STRINGS
from lib.core.settings import HEURISTIC_CHECK_ALPHABET from lib.core.settings import HEURISTIC_CHECK_ALPHABET
from lib.core.settings import SUHOSIN_MAX_VALUE_LENGTH from lib.core.settings import SUHOSIN_MAX_VALUE_LENGTH
from lib.core.settings import UNKNOWN_DBMS_VERSION from lib.core.settings import UNKNOWN_DBMS
from lib.core.settings import LOWER_RATIO_BOUND from lib.core.settings import LOWER_RATIO_BOUND
from lib.core.settings import UPPER_RATIO_BOUND from lib.core.settings import UPPER_RATIO_BOUND
from lib.core.settings import IDS_WAF_CHECK_PAYLOAD from lib.core.settings import IDS_WAF_CHECK_PAYLOAD
@ -441,11 +444,21 @@ def checkSqlInjection(place, parameter, value):
configUnion(test.request.char, test.request.columns) configUnion(test.request.char, test.request.columns)
if not Backend.getIdentifiedDbms(): if not Backend.getIdentifiedDbms():
warnMsg = "using unescaped version of the test " if not kb.heuristicDbms:
warnMsg += "because of zero knowledge of the " kb.heuristicDbms = heuristicCheckDbms(injection) or UNKNOWN_DBMS
warnMsg += "back-end DBMS. You can try to "
warnMsg += "explicitly set it using option '--dbms'" if kb.heuristicDbms == UNKNOWN_DBMS:
singleTimeWarnMessage(warnMsg) warnMsg = "using unescaped version of the test "
warnMsg += "because of zero knowledge of the "
warnMsg += "back-end DBMS. You can try to "
warnMsg += "explicitly set it using option '--dbms'"
singleTimeWarnMessage(warnMsg)
else:
warnMsg = "heuristic test showed that the back-end DBMS "
warnMsg += "could be '%s' " % kb.heuristicDbms
singleTimeWarnMessage(warnMsg)
Backend.forceDbms(kb.heuristicDbms)
if unionExtended: if unionExtended:
infoMsg = "automatically extending ranges " infoMsg = "automatically extending ranges "
@ -582,6 +595,27 @@ def checkSqlInjection(place, parameter, value):
return injection return injection
def heuristicCheckDbms(injection):
retVal = None
if not Backend.getIdentifiedDbms() and len(injection.data) == 1 and PAYLOAD.TECHNIQUE.BOOLEAN in injection.data:
pushValue(kb.injection)
kb.injection = injection
randStr1, randStr2 = randomStr(), randomStr()
for dbms in getPublicTypeMembers(DBMS, True):
Backend.forceDbms(dbms)
if checkBooleanExpression("(SELECT '%s'%s)='%s'" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), randStr1)):
if not checkBooleanExpression("(SELECT '%s'%s)='%s'" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), randStr2)):
retVal = dbms
break
Backend.flushForcedDbms()
kb.injection = popValue()
return retVal
def checkFalsePositives(injection): def checkFalsePositives(injection):
""" """
Checks for false positives (only in single special cases) Checks for false positives (only in single special cases)
@ -723,7 +757,7 @@ def heuristicCheckSqlInjection(place, parameter):
kb.ignoreCasted = readInput(message, default='Y' if conf.multipleTargets else 'N').upper() != 'N' kb.ignoreCasted = readInput(message, default='Y' if conf.multipleTargets else 'N').upper() != 'N'
elif result: elif result:
infoMsg += "be injectable (possible DBMS: %s)" % (Format.getErrorParsedDBMSes() or UNKNOWN_DBMS_VERSION) infoMsg += "be injectable (possible DBMS: %s)" % (Format.getErrorParsedDBMSes() or UNKNOWN_DBMS)
logger.info(infoMsg) logger.info(infoMsg)
else: else:

View File

@ -122,6 +122,7 @@ from lib.core.settings import SUPPORTED_DBMS
from lib.core.settings import TEXT_TAG_REGEX from lib.core.settings import TEXT_TAG_REGEX
from lib.core.settings import TIME_STDEV_COEFF from lib.core.settings import TIME_STDEV_COEFF
from lib.core.settings import UNICODE_ENCODING from lib.core.settings import UNICODE_ENCODING
from lib.core.settings import UNKNOWN_DBMS
from lib.core.settings import UNKNOWN_DBMS_VERSION from lib.core.settings import UNKNOWN_DBMS_VERSION
from lib.core.settings import URI_QUESTION_MARKER from lib.core.settings import URI_QUESTION_MARKER
from lib.core.settings import URLENCODE_CHAR_LIMIT from lib.core.settings import URLENCODE_CHAR_LIMIT

View File

@ -1526,6 +1526,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
kb.fileReadMode = False kb.fileReadMode = False
kb.forcedDbms = None kb.forcedDbms = None
kb.headersFp = {} kb.headersFp = {}
kb.heuristicDbms = None
kb.heuristicTest = None kb.heuristicTest = None
kb.hintValue = None kb.hintValue = None
kb.htmlFp = [] kb.htmlFp = []

View File

@ -111,6 +111,9 @@ INFERENCE_EQUALS_CHAR = "="
# Character used for operation "not-equals" in inference # Character used for operation "not-equals" in inference
INFERENCE_NOT_EQUALS_CHAR = "!=" INFERENCE_NOT_EQUALS_CHAR = "!="
# String used for representation of unknown dbms
UNKNOWN_DBMS = "Unknown"
# String used for representation of unknown dbms version # String used for representation of unknown dbms version
UNKNOWN_DBMS_VERSION = "Unknown" UNKNOWN_DBMS_VERSION = "Unknown"