Merge branch 'master' of github.com:sqlmapproject/sqlmap

This commit is contained in:
Bernardo Damele 2013-01-25 17:11:38 +00:00
commit a0b9e0f1c5
7 changed files with 97 additions and 13 deletions

View File

@ -22,6 +22,7 @@ from lib.core.common import extractTextTagContent
from lib.core.common import findDynamicContent
from lib.core.common import Format
from lib.core.common import getLastRequestHTTPError
from lib.core.common import getPublicTypeMembers
from lib.core.common import getSortedInjectionTests
from lib.core.common import getUnicode
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.datatype import AttribDict
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 HTTPHEADER
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 HEURISTIC_CHECK_ALPHABET
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 UPPER_RATIO_BOUND
from lib.core.settings import IDS_WAF_CHECK_PAYLOAD
@ -441,11 +444,17 @@ def checkSqlInjection(place, parameter, value):
configUnion(test.request.char, test.request.columns)
if not Backend.getIdentifiedDbms():
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)
if not kb.heuristicDbms:
kb.heuristicDbms = heuristicCheckDbms(injection) or UNKNOWN_DBMS
if kb.heuristicDbms == UNKNOWN_DBMS:
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:
Backend.forceDbms(kb.heuristicDbms)
if unionExtended:
infoMsg = "automatically extending ranges "
@ -582,6 +591,32 @@ def checkSqlInjection(place, parameter, value):
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()
if retVal:
infoMsg = "heuristic test showed that the back-end DBMS "
infoMsg += "could be '%s' " % retVal
logger.info(infoMsg)
return retVal
def checkFalsePositives(injection):
"""
Checks for false positives (only in single special cases)
@ -723,7 +758,7 @@ def heuristicCheckSqlInjection(place, parameter):
kb.ignoreCasted = readInput(message, default='Y' if conf.multipleTargets else 'N').upper() != 'N'
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)
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 TIME_STDEV_COEFF
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 URI_QUESTION_MARKER
from lib.core.settings import URLENCODE_CHAR_LIMIT

View File

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

View File

@ -36,7 +36,8 @@ UPPER_RATIO_BOUND = 0.98
# Markers for special cases when parameter values contain html encoded characters
PARAMETER_AMP_MARKER = "__AMP__"
PARAMETER_SEMICOLON_MARKER = "__SEMICOLON__"
PARTIAL_VALUE_MARKER = "__PARTIAL__"
PARTIAL_VALUE_MARKER = "__PARTIAL_VALUE__"
PARTIAL_HEX_VALUE_MARKER = "__PARTIAL_HEX_VALUE__"
URI_QUESTION_MARKER = "__QUESTION_MARK__"
ASTERISK_MARKER = "__ASTERISK_MARK__"
@ -111,6 +112,9 @@ INFERENCE_EQUALS_CHAR = "="
# Character used for operation "not-equals" in inference
INFERENCE_NOT_EQUALS_CHAR = "!="
# String used for representation of unknown dbms
UNKNOWN_DBMS = "Unknown"
# String used for representation of unknown dbms version
UNKNOWN_DBMS_VERSION = "Unknown"
@ -459,7 +463,7 @@ VALID_TIME_CHARS_RUN_THRESHOLD = 100
CHECK_ZERO_COLUMNS_THRESHOLD = 10
# Boldify all logger messages containing these "patterns"
BOLD_PATTERNS = ("' injectable", "might be injectable", "' is vulnerable", "is not injectable", "test failed", "test passed", "live test final result")
BOLD_PATTERNS = ("' injectable", "might be injectable", "' is vulnerable", "is not injectable", "test failed", "test passed", "live test final result", "heuristic test showed")
# Generic www root directory names
GENERIC_DOC_ROOT_DIRECTORY_NAMES = ("htdocs", "wwwroot", "www")

View File

@ -687,7 +687,7 @@ class Connect(object):
else:
uri = conf.url
if place == PLACE.CUSTOM_HEADER:
if value and place == PLACE.CUSTOM_HEADER:
if not auxHeaders:
auxHeaders = {}
auxHeaders[value.split(',')[0]] = value.split(',', 1)[1]

View File

@ -42,6 +42,7 @@ from lib.core.settings import INFERENCE_GREATER_CHAR
from lib.core.settings import INFERENCE_EQUALS_CHAR
from lib.core.settings import INFERENCE_NOT_EQUALS_CHAR
from lib.core.settings import MAX_TIME_REVALIDATION_STEPS
from lib.core.settings import PARTIAL_HEX_VALUE_MARKER
from lib.core.settings import PARTIAL_VALUE_MARKER
from lib.core.settings import VALID_TIME_CHARS_RUN_THRESHOLD
from lib.core.threads import getCurrentThreadData
@ -65,10 +66,17 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
retVal = hashDBRetrieve(expression, checkConf=True)
if retVal:
if PARTIAL_VALUE_MARKER in retVal:
if PARTIAL_HEX_VALUE_MARKER in retVal:
retVal = retVal.replace(PARTIAL_HEX_VALUE_MARKER, "")
if retVal and conf.hexConvert:
partialValue = retVal
infoMsg = "resuming partial value: %s" % safecharencode(partialValue)
logger.info(infoMsg)
elif PARTIAL_VALUE_MARKER in retVal:
retVal = retVal.replace(PARTIAL_VALUE_MARKER, "")
if retVal:
if retVal and not conf.hexConvert:
partialValue = retVal
infoMsg = "resuming partial value: %s" % safecharencode(partialValue)
logger.info(infoMsg)
@ -545,7 +553,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
finalValue = decodeHexValue(finalValue) if conf.hexConvert else finalValue
hashDBWrite(expression, finalValue)
elif partialValue:
hashDBWrite(expression, "%s%s" % (PARTIAL_VALUE_MARKER, partialValue))
hashDBWrite(expression, "%s%s" % (PARTIAL_VALUE_MARKER if not conf.hexConvert else PARTIAL_HEX_VALUE_MARKER, partialValue))
if conf.hexConvert and not abortedFlag:
infoMsg = "\r[%s] [INFO] retrieved: %s %s\n" % (time.strftime("%X"), filterControlChars(finalValue), " " * retrievedLength)

View File

@ -3354,6 +3354,41 @@
<item value="r'performed 112 queries'" console_output="True"/>
</parse>
</case>
<case name="Custom GET parameter injection mark">
<switches>
<verbose value="2"/>
<url value="http://debiandev/sqlmap/mysql/get_int.php?id=1*"/>
<tech value="B"/>
<getBanner value="True"/>
</switches>
<parse>
<item value="banner: '5.1.66-0+squeeze1'"/>
</parse>
</case>
<case name="Custom POST data injection mark">
<switches>
<verbose value="2"/>
<url value="http://debiandev/sqlmap/mysql/post_int.php"/>
<data value="id=1*"/>
<tech value="E"/>
<getBanner value="True"/>
</switches>
<parse>
<item value="banner: '5.1.66-0+squeeze1'"/>
</parse>
</case>
<case name="Custom HTTP header (UA) injection mark">
<switches>
<verbose value="2"/>
<url value="http://debiandev/sqlmap/mysql/header_str.php"/>
<headers value="User-Agent: 1*"/>
<tech value="U"/>
<getBanner value="True"/>
</switches>
<parse>
<item value="banner: '5.1.66-0+squeeze1'"/>
</parse>
</case>
<case name="Estimated time of arrival">
<switches>
<verbose value="2"/>