mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-01-24 00:04:23 +03:00
Merge branch 'master' of github.com:sqlmapproject/sqlmap
This commit is contained in:
commit
a0b9e0f1c5
|
@ -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,17 @@ 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:
|
||||||
|
Backend.forceDbms(kb.heuristicDbms)
|
||||||
|
|
||||||
if unionExtended:
|
if unionExtended:
|
||||||
infoMsg = "automatically extending ranges "
|
infoMsg = "automatically extending ranges "
|
||||||
|
@ -582,6 +591,32 @@ 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()
|
||||||
|
|
||||||
|
if retVal:
|
||||||
|
infoMsg = "heuristic test showed that the back-end DBMS "
|
||||||
|
infoMsg += "could be '%s' " % retVal
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
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 +758,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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 = []
|
||||||
|
|
|
@ -36,7 +36,8 @@ UPPER_RATIO_BOUND = 0.98
|
||||||
# Markers for special cases when parameter values contain html encoded characters
|
# Markers for special cases when parameter values contain html encoded characters
|
||||||
PARAMETER_AMP_MARKER = "__AMP__"
|
PARAMETER_AMP_MARKER = "__AMP__"
|
||||||
PARAMETER_SEMICOLON_MARKER = "__SEMICOLON__"
|
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__"
|
URI_QUESTION_MARKER = "__QUESTION_MARK__"
|
||||||
ASTERISK_MARKER = "__ASTERISK_MARK__"
|
ASTERISK_MARKER = "__ASTERISK_MARK__"
|
||||||
|
|
||||||
|
@ -111,6 +112,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"
|
||||||
|
|
||||||
|
@ -459,7 +463,7 @@ VALID_TIME_CHARS_RUN_THRESHOLD = 100
|
||||||
CHECK_ZERO_COLUMNS_THRESHOLD = 10
|
CHECK_ZERO_COLUMNS_THRESHOLD = 10
|
||||||
|
|
||||||
# Boldify all logger messages containing these "patterns"
|
# 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 www root directory names
|
||||||
GENERIC_DOC_ROOT_DIRECTORY_NAMES = ("htdocs", "wwwroot", "www")
|
GENERIC_DOC_ROOT_DIRECTORY_NAMES = ("htdocs", "wwwroot", "www")
|
||||||
|
|
|
@ -687,7 +687,7 @@ class Connect(object):
|
||||||
else:
|
else:
|
||||||
uri = conf.url
|
uri = conf.url
|
||||||
|
|
||||||
if place == PLACE.CUSTOM_HEADER:
|
if value and place == PLACE.CUSTOM_HEADER:
|
||||||
if not auxHeaders:
|
if not auxHeaders:
|
||||||
auxHeaders = {}
|
auxHeaders = {}
|
||||||
auxHeaders[value.split(',')[0]] = value.split(',', 1)[1]
|
auxHeaders[value.split(',')[0]] = value.split(',', 1)[1]
|
||||||
|
|
|
@ -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_EQUALS_CHAR
|
||||||
from lib.core.settings import INFERENCE_NOT_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 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 PARTIAL_VALUE_MARKER
|
||||||
from lib.core.settings import VALID_TIME_CHARS_RUN_THRESHOLD
|
from lib.core.settings import VALID_TIME_CHARS_RUN_THRESHOLD
|
||||||
from lib.core.threads import getCurrentThreadData
|
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)
|
retVal = hashDBRetrieve(expression, checkConf=True)
|
||||||
|
|
||||||
if retVal:
|
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, "")
|
retVal = retVal.replace(PARTIAL_VALUE_MARKER, "")
|
||||||
|
|
||||||
if retVal:
|
if retVal and not conf.hexConvert:
|
||||||
partialValue = retVal
|
partialValue = retVal
|
||||||
infoMsg = "resuming partial value: %s" % safecharencode(partialValue)
|
infoMsg = "resuming partial value: %s" % safecharencode(partialValue)
|
||||||
logger.info(infoMsg)
|
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
|
finalValue = decodeHexValue(finalValue) if conf.hexConvert else finalValue
|
||||||
hashDBWrite(expression, finalValue)
|
hashDBWrite(expression, finalValue)
|
||||||
elif partialValue:
|
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:
|
if conf.hexConvert and not abortedFlag:
|
||||||
infoMsg = "\r[%s] [INFO] retrieved: %s %s\n" % (time.strftime("%X"), filterControlChars(finalValue), " " * retrievedLength)
|
infoMsg = "\r[%s] [INFO] retrieved: %s %s\n" % (time.strftime("%X"), filterControlChars(finalValue), " " * retrievedLength)
|
||||||
|
|
|
@ -3354,6 +3354,41 @@
|
||||||
<item value="r'performed 112 queries'" console_output="True"/>
|
<item value="r'performed 112 queries'" console_output="True"/>
|
||||||
</parse>
|
</parse>
|
||||||
</case>
|
</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">
|
<case name="Estimated time of arrival">
|
||||||
<switches>
|
<switches>
|
||||||
<verbose value="2"/>
|
<verbose value="2"/>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user