mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-02-03 13:14:13 +03:00
Code refactoring and cosmetics
This commit is contained in:
parent
a8d660db54
commit
1c86ec374e
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
if hasattr(kb, "dbms") and kb.dbms is not None:
|
||||||
return self[kb.dbms if kb.dbms else kb.misc.testedDbms](expression, quote=quote)
|
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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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<result>.*?)[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<result>.*?)[DELIMITER_STOP]</grep>
|
|
||||||
</response>
|
|
||||||
</test>
|
|
||||||
-->
|
|
||||||
<!-- End of UNION query tests -->
|
|
||||||
|
|
||||||
</root>
|
</root>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user