Now, if the back-end dbms type has been identified by the detection engine, skips the fingerprint phase.

Major code refactoring and commenting to detection engine.
Ask user whether or not to proceed to test remaining parameters after an injection point has been identified.
Restore beep at SQL injection find.
Avoid reuse of same variable in DBMS handler code.
Minor adjustment of payloads XML file.
This commit is contained in:
Bernardo Damele 2010-11-30 22:40:25 +00:00
parent fcdebbd55f
commit c8f943f5e4
17 changed files with 210 additions and 118 deletions

View File

@ -67,7 +67,24 @@ def unescape(string, dbms):
"Sybase": Sybase.unescape "Sybase": Sybase.unescape
} }
if dbms in unescaper:
return unescaper[dbms](string) return unescaper[dbms](string)
else:
return string
def unescapeDbms(payload, injection, dbms):
# If this is a DBMS-specific test (dbms), sqlmap identified the
# DBMS during previous a test (injection.dbms) or the user
# provided a DBMS (conf.dbms), unescape the strings between single
# quotes in the payload
if injection.dbms is not None:
payload = unescape(payload, injection.dbms)
elif dbms is not None:
payload = unescape(payload, dbms)
elif conf.dbms is not None:
payload = unescape(payload, conf.dbms)
return payload
def checkSqlInjection(place, parameter, value): def checkSqlInjection(place, parameter, value):
# Store here the details about boundaries and payload used to # Store here the details about boundaries and payload used to
@ -77,8 +94,9 @@ def checkSqlInjection(place, parameter, value):
for test in conf.tests: for test in conf.tests:
title = test.title title = test.title
stype = test.stype stype = test.stype
proceed = True
# Skip test if the risk is higher than the provided (or default)
# value
# Parse test's <risk> # Parse test's <risk>
if test.risk > conf.risk: if test.risk > conf.risk:
debugMsg = "skipping test '%s' because the risk " % title debugMsg = "skipping test '%s' because the risk " % title
@ -86,6 +104,8 @@ def checkSqlInjection(place, parameter, value):
logger.debug(debugMsg) logger.debug(debugMsg)
continue continue
# Skip test if the level is higher than the provided (or default)
# value
# Parse test's <level> # Parse test's <level>
if test.level > conf.level: if test.level > conf.level:
debugMsg = "skipping test '%s' because the level " % title debugMsg = "skipping test '%s' because the level " % title
@ -93,26 +113,27 @@ def checkSqlInjection(place, parameter, value):
logger.debug(debugMsg) logger.debug(debugMsg)
continue continue
# Skip test if it is the same SQL injection type already
# identified by another test
if injection.data and stype in injection.data:
debugMsg = "skipping test '%s' because " % title
debugMsg += "the payload for %s has " % PAYLOAD.SQLINJECTION[stype]
debugMsg += "already been identified"
logger.debug(debugMsg)
continue
# Skip DBMS-specific test if it does not match either the
# previously identified or the user's provided DBMS
if "details" in test and "dbms" in test.details: if "details" in test and "dbms" in test.details:
dbms = test.details.dbms dbms = test.details.dbms
else: else:
dbms = None dbms = None
# Skip current test if it is the same SQL injection type
# already identified by another test
if injection.data and stype in injection.data:
debugMsg = "skipping test '%s' because " % title
debugMsg += "we have already the payload for %s" % PAYLOAD.SQLINJECTION[stype]
logger.debug(debugMsg)
continue
# Skip DBMS-specific tests if they do not match the DBMS
# identified
if dbms is not None: if dbms is not None:
if injection.dbms is not None and injection.dbms != dbms: if injection.dbms is not None and injection.dbms != dbms:
debugMsg = "skipping test '%s' because " % title debugMsg = "skipping test '%s' because " % title
debugMsg += "the back-end DBMS is %s" % injection.dbms debugMsg += "the back-end DBMS identified is "
debugMsg += "%s" % injection.dbms
logger.debug(debugMsg) logger.debug(debugMsg)
continue continue
@ -128,16 +149,10 @@ def checkSqlInjection(place, parameter, value):
logger.info(infoMsg) logger.info(infoMsg)
# Parse test's <request> # Parse test's <request>
payload = agent.cleanupPayload(test.request.payload) comment = agent.getComment(test.request)
fstPayload = agent.cleanupPayload(test.request.payload)
if dbms: fstPayload = unescapeDbms(fstPayload, injection, dbms)
payload = unescape(payload, dbms) fstPayload = "%s%s" % (fstPayload, comment)
if "comment" in test.request:
comment = test.request.comment
else:
comment = ""
testPayload = "%s%s" % (payload, comment)
if conf.prefix is not None and conf.suffix is not None: if conf.prefix is not None and conf.suffix is not None:
# Create a custom boundary object for user's supplied prefix # Create a custom boundary object for user's supplied prefix
@ -162,17 +177,21 @@ def checkSqlInjection(place, parameter, value):
else: else:
boundary.ptype = 1 boundary.ptype = 1
# Prepend user's provided boundaries to all others # Prepend user's provided boundaries to all others boundaries
conf.boundaries.insert(0, boundary) conf.boundaries.insert(0, boundary)
for boundary in conf.boundaries: for boundary in conf.boundaries:
injectable = False
# Skip boundary if the level is higher than the provided (or
# default) value
# Parse boundary's <level> # Parse boundary's <level>
if boundary.level > conf.level: if boundary.level > conf.level:
# NOTE: shall we report every single skipped boundary too? # NOTE: shall we report every single skipped boundary too?
continue continue
# Parse test's <clause> and boundary's <clause>
# Skip boundary if it does not match against test's <clause> # Skip boundary if it does not match against test's <clause>
# Parse test's <clause> and boundary's <clause>
clauseMatch = False clauseMatch = False
for clauseTest in test.clause: for clauseTest in test.clause:
@ -183,8 +202,8 @@ def checkSqlInjection(place, parameter, value):
if test.clause != [ 0 ] and boundary.clause != [ 0 ] and not clauseMatch: if test.clause != [ 0 ] and boundary.clause != [ 0 ] and not clauseMatch:
continue continue
# Parse test's <where> and boundary's <where>
# Skip boundary if it does not match against test's <where> # Skip boundary if it does not match against test's <where>
# Parse test's <where> and boundary's <where>
whereMatch = False whereMatch = False
for where in test.where: for where in test.where:
@ -199,11 +218,10 @@ def checkSqlInjection(place, parameter, value):
prefix = boundary.prefix if boundary.prefix else "" prefix = boundary.prefix if boundary.prefix else ""
suffix = boundary.suffix if boundary.suffix else "" suffix = boundary.suffix if boundary.suffix else ""
ptype = boundary.ptype ptype = boundary.ptype
injectable = False
# If the previous injections succeeded, we know which prefix, # If the previous injections succeeded, we know which prefix,
# postfix and parameter type to use for further tests, no # suffix and parameter type to use for further tests, no
# need to cycle through all of the boundaries anymore # need to cycle through the boundaries for the following tests
condBound = (injection.prefix is not None and injection.suffix is not None) condBound = (injection.prefix is not None and injection.suffix is not None)
condBound &= (injection.prefix != prefix or injection.suffix != suffix) condBound &= (injection.prefix != prefix or injection.suffix != suffix)
condType = injection.ptype is not None and injection.ptype != ptype condType = injection.ptype is not None and injection.ptype != ptype
@ -213,8 +231,8 @@ def checkSqlInjection(place, parameter, value):
# For each test's <where> # For each test's <where>
for where in test.where: for where in test.where:
# The <where> tag defines where to add our injection # Threat the parameter original value according to the
# string to the parameter under assessment. # test's <where> tag
if where == 1: if where == 1:
origValue = value origValue = value
elif where == 2: elif where == 2:
@ -222,41 +240,41 @@ def checkSqlInjection(place, parameter, value):
elif where == 3: elif where == 3:
origValue = "" origValue = ""
# Forge payload by prepending with boundary's prefix and # Forge request payload by prepending with boundary's
# appending with boundary's suffix the test's # prefix and appending the boundary's suffix to the
# ' <payload><command> ' string # test's ' <payload><comment> ' string
boundPayload = "%s%s %s %s" % (origValue, prefix, testPayload, suffix) boundPayload = "%s%s %s %s" % (origValue, prefix, fstPayload, suffix)
boundPayload = boundPayload.strip() boundPayload = boundPayload.strip()
boundPayload = agent.cleanupPayload(boundPayload) boundPayload = agent.cleanupPayload(boundPayload)
reqPayload = agent.payload(place, parameter, value, boundPayload) reqPayload = agent.payload(place, parameter, value, boundPayload)
# Perform the test's request and check whether or not the
# payload was successful
# Parse test's <response> # Parse test's <response>
# Check wheather or not the payload was successful
for method, check in test.response.items(): for method, check in test.response.items():
check = agent.cleanupPayload(check) check = agent.cleanupPayload(check)
# In case of boolean-based blind SQL injection # In case of boolean-based blind SQL injection
if method == "comparison": if method == "comparison":
sndPayload = agent.cleanupPayload(test.response.comparison) sndPayload = agent.cleanupPayload(test.response.comparison)
sndPayload = unescapeDbms(sndPayload, injection, dbms)
sndPayload = "%s%s" % (sndPayload, comment)
if dbms: # Forge response payload by prepending with
sndPayload = unescape(sndPayload, dbms) # boundary's prefix and appending the boundary's
# suffix to the test's ' <payload><comment> '
if "comment" in test.response: # string
sndComment = test.response.comment
else:
sndComment = ""
sndPayload = "%s%s" % (sndPayload, sndComment)
boundPayload = "%s%s %s %s" % (origValue, prefix, sndPayload, suffix) boundPayload = "%s%s %s %s" % (origValue, prefix, sndPayload, suffix)
boundPayload = boundPayload.strip() boundPayload = boundPayload.strip()
boundPayload = agent.cleanupPayload(boundPayload) boundPayload = agent.cleanupPayload(boundPayload)
cmpPayload = agent.payload(place, parameter, value, boundPayload) cmpPayload = agent.payload(place, parameter, value, boundPayload)
# Useful to set conf.matchRatio at first # Useful to set conf.matchRatio at first based on
# the False response content
conf.matchRatio = None conf.matchRatio = None
_ = Request.queryPage(cmpPayload, place) _ = Request.queryPage(cmpPayload, place)
# Compare True and False response contents
trueResult = Request.queryPage(reqPayload, place) trueResult = Request.queryPage(reqPayload, place)
if trueResult: if trueResult:
@ -273,6 +291,8 @@ def checkSqlInjection(place, parameter, value):
# In case of error-based or UNION query SQL injections # In case of error-based or UNION query SQL injections
elif method == "grep": elif method == "grep":
# Perform the test's request and grep the response
# body for the test's <grep> regular expression
reqBody, _ = Request.queryPage(reqPayload, place, content=True) reqBody, _ = Request.queryPage(reqPayload, place, content=True)
match = re.search(check, reqBody, re.DOTALL | re.IGNORECASE) match = re.search(check, reqBody, re.DOTALL | re.IGNORECASE)
@ -290,8 +310,11 @@ def checkSqlInjection(place, parameter, value):
injectable = True injectable = True
# In case of time-based blind or stacked queries SQL injections # In case of time-based blind or stacked queries
# SQL injections
elif method == "time": elif method == "time":
# Perform the test's request and check how long
# it takes to get the response back
start = time.time() start = time.time()
_ = Request.queryPage(reqPayload, place) _ = Request.queryPage(reqPayload, place)
duration = calculateDeltaSeconds(start) duration = calculateDeltaSeconds(start)
@ -302,26 +325,44 @@ def checkSqlInjection(place, parameter, value):
injectable = True injectable = True
# If the injection test was successful feed the injection
# object with the test's details
if injectable is True: if injectable is True:
# Feed with the boundaries details only the first time a
# test has been successful
if injection.place is None or injection.parameter is None:
injection.place = place injection.place = place
injection.parameter = parameter injection.parameter = parameter
injection.ptype = ptype injection.ptype = ptype
injection.prefix = prefix injection.prefix = prefix
injection.suffix = suffix injection.suffix = suffix
injection.data[stype] = (boundPayload, comment) # Feed with test details every time a test is successful
injection.data[stype] = (title, reqPayload, where, comment)
if "details" in test: if "details" in test:
for detailKey, detailValue in test.details.items(): for detailKey, detailValue in test.details.items():
if detailKey == "dbms" and injection.dbms is None: if detailKey == "dbms" and injection.dbms is None:
injection.dbms = detailValue injection.dbms = detailValue
kb.dbms = detailValue
elif detailKey == "dbms_version" and injection.dbms_version is None: elif detailKey == "dbms_version" and injection.dbms_version is None:
injection.dbms_version = detailValue injection.dbms_version = detailValue
kb.dbmsVersion = [ detailValue ]
elif detailKey == "os" and injection.os is None: elif detailKey == "os" and injection.os is None:
injection.os = detailValue injection.os = detailValue
beep()
# There is no need to perform this test for other
# <where> tags
break break
if injectable is True:
# There is no need to perform this test with others
# boundaries
break
# Return the injection object
if injection.place is not None and injection.parameter is not None: if injection.place is not None and injection.parameter is not None:
return injection return injection
else: else:

View File

@ -109,7 +109,8 @@ def __formatInjection(inj):
for stype, sdata in inj.data.items(): for stype, sdata in inj.data.items():
stype = PAYLOAD.SQLINJECTION[stype] if isinstance(stype, int) else stype stype = PAYLOAD.SQLINJECTION[stype] if isinstance(stype, int) else stype
data += " Type: %s\n" % stype data += " Type: %s\n" % stype
data += " Payload: %s\n\n" % sdata[0] data += " Title: %s\n" % sdata[0]
data += " Payload: %s\n\n" % sdata[1]
return data return data
@ -126,13 +127,16 @@ def __showInjections():
def __saveToSessionFile(): def __saveToSessionFile():
for inj in kb.injections: for inj in kb.injections:
if inj.place is None or inj.parameter is None:
continue
setInjection(inj) setInjection(inj)
place = inj.place place = inj.place
parameter = inj.parameter parameter = inj.parameter
for stype, sdata in inj.data.items(): for stype, sdata in inj.data.items():
payload = sdata[0] payload = sdata[1]
if stype == 1: if stype == 1:
kb.booleanTest = payload kb.booleanTest = payload
@ -313,6 +317,8 @@ def start():
parameters.remove(place) parameters.remove(place)
parameters.insert(0, place) parameters.insert(0, place)
proceed = True
for place in parameters: for place in parameters:
# Test User-Agent header only if --level >= 4 # Test User-Agent header only if --level >= 4
condition = (place == "User-Agent" and conf.level < 4) condition = (place == "User-Agent" and conf.level < 4)
@ -325,6 +331,9 @@ def start():
if not conf.paramDict.has_key(place): if not conf.paramDict.has_key(place):
continue continue
if not proceed:
break
paramDict = conf.paramDict[place] paramDict = conf.paramDict[place]
for parameter, value in paramDict.items(): for parameter, value in paramDict.items():
testSqlInj = True testSqlInj = True
@ -361,15 +370,22 @@ def start():
injection = checkSqlInjection(place, parameter, value) injection = checkSqlInjection(place, parameter, value)
if injection: if injection is not None and injection.place is not None:
kb.injections.append(injection) kb.injections.append(injection)
msg = "%s parameter '%s' " % (injection.place, injection.parameter)
msg += "is vulnerable. Do you want to keep testing the others? [y/N] "
test = readInput(msg, default="N")
if test[0] in ("n", "N"):
proceed = False
break
else: else:
warnMsg = "%s parameter '%s' is not " % (place, parameter) warnMsg = "%s parameter '%s' is not " % (place, parameter)
warnMsg += "injectable" warnMsg += "injectable"
logger.warn(warnMsg) logger.warn(warnMsg)
if (len(kb.injections) == 0 or len(kb.injections) == 1 and kb.injections[0].parameter is None) \ if len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None):
and not kb.injection.place and not kb.injection.parameter:
errMsg = "all parameters are not injectable, try " errMsg = "all parameters are not injectable, try "
errMsg += "a higher --level" errMsg += "a higher --level"
raise sqlmapNotVulnerableException, errMsg raise sqlmapNotVulnerableException, errMsg

View File

@ -50,7 +50,7 @@ def setHandler():
count = 0 count = 0
dbmsNames = ( "MySQL", "Oracle", "PostgreSQL", "Microsoft SQL Server", "SQLite", "Microsoft Access", "Firebird", "SAP MaxDB", "Sybase" ) dbmsNames = ( "MySQL", "Oracle", "PostgreSQL", "Microsoft SQL Server", "SQLite", "Microsoft Access", "Firebird", "SAP MaxDB", "Sybase" )
dbmsMap = [ dbmsObj = [
( MYSQL_ALIASES, MySQLMap, MySQLConn ), ( MYSQL_ALIASES, MySQLMap, MySQLConn ),
( ORACLE_ALIASES, OracleMap, OracleConn ), ( ORACLE_ALIASES, OracleMap, OracleConn ),
( PGSQL_ALIASES, PostgreSQLMap, PostgreSQLConn ), ( PGSQL_ALIASES, PostgreSQLMap, PostgreSQLConn ),
@ -64,24 +64,27 @@ def setHandler():
if kb.htmlFp: if kb.htmlFp:
inferencedDbms = kb.htmlFp[-1] inferencedDbms = kb.htmlFp[-1]
elif hasattr(kb.injection, "dbms"):
inferencedDbms = kb.injection.dbms
else: else:
inferencedDbms = None inferencedDbms = None
for injection in kb.injections:
if hasattr(injection, "dbms"):
inferencedDbms = injection.dbms
break
if inferencedDbms is not None: if inferencedDbms is not None:
for i in xrange(len(dbmsMap)): for i in xrange(len(dbmsObj)):
dbmsAliases, _, _ = dbmsMap[i] dbmsAliases, _, _ = dbmsObj[i]
if inferencedDbms.lower() in dbmsAliases: if inferencedDbms.lower() in dbmsAliases:
if i > 0: if i > 0:
pushValue(dbmsMap[i]) pushValue(dbmsObj[i])
dbmsMap.remove(dbmsMap[i]) dbmsObj.remove(dbmsObj[i])
dbmsMap.insert(0, popValue()) dbmsObj.insert(0, popValue())
break break
for dbmsAliases, dbmsMap, dbmsConn in dbmsMap: for dbmsAliases, dbmsMap, dbmsConn in dbmsObj:
if conf.dbms and conf.dbms not in dbmsAliases: if conf.dbms and conf.dbms not in dbmsAliases:
debugMsg = "skipping test for %s" % dbmsNames[count] debugMsg = "skipping test for %s" % dbmsNames[count]
logger.debug(debugMsg) logger.debug(debugMsg)
@ -102,7 +105,6 @@ def setHandler():
if handler.checkDbms(): if handler.checkDbms():
if not conf.dbms or conf.dbms in dbmsAliases: if not conf.dbms or conf.dbms in dbmsAliases:
kb.dbmsDetected = True kb.dbmsDetected = True
conf.dbmsHandler = handler conf.dbmsHandler = handler
return return

View File

@ -126,20 +126,6 @@ class Agent:
return payload return payload
def cleanupPayload(self, payload):
randInt = randomInt()
randInt1 = randomInt()
randStr = randomStr()
payload = payload.replace("[RANDNUM]", str(randInt))
payload = payload.replace("[RANDNUM1]", str(randInt1))
payload = payload.replace("[RANDSTR]", randStr)
payload = payload.replace("[ERROR_START_CHAR]", ERROR_START_CHAR)
payload = payload.replace("[ERROR_END_CHAR]", ERROR_END_CHAR)
payload = payload.replace("[SLEEPTIME]", str(conf.timeSec))
return payload
def prefixQuery(self, string): def prefixQuery(self, string):
""" """
This method defines how the input string has to be escaped This method defines how the input string has to be escaped
@ -173,6 +159,28 @@ class Agent:
return string return string
def cleanupPayload(self, payload):
randInt = randomInt()
randInt1 = randomInt()
randStr = randomStr()
payload = payload.replace("[RANDNUM]", str(randInt))
payload = payload.replace("[RANDNUM1]", str(randInt1))
payload = payload.replace("[RANDSTR]", randStr)
payload = payload.replace("[ERROR_START_CHAR]", ERROR_START_CHAR)
payload = payload.replace("[ERROR_END_CHAR]", ERROR_END_CHAR)
payload = payload.replace("[SLEEPTIME]", str(conf.timeSec))
return payload
def getComment(self, reqObj):
if "comment" in reqObj:
comment = reqObj.comment
else:
comment = ""
return comment
def nullAndCastField(self, field): def nullAndCastField(self, field):
""" """
Take in input a field string and return its processed nulled and Take in input a field string and return its processed nulled and

View File

@ -98,8 +98,10 @@ def setInjection(inj):
for stype, sdata in inj.data.items(): for stype, sdata in inj.data.items():
dataToSessionFile("[%s][%s][%s][Injection type][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), PAYLOAD.SQLINJECTION[stype])) dataToSessionFile("[%s][%s][%s][Injection type][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), PAYLOAD.SQLINJECTION[stype]))
dataToSessionFile("[%s][%s][%s][Injection payload][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), sdata[0])) dataToSessionFile("[%s][%s][%s][Injection title][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), sdata[0]))
dataToSessionFile("[%s][%s][%s][Injection comment][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), sdata[1])) dataToSessionFile("[%s][%s][%s][Injection payload][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), sdata[1]))
dataToSessionFile("[%s][%s][%s][Injection where][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), sdata[2]))
dataToSessionFile("[%s][%s][%s][Injection comment][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), sdata[3]))
def setDbms(dbms): def setDbms(dbms):
""" """
@ -371,7 +373,7 @@ def resumeConfKb(expression, url, value):
warnMsg += "injectable point" warnMsg += "injectable point"
logger.warn(warnMsg) logger.warn(warnMsg)
else: else:
if kb.injection.place is not None: if kb.injection.place is not None and kb.injection.parameter is not None:
kb.injections.append(kb.injection) kb.injections.append(kb.injection)
kb.injection = injectionDict() kb.injection = injectionDict()
@ -422,6 +424,13 @@ def resumeConfKb(expression, url, value):
logMsg = "resuming injection type '%s' from session file" % stype logMsg = "resuming injection type '%s' from session file" % stype
logger.info(logMsg) logger.info(logMsg)
elif expression == "Injection title" and url == conf.url:
title = unSafeFormatString(value[:-1])
kb.injection.data[kb.injection.data.keys()[0]].append(title)
logMsg = "resuming injection title '%s' from session file" % title
logger.info(logMsg)
elif expression == "Injection payload" and url == conf.url: elif expression == "Injection payload" and url == conf.url:
payload = unSafeFormatString(value[:-1]) payload = unSafeFormatString(value[:-1])
kb.injection.data[kb.injection.data.keys()[0]].append(payload) kb.injection.data[kb.injection.data.keys()[0]].append(payload)
@ -429,6 +438,13 @@ def resumeConfKb(expression, url, value):
logMsg = "resuming injection payload '%s' from session file" % payload logMsg = "resuming injection payload '%s' from session file" % payload
logger.info(logMsg) logger.info(logMsg)
elif expression == "Injection where" and url == conf.url:
where = unSafeFormatString(value[:-1])
kb.injection.data[kb.injection.data.keys()[0]].append(where)
logMsg = "resuming injection where '%s' from session file" % where
logger.info(logMsg)
elif expression == "Injection comment" and url == conf.url: elif expression == "Injection comment" and url == conf.url:
comment = unSafeFormatString(value[:-1]) comment = unSafeFormatString(value[:-1])
kb.injection.data[kb.injection.data.keys()[0]].append(comment) kb.injection.data[kb.injection.data.keys()[0]].append(comment)
@ -492,10 +508,10 @@ def resumeConfKb(expression, url, value):
test = readInput(message, default="N") test = readInput(message, default="N")
if not test or test[0] in ("n", "N"): if not test or test[0] in ("n", "N"):
conf.dbms = dbms kb.dbms = dbms
kb.dbmsVersion = dbmsVersion kb.dbmsVersion = dbmsVersion
else: else:
conf.dbms = dbms kb.dbms = dbms
kb.dbmsVersion = dbmsVersion kb.dbmsVersion = dbmsVersion
elif expression == "OS" and url == conf.url: elif expression == "OS" and url == conf.url:

View File

@ -173,7 +173,9 @@ def __setOutputResume():
elif len(value) >= len(kb.resumedQueries[url][expression]): elif len(value) >= len(kb.resumedQueries[url][expression]):
kb.resumedQueries[url][expression] = value kb.resumedQueries[url][expression] = value
if kb.injection.place is not None and kb.injection.parameter is not None:
kb.injections.append(kb.injection) kb.injections.append(kb.injection)
readSessionFP.close() readSessionFP.close()
else: else:
try: try:

View File

@ -19,6 +19,8 @@ def cleanupVals(values, tag):
for value in values: for value in values:
if value.isdigit(): if value.isdigit():
value = int(value) value = int(value)
else:
value = str(value)
values[count] = value values[count] = value
count += 1 count += 1

View File

@ -152,7 +152,7 @@ class Fingerprint(GenericFingerprint):
return value return value
def checkDbms(self): def checkDbms(self):
if conf.dbms in ACCESS_ALIASES: if (kb.dbms is not None and kb.dbms.lower() in ACCESS_ALIASES) or conf.dbms in ACCESS_ALIASES:
setDbms(DBMS.ACCESS) setDbms(DBMS.ACCESS)
if not conf.extensiveFp: if not conf.extensiveFp:

View File

@ -103,7 +103,7 @@ class Fingerprint(GenericFingerprint):
return retVal return retVal
def checkDbms(self): def checkDbms(self):
if conf.dbms in FIREBIRD_ALIASES: if (kb.dbms is not None and kb.dbms.lower() in FIREBIRD_ALIASES) or conf.dbms in FIREBIRD_ALIASES:
setDbms(DBMS.FIREBIRD) setDbms(DBMS.FIREBIRD)
self.getBanner() self.getBanner()

View File

@ -105,7 +105,7 @@ class Fingerprint(GenericFingerprint):
return value return value
def checkDbms(self): def checkDbms(self):
if conf.dbms in MAXDB_ALIASES: if (kb.dbms is not None and kb.dbms.lower() in MAXDB_ALIASES) or conf.dbms in MAXDB_ALIASES:
setDbms(DBMS.MAXDB) setDbms(DBMS.MAXDB)
self.getBanner() self.getBanner()

View File

@ -71,7 +71,9 @@ class Fingerprint(GenericFingerprint):
return value return value
def checkDbms(self): def checkDbms(self):
if conf.dbms in MSSQL_ALIASES and kb.dbmsVersion and kb.dbmsVersion[0].isdigit(): if ((kb.dbms is not None and kb.dbms.lower() in MSSQL_ALIASES) \
or conf.dbms in MSSQL_ALIASES) and kb.dbmsVersion and \
kb.dbmsVersion[0].isdigit():
setDbms("%s %s" % (DBMS.MSSQL, kb.dbmsVersion[0])) setDbms("%s %s" % (DBMS.MSSQL, kb.dbmsVersion[0]))
self.getBanner() self.getBanner()

View File

@ -142,10 +142,16 @@ class Fingerprint(GenericFingerprint):
* http://dev.mysql.com/doc/refman/6.0/en/news-6-0-x.html (manual has been withdrawn) * http://dev.mysql.com/doc/refman/6.0/en/news-6-0-x.html (manual has been withdrawn)
""" """
if conf.dbms in MYSQL_ALIASES and kb.dbmsVersion and kb.dbmsVersion[0].isdigit(): if ((kb.dbms is not None and kb.dbms.lower() in MYSQL_ALIASES) \
or conf.dbms in MYSQL_ALIASES) and kb.dbmsVersion and \
kb.dbmsVersion[0] != "Unknown":
kb.dbmsVersion[0] = kb.dbmsVersion[0].replace(">", "")
kb.dbmsVersion[0] = kb.dbmsVersion[0].replace("=", "")
kb.dbmsVersion[0] = kb.dbmsVersion[0].replace(" ", "")
setDbms("%s %s" % (DBMS.MYSQL, kb.dbmsVersion[0])) setDbms("%s %s" % (DBMS.MYSQL, kb.dbmsVersion[0]))
if int(kb.dbmsVersion[0]) >= 5: if str(kb.dbmsVersion[0]) >= '5':
kb.data.has_information_schema = True kb.data.has_information_schema = True
self.getBanner() self.getBanner()

View File

@ -64,7 +64,7 @@ class Fingerprint(GenericFingerprint):
return value return value
def checkDbms(self): def checkDbms(self):
if conf.dbms in ORACLE_ALIASES: if (kb.dbms is not None and kb.dbms.lower() in ORACLE_ALIASES) or conf.dbms in ORACLE_ALIASES:
setDbms(DBMS.ORACLE) setDbms(DBMS.ORACLE)
self.getBanner() self.getBanner()

View File

@ -73,7 +73,7 @@ class Fingerprint(GenericFingerprint):
* http://www.postgresql.org/docs/8.4/interactive/release.html (up to 8.4.2) * http://www.postgresql.org/docs/8.4/interactive/release.html (up to 8.4.2)
""" """
if conf.dbms in PGSQL_ALIASES: if (kb.dbms is not None and kb.dbms.lower() in PGSQL_ALIASES) or conf.dbms in PGSQL_ALIASES:
setDbms(DBMS.POSTGRESQL) setDbms(DBMS.POSTGRESQL)
self.getBanner() self.getBanner()

View File

@ -69,7 +69,7 @@ class Fingerprint(GenericFingerprint):
* http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions * http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions
""" """
if conf.dbms in SQLITE_ALIASES: if (kb.dbms is not None and kb.dbms.lower() in SQLITE_ALIASES) or conf.dbms in SQLITE_ALIASES:
setDbms(DBMS.SQLITE) setDbms(DBMS.SQLITE)
self.getBanner() self.getBanner()

View File

@ -63,7 +63,9 @@ class Fingerprint(GenericFingerprint):
return value return value
def checkDbms(self): def checkDbms(self):
if conf.dbms in SYBASE_ALIASES and kb.dbmsVersion and kb.dbmsVersion[0].isdigit(): if ((kb.dbms is not None and kb.dbms.lower() in SYBASE_ALIASES) \
or conf.dbms in SYBASE_ALIASES) and kb.dbmsVersion and \
kb.dbmsVersion[0].isdigit():
setDbms("%s %s" % (DBMS.SYBASE, kb.dbmsVersion[0])) setDbms("%s %s" % (DBMS.SYBASE, kb.dbmsVersion[0]))
self.getBanner() self.getBanner()

View File

@ -35,7 +35,7 @@ Tag: <boundary>
A comma separated list of these values is also possible. A comma separated list of these values is also possible.
Sub-tag: <where> Sub-tag: <where>
This depends on the <where> value of the <test> (payload) in exam. Where to add our '<prefix> <payload><comment> <suffix>' string.
Valid values: Valid values:
1: When the value of <test>'s <where> is 1. 1: When the value of <test>'s <where> is 1.
@ -463,7 +463,6 @@ Formats:
</response> </response>
<details> <details>
<dbms>MySQL</dbms> <dbms>MySQL</dbms>
<dbms_version>&lt; 5.0</dbms_version>
</details> </details>
</test> </test>
@ -554,7 +553,6 @@ Formats:
</response> </response>
<details> <details>
<dbms>MySQL</dbms> <dbms>MySQL</dbms>
<dbms_version>&lt; 5.0</dbms_version>
</details> </details>
</test> </test>
@ -888,7 +886,6 @@ Formats:
</response> </response>
<details> <details>
<dbms>MySQL</dbms> <dbms>MySQL</dbms>
<dbms_version>&lt; 5.0.12</dbms_version>
</details> </details>
</test> </test>
@ -1108,7 +1105,6 @@ Formats:
</response> </response>
<details> <details>
<dbms>MySQL</dbms> <dbms>MySQL</dbms>
<dbms_version>&lt; 5.0.12</dbms_version>
</details> </details>
</test> </test>
@ -1212,7 +1208,6 @@ Formats:
</response> </response>
<details> <details>
<dbms>MySQL</dbms> <dbms>MySQL</dbms>
<dbms_version>&lt; 5.0.12</dbms_version>
</details> </details>
</test> </test>