Improved --union-cols to accept a range to test for union SQL injection. By default it is 1-20.

This commit is contained in:
Bernardo Damele 2010-11-19 15:48:24 +00:00
parent ad17e9ed2a
commit c23126547e
4 changed files with 59 additions and 47 deletions

View File

@ -488,36 +488,50 @@ def __setWriteFile():
conf.wFileType = getFileType(conf.wFile) conf.wFileType = getFileType(conf.wFile)
def __setUnion(): def __setUnion():
if isinstance(conf.uChar, basestring) and conf.uChar != "NULL" and not conf.uChar.isdigit(): if isinstance(conf.uTech, basestring):
if not conf.uChar.startswith("'") or not conf.uChar.endswith("'"): debugMsg = "setting the UNION query SQL injection detection technique"
debugMsg = "setting the UNION query SQL injection character to '%s'" % conf.uChar logger.debug(debugMsg)
uTechOriginal = conf.uTech
conf.uTech = conf.uTech.lower()
if conf.uTech and conf.uTech not in ( "char", "orderby" ):
infoMsg = "resetting the UNION query detection technique to "
infoMsg += "'char', '%s' is not a valid technique" % uTechOriginal
logger.info(infoMsg)
conf.uTech = "char"
else:
debugMsg = "setting UNION query detection technique to "
debugMsg += "'%s'" % uTechOriginal
logger.debug(debugMsg)
if isinstance(conf.uCols, basestring) and conf.uChar != "1-20":
debugMsg = "setting the UNION query SQL injection range of columns"
logger.debug(debugMsg)
if "-" not in conf.uCols:
raise sqlmapSyntaxException, "--union-cols must be a range with hyphon"
conf.uCols = conf.uCols.replace(" ", "")
conf.uColsStart, conf.uColsStop = conf.uCols.split("-")
if not conf.uColsStart.isdigit() or not conf.uColsStop.isdigit():
raise sqlmapSyntaxException, "--union-cols must be a range of integers"
conf.uColsStart = int(conf.uColsStart)
conf.uColsStop = int(conf.uColsStop)
if isinstance(conf.uChar, basestring) and conf.uChar != "NULL":
debugMsg = "setting the UNION query SQL injection character to '%s'" % conf.uChar
logger.debug(debugMsg)
if not conf.uChar.isdigit() and ( not conf.uChar.startswith("'") or not conf.uChar.endswith("'") ):
debugMsg = "forcing the UNION query SQL injection character to '%s'" % conf.uChar
logger.debug(debugMsg) logger.debug(debugMsg)
conf.uChar = "'%s'" % conf.uChar conf.uChar = "'%s'" % conf.uChar
if conf.uTech is None:
conf.uTech = "NULL"
return
debugMsg = "setting the UNION query SQL injection detection technique"
logger.debug(debugMsg)
uTechOriginal = conf.uTech
conf.uTech = conf.uTech.lower()
if conf.uTech and conf.uTech not in ( "null", "orderby" ):
infoMsg = "resetting the UNION query detection technique to "
infoMsg += "'NULL', '%s' is not a valid technique" % uTechOriginal
logger.info(infoMsg)
conf.uTech = "NULL"
else:
debugMsg = "setting UNION query detection technique to "
debugMsg += "'%s'" % uTechOriginal
logger.debug(debugMsg)
def __setOS(): def __setOS():
""" """
Force the back-end DBMS operating system option. Force the back-end DBMS operating system option.

View File

@ -240,11 +240,11 @@ def cmdLineParser():
action="store_true", default=False, action="store_true", default=False,
help="Test for and use UNION query (inband) SQL injection") help="Test for and use UNION query (inband) SQL injection")
techniques.add_option("--union-tech", dest="uTech", techniques.add_option("--union-tech", dest="uTech", default="char",
help="Technique to test for UNION query SQL injection") help="Technique to test for UNION query SQL injection")
techniques.add_option("--union-cols", dest="uCols", type="int", default=20, techniques.add_option("--union-cols", dest="uCols", default="1-20",
help="Maximum number of columns to test for") help="Range of columns to test for UNION query SQL injection")
techniques.add_option("--union-char", dest="uChar", default="NULL", techniques.add_option("--union-char", dest="uChar", default="NULL",
help="Character to use to bruteforce number of columns") help="Character to use to bruteforce number of columns")

View File

@ -99,7 +99,7 @@ def __unionTestByCharBruteforce(comment):
query = agent.prefixQuery("UNION ALL SELECT %s" % conf.uChar) query = agent.prefixQuery("UNION ALL SELECT %s" % conf.uChar)
for count in range(1, conf.uCols+1): for count in range(conf.uColsStart, conf.uColsStop+1):
if kb.dbms == DBMS.ORACLE and query.endswith(" FROM DUAL"): if kb.dbms == DBMS.ORACLE and query.endswith(" FROM DUAL"):
query = query[:-len(" FROM DUAL")] query = query[:-len(" FROM DUAL")]
@ -121,7 +121,7 @@ def __unionTestByOrderBy(comment):
columns = None columns = None
prevPayload = "" prevPayload = ""
for count in range(1, conf.uCols+2): for count in range(conf.uColsStart, conf.uColsStop+1):
query = agent.prefixQuery("ORDER BY %d" % count) query = agent.prefixQuery("ORDER BY %d" % count)
orderByQuery = agent.suffixQuery(query, comment) orderByQuery = agent.suffixQuery(query, comment)
payload = agent.payload(newValue=orderByQuery, negative=negative, falseCond=falseCond) payload = agent.payload(newValue=orderByQuery, negative=negative, falseCond=falseCond)
@ -161,17 +161,15 @@ def unionTest():
logger.info(infoMsg) logger.info(infoMsg)
validPayload = None validPayload = None
comment = queries[kb.dbms].comment.query
for comment in (queries[kb.dbms].comment.query, ""): if conf.uTech == "orderby":
if conf.uTech == "orderby": validPayload = __unionTestByOrderBy(comment)
validPayload = __unionTestByOrderBy(comment) else:
else: validPayload = __unionTestByCharBruteforce(comment)
validPayload = __unionTestByCharBruteforce(comment)
if validPayload: if validPayload:
setUnion(comment=comment) setUnion(comment=comment)
break
if isinstance(kb.unionPosition, int): if isinstance(kb.unionPosition, int):
infoMsg = "the target url is affected by an exploitable " infoMsg = "the target url is affected by an exploitable "

View File

@ -256,14 +256,14 @@ unionTest = False
# Technique to test for UNION query SQL injection # Technique to test for UNION query SQL injection
# The possible techniques are by NULL bruteforcing (bf) or by ORDER BY # The possible techniques are by NULL bruteforcing (bf) or by ORDER BY
# clause (ob) # clause (ob)
# Valid: NULL, OrderBy # Valid: char, OrderBy
# Default: NULL # Default: char
uTech = NULL uTech = char
# Maximum number of columns to test for # Range of columns to test for
# Valid: integer # Valid: range of integers
# Default: 20 # Default: 1-20
uCols = 20 uCols = 1-20
# Character to use to bruteforce number of columns # Character to use to bruteforce number of columns
# Valid: string # Valid: string