From 1c86ec374ebf3ec92189a1b1df9b49269fae4e2a Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 7 Jan 2011 15:41:09 +0000 Subject: [PATCH] Code refactoring and cosmetics --- lib/controller/controller.py | 1 + lib/core/common.py | 87 +++++++++++++++++++++--------------- lib/core/enums.py | 1 + lib/core/unescaper.py | 7 ++- lib/request/basic.py | 10 +++-- lib/request/connect.py | 2 +- xml/payloads.xml | 51 ++++----------------- 7 files changed, 76 insertions(+), 83 deletions(-) diff --git a/lib/controller/controller.py b/lib/controller/controller.py index b65ccbbf4..14055f196 100644 --- a/lib/controller/controller.py +++ b/lib/controller/controller.py @@ -185,6 +185,7 @@ def start(): testSqlInj = True testSqlInj &= (conf.hostname, conf.path, None, None) not in kb.testedParams + if not testSqlInj: infoMsg = "skipping '%s'" % targetUrl logger.info(infoMsg) diff --git a/lib/core/common.py b/lib/core/common.py index c5dc66abb..0f89d5ffe 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -1789,13 +1789,14 @@ def findDynamicContent(firstPage, secondPage): def removeDynamicContent(page): """ - Removing dynamic content from supplied - page basing removal on precalculated - dynamic markings + Removing dynamic content from supplied page basing removal on + precalculated dynamic markings """ + if page: for item in kb.dynamicMarkings: prefix, suffix = item + if prefix is None and suffix is None: continue elif prefix is None: @@ -1809,10 +1810,10 @@ def removeDynamicContent(page): def filterStringValue(value, regex, replace=None): """ - Returns string value consisting only - of chars satisfying supplied regular - expressson + Returns string value consisting only of chars satisfying supplied + regular expression """ + retVal = "" if value: @@ -1826,16 +1827,17 @@ def filterStringValue(value, regex, replace=None): def filterControlChars(value): """ - Returns string value with control - chars being supstituted with ' ' + Returns string value with control chars being supstituted with ' ' """ + return filterStringValue(value, NON_CONTROL_CHAR_REGEX, ' ') def isDBMSVersionAtLeast(version): """ - Checks if the recognized DBMS version - is at least the version specified + Checks if the recognized DBMS version is at least the version + specified """ + retVal = None if kb.dbmsVersion and kb.dbmsVersion[0] != UNKNOWN_DBMS_VERSION and kb.dbmsVersion[0] != None: @@ -1843,6 +1845,7 @@ def isDBMSVersionAtLeast(version): while True: index = value.find('.', value.find('.') + 1) + if index > -1: value = value[0:index] + value[index + 1:] else: @@ -1866,9 +1869,9 @@ def isDBMSVersionAtLeast(version): def parseSqliteTableSchema(value): """ - Parses table column names and types from - specified SQLite table schema + Parses table column names and types from specified SQLite table schema """ + if value: table = {} columns = {} @@ -1883,6 +1886,7 @@ def getTechniqueData(technique=None): """ Returns injection data for technique specified """ + retVal = None if technique and technique in kb.injection.data: @@ -1892,16 +1896,17 @@ def getTechniqueData(technique=None): def isTechniqueAvailable(technique=None): """ - Returns True if there is injection data which - sqlmap could use for technique specified + Returns True if there is injection data which sqlmap could use for + technique specified """ + return getTechniqueData(technique) is not None def initTechnique(technique=None): """ - Prepares proper page template and match ratio - for technique specified + Prepares proper page template and match ratio for technique specified """ + data = getTechniqueData(technique) if data: @@ -1914,77 +1919,87 @@ def initTechnique(technique=None): def arrayizeValue(value): """ - Makes a list out of value if it's not already - list itself + Makes a list out of value if it is not already a list, tuple or set + itself """ - if not isinstance(value, list): - value = [value] + + if not isinstance(value, (list, tuple, set)): + value = [ value ] + return value def getInjectionTests(): """ - Returns prioritized test list by eventually - detected DBMS from error messages + Returns prioritized test list by eventually detected DBMS from error + messages """ + retVal = conf.tests + if getErrorParsedDBMSes(): - retVal = sorted(retVal, key=lambda test: False\ - if 'details' in test and 'dbms' in test.details\ + retVal = sorted(retVal, key=lambda test: False \ + if 'details' in test and 'dbms' in test.details \ and test.details.dbms in getErrorParsedDBMSes() else True) return retVal def filterListValue(value, regex): """ - Returns list with items that have parts - satisfying given regular expression + Returns list with items that have parts satisfying given regular + expression """ + if regex: retVal = [] filter = getCompiledRegex(regex, re.I) + for word in value: if filter.search(word): retVal.append(word) + return retVal else: return value def unicodeToSafeHTMLValue(value): """ - Returns HTML representation of unicode - string value safe for sending over HTTP(s) + Returns HTML representation of unicode string value safe for sending + over HTTP(s) """ + retVal = value + if value: for char in value: if ord(char) > 127: retVal = retVal.replace(char, "&#%d;" % ord(char)) + return retVal def getErrorParsedDBMSes(): """ - Returns array with parsed DBMS - names till now + Returns array with parsed DBMS names till now """ + return kb.htmlFp def showHttpErrorCodes(): """ - Shows all HTTP error codes - raised till now + Shows all HTTP error codes raised till now """ + if kb.httpErrorCodes: warnMsg = "HTTP error codes detected during testing:\n" - warnMsg += ", ".join("%d (%s) - %d times" % (code, httplib.responses[code]\ - if code in httplib.responses else '?', count)\ + warnMsg += ", ".join("%d (%s) - %d times" % (code, httplib.responses[code] \ + if code in httplib.responses else '?', count) \ for code, count in kb.httpErrorCodes.items()) logger.warn(warnMsg) def getComparePageRatio(firstPage, secondPage, filtered=False): """ - Returns comparison ratio between - two given pages + Returns comparison ratio between two given pages """ + if filtered: firstPage = getFilteredPageContent(firstPage) secondPage = getFilteredPageContent(secondPage) diff --git a/lib/core/enums.py b/lib/core/enums.py index 676fd63e1..aac274b5a 100644 --- a/lib/core/enums.py +++ b/lib/core/enums.py @@ -98,6 +98,7 @@ class PAYLOAD: COMPARISON = "comparison" GREP = "grep" TIME = "time" + UNION = "union" class TECHNIQUE: HEURISTIC = 0 diff --git a/lib/core/unescaper.py b/lib/core/unescaper.py index 63a6ccf94..a9ec6c8ca 100644 --- a/lib/core/unescaper.py +++ b/lib/core/unescaper.py @@ -12,6 +12,11 @@ from lib.core.datatype import advancedDict class Unescaper(advancedDict): def unescape(self, expression, quote=True): - return self[kb.dbms if kb.dbms else kb.misc.testedDbms](expression, quote=quote) + if hasattr(kb, "dbms") and kb.dbms is not None: + return self[kb.dbms if kb.dbms else kb.misc.testedDbms](expression, quote=quote) + elif hasattr(kb.misc, "testedDbms") and kb.misc.testedDbms is not None: + return self[kb.misc.testedDbms](expression, quote=quote) + else: + return expression unescaper = Unescaper() diff --git a/lib/request/basic.py b/lib/request/basic.py index 9e23c5fde..dffe93580 100644 --- a/lib/request/basic.py +++ b/lib/request/basic.py @@ -67,11 +67,12 @@ def parseResponse(page, headers): htmlParser(page) # Detect injectable page absolute system path - # NOTE: this regular expression works if the remote web application - # is written in PHP and debug/error messages are enabled. - + # NOTE: this regular expression works if the remote web + # application is written in PHP and debug/error messages are + # enabled for regex in ( r" in (?P.*?) on line", r"(?:>|\s)(?P[A-Za-z]:[\\/][\w.\\/]*)", r"(?:>|\s)(?P/\w[/\w.]+)" ): regObj = getCompiledRegex(regex) + for match in regObj.finditer(page): absFilePath = match.group("result").strip() page = page.replace(absFilePath, "") @@ -145,10 +146,13 @@ def decodePage(page, contentEncoding, contentType): def processResponse(page, responseHeaders): page = getUnicode(page) + parseResponse(page, responseHeaders) + if conf.parseErrors: msg = extractErrorMessage(page) if msg: logger.info("parsed error message: '%s'" % msg) + return page diff --git a/lib/request/connect.py b/lib/request/connect.py index 3278f5bf9..131ae4b62 100644 --- a/lib/request/connect.py +++ b/lib/request/connect.py @@ -428,7 +428,7 @@ class Connect: logger.warn(warnMsg) while len(kb.responseTimes) < MIN_TIME_RESPONSES: - _ = Connect.queryPage(content=True) + Connect.queryPage(content=True) if conf.safUrl and conf.saFreq > 0: kb.queryCounter += 1 diff --git a/xml/payloads.xml b/xml/payloads.xml index be125f7f4..605882a7f 100644 --- a/xml/payloads.xml +++ b/xml/payloads.xml @@ -151,8 +151,7 @@ Tag: Sub-tag: Regular expression to grep for in the response body. - NOTE: useful to test for error-based and UNION query SQL - injections. + NOTE: useful to test for error-based SQL injection. Sub-tag: