Code refactoring and cosmetics

This commit is contained in:
Bernardo Damele 2011-01-07 15:41:09 +00:00
parent a8d660db54
commit 1c86ec374e
7 changed files with 76 additions and 83 deletions

View File

@ -185,6 +185,7 @@ def start():
testSqlInj = True testSqlInj = True
testSqlInj &= (conf.hostname, conf.path, None, None) not in kb.testedParams testSqlInj &= (conf.hostname, conf.path, None, None) not in kb.testedParams
if not testSqlInj: if not testSqlInj:
infoMsg = "skipping '%s'" % targetUrl infoMsg = "skipping '%s'" % targetUrl
logger.info(infoMsg) logger.info(infoMsg)

View File

@ -1789,13 +1789,14 @@ def findDynamicContent(firstPage, secondPage):
def removeDynamicContent(page): def removeDynamicContent(page):
""" """
Removing dynamic content from supplied Removing dynamic content from supplied page basing removal on
page basing removal on precalculated precalculated dynamic markings
dynamic markings
""" """
if page: if page:
for item in kb.dynamicMarkings: for item in kb.dynamicMarkings:
prefix, suffix = item prefix, suffix = item
if prefix is None and suffix is None: if prefix is None and suffix is None:
continue continue
elif prefix is None: elif prefix is None:
@ -1809,10 +1810,10 @@ def removeDynamicContent(page):
def filterStringValue(value, regex, replace=None): def filterStringValue(value, regex, replace=None):
""" """
Returns string value consisting only Returns string value consisting only of chars satisfying supplied
of chars satisfying supplied regular regular expression
expressson
""" """
retVal = "" retVal = ""
if value: if value:
@ -1826,16 +1827,17 @@ def filterStringValue(value, regex, replace=None):
def filterControlChars(value): def filterControlChars(value):
""" """
Returns string value with control Returns string value with control chars being supstituted with ' '
chars being supstituted with ' '
""" """
return filterStringValue(value, NON_CONTROL_CHAR_REGEX, ' ') return filterStringValue(value, NON_CONTROL_CHAR_REGEX, ' ')
def isDBMSVersionAtLeast(version): def isDBMSVersionAtLeast(version):
""" """
Checks if the recognized DBMS version Checks if the recognized DBMS version is at least the version
is at least the version specified specified
""" """
retVal = None retVal = None
if kb.dbmsVersion and kb.dbmsVersion[0] != UNKNOWN_DBMS_VERSION and kb.dbmsVersion[0] != 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: while True:
index = value.find('.', value.find('.') + 1) index = value.find('.', value.find('.') + 1)
if index > -1: if index > -1:
value = value[0:index] + value[index + 1:] value = value[0:index] + value[index + 1:]
else: else:
@ -1866,9 +1869,9 @@ def isDBMSVersionAtLeast(version):
def parseSqliteTableSchema(value): def parseSqliteTableSchema(value):
""" """
Parses table column names and types from Parses table column names and types from specified SQLite table schema
specified SQLite table schema
""" """
if value: if value:
table = {} table = {}
columns = {} columns = {}
@ -1883,6 +1886,7 @@ def getTechniqueData(technique=None):
""" """
Returns injection data for technique specified Returns injection data for technique specified
""" """
retVal = None retVal = None
if technique and technique in kb.injection.data: if technique and technique in kb.injection.data:
@ -1892,16 +1896,17 @@ def getTechniqueData(technique=None):
def isTechniqueAvailable(technique=None): def isTechniqueAvailable(technique=None):
""" """
Returns True if there is injection data which Returns True if there is injection data which sqlmap could use for
sqlmap could use for technique specified technique specified
""" """
return getTechniqueData(technique) is not None return getTechniqueData(technique) is not None
def initTechnique(technique=None): def initTechnique(technique=None):
""" """
Prepares proper page template and match ratio Prepares proper page template and match ratio for technique specified
for technique specified
""" """
data = getTechniqueData(technique) data = getTechniqueData(technique)
if data: if data:
@ -1914,77 +1919,87 @@ def initTechnique(technique=None):
def arrayizeValue(value): def arrayizeValue(value):
""" """
Makes a list out of value if it's not already Makes a list out of value if it is not already a list, tuple or set
list itself itself
""" """
if not isinstance(value, list):
value = [value] if not isinstance(value, (list, tuple, set)):
value = [ value ]
return value return value
def getInjectionTests(): def getInjectionTests():
""" """
Returns prioritized test list by eventually Returns prioritized test list by eventually detected DBMS from error
detected DBMS from error messages messages
""" """
retVal = conf.tests retVal = conf.tests
if getErrorParsedDBMSes(): if getErrorParsedDBMSes():
retVal = sorted(retVal, key=lambda test: False\ retVal = sorted(retVal, key=lambda test: False \
if 'details' in test and 'dbms' in test.details\ if 'details' in test and 'dbms' in test.details \
and test.details.dbms in getErrorParsedDBMSes() else True) and test.details.dbms in getErrorParsedDBMSes() else True)
return retVal return retVal
def filterListValue(value, regex): def filterListValue(value, regex):
""" """
Returns list with items that have parts Returns list with items that have parts satisfying given regular
satisfying given regular expression expression
""" """
if regex: if regex:
retVal = [] retVal = []
filter = getCompiledRegex(regex, re.I) filter = getCompiledRegex(regex, re.I)
for word in value: for word in value:
if filter.search(word): if filter.search(word):
retVal.append(word) retVal.append(word)
return retVal return retVal
else: else:
return value return value
def unicodeToSafeHTMLValue(value): def unicodeToSafeHTMLValue(value):
""" """
Returns HTML representation of unicode Returns HTML representation of unicode string value safe for sending
string value safe for sending over HTTP(s) over HTTP(s)
""" """
retVal = value retVal = value
if value: if value:
for char in value: for char in value:
if ord(char) > 127: if ord(char) > 127:
retVal = retVal.replace(char, "&#%d;" % ord(char)) retVal = retVal.replace(char, "&#%d;" % ord(char))
return retVal return retVal
def getErrorParsedDBMSes(): def getErrorParsedDBMSes():
""" """
Returns array with parsed DBMS Returns array with parsed DBMS names till now
names till now
""" """
return kb.htmlFp return kb.htmlFp
def showHttpErrorCodes(): def showHttpErrorCodes():
""" """
Shows all HTTP error codes Shows all HTTP error codes raised till now
raised till now
""" """
if kb.httpErrorCodes: if kb.httpErrorCodes:
warnMsg = "HTTP error codes detected during testing:\n" warnMsg = "HTTP error codes detected during testing:\n"
warnMsg += ", ".join("%d (%s) - %d times" % (code, httplib.responses[code]\ warnMsg += ", ".join("%d (%s) - %d times" % (code, httplib.responses[code] \
if code in httplib.responses else '?', count)\ if code in httplib.responses else '?', count) \
for code, count in kb.httpErrorCodes.items()) for code, count in kb.httpErrorCodes.items())
logger.warn(warnMsg) logger.warn(warnMsg)
def getComparePageRatio(firstPage, secondPage, filtered=False): def getComparePageRatio(firstPage, secondPage, filtered=False):
""" """
Returns comparison ratio between Returns comparison ratio between two given pages
two given pages
""" """
if filtered: if filtered:
firstPage = getFilteredPageContent(firstPage) firstPage = getFilteredPageContent(firstPage)
secondPage = getFilteredPageContent(secondPage) secondPage = getFilteredPageContent(secondPage)

View File

@ -98,6 +98,7 @@ class PAYLOAD:
COMPARISON = "comparison" COMPARISON = "comparison"
GREP = "grep" GREP = "grep"
TIME = "time" TIME = "time"
UNION = "union"
class TECHNIQUE: class TECHNIQUE:
HEURISTIC = 0 HEURISTIC = 0

View File

@ -12,6 +12,11 @@ from lib.core.datatype import advancedDict
class Unescaper(advancedDict): class Unescaper(advancedDict):
def unescape(self, expression, quote=True): 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() unescaper = Unescaper()

View File

@ -67,11 +67,12 @@ def parseResponse(page, headers):
htmlParser(page) htmlParser(page)
# Detect injectable page absolute system path # Detect injectable page absolute system path
# NOTE: this regular expression works if the remote web application # NOTE: this regular expression works if the remote web
# is written in PHP and debug/error messages are enabled. # application is written in PHP and debug/error messages are
# enabled
for regex in ( r" in <b>(?P<result>.*?)</b> on line", r"(?:>|\s)(?P<result>[A-Za-z]:[\\/][\w.\\/]*)", r"(?:>|\s)(?P<result>/\w[/\w.]+)" ): for regex in ( r" in <b>(?P<result>.*?)</b> on line", r"(?:>|\s)(?P<result>[A-Za-z]:[\\/][\w.\\/]*)", r"(?:>|\s)(?P<result>/\w[/\w.]+)" ):
regObj = getCompiledRegex(regex) regObj = getCompiledRegex(regex)
for match in regObj.finditer(page): for match in regObj.finditer(page):
absFilePath = match.group("result").strip() absFilePath = match.group("result").strip()
page = page.replace(absFilePath, "") page = page.replace(absFilePath, "")
@ -145,10 +146,13 @@ def decodePage(page, contentEncoding, contentType):
def processResponse(page, responseHeaders): def processResponse(page, responseHeaders):
page = getUnicode(page) page = getUnicode(page)
parseResponse(page, responseHeaders) parseResponse(page, responseHeaders)
if conf.parseErrors: if conf.parseErrors:
msg = extractErrorMessage(page) msg = extractErrorMessage(page)
if msg: if msg:
logger.info("parsed error message: '%s'" % msg) logger.info("parsed error message: '%s'" % msg)
return page return page

View File

@ -428,7 +428,7 @@ class Connect:
logger.warn(warnMsg) logger.warn(warnMsg)
while len(kb.responseTimes) < MIN_TIME_RESPONSES: while len(kb.responseTimes) < MIN_TIME_RESPONSES:
_ = Connect.queryPage(content=True) Connect.queryPage(content=True)
if conf.safUrl and conf.saFreq > 0: if conf.safUrl and conf.saFreq > 0:
kb.queryCounter += 1 kb.queryCounter += 1

View File

@ -151,8 +151,7 @@ Tag: <test>
Sub-tag: <grep> Sub-tag: <grep>
Regular expression to grep for in the response body. Regular expression to grep for in the response body.
NOTE: useful to test for error-based and UNION query SQL NOTE: useful to test for error-based SQL injection.
injections.
Sub-tag: <time> Sub-tag: <time>
Time in seconds to wait before the response is returned. Time in seconds to wait before the response is returned.
@ -160,7 +159,12 @@ Tag: <test>
NOTE: useful to test for time-based blind and stacked queries NOTE: useful to test for time-based blind and stacked queries
SQL injections. SQL injections.
Sub-tag: <out-of-band> Sub-tag: <union>
Calls unionTest() function.
NOTE: useful to test for UNION query (inband) SQL injection.
Sub-tag: <oob>
# TODO # TODO
Sub-tag: <details> Sub-tag: <details>
@ -202,6 +206,8 @@ Formats:
<comparison></comparison> <comparison></comparison>
<grep></grep> <grep></grep>
<time></time> <time></time>
<union></union>
<oob></oob>
</response> </response>
<details> <details>
<dbms></dbms> <dbms></dbms>
@ -1818,43 +1824,4 @@ Formats:
<!-- TODO: if possible, add payload for Microsoft Access and SAP MaxDB --> <!-- TODO: if possible, add payload for Microsoft Access and SAP MaxDB -->
<!-- End of OR time-based blind tests --> <!-- End of OR time-based blind tests -->
<!-- UNION query tests -->
<!-- TODO: sure about all these clauses? Verify on every DBMS -->
<!--
<test>
<title>UNION query</title>
<stype>3</stype>
<level>1</level>
<risk>1</risk>
<clause>1,2,3,4,5</clause>
<where>1</where>
<vector>UNION ALL SELECT [UNION_STRING]</vector>
<request>
<payload>UNION ALL SELECT [UNION_TEST]</payload>
<comment></comment>
</request>
<response>
<grep>[DELIMITER_START](?P&lt;result&gt;.*?)[DELIMITER_STOP]</grep>
</response>
</test>
<test>
<title>Single-entry UNION query</title>
<stype>3</stype>
<level>1</level>
<risk>1</risk>
<clause>1,2,3,4,5</clause>
<where>2</where>
<vector>UNION ALL SELECT [UNION_STRING]</vector>
<request>
<payload>UNION ALL SELECT [UNION_TEST]</payload>
<comment></comment>
</request>
<response>
<grep>[DELIMITER_START](?P&lt;result&gt;.*?)[DELIMITER_STOP]</grep>
</response>
</test>
-->
<!-- End of UNION query tests -->
</root> </root>