mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-02-16 19:40:37 +03:00
Added generic and mysql UNION tests from 1 to 25 columns.
Adapted config file and command line removing now outdated --union-test switch. Minor bug fix. Minor code refactoring. Got rid of some debug messages, standardized logging of UNION tests.
This commit is contained in:
parent
300128042c
commit
2f5995a7eb
|
@ -17,7 +17,6 @@ from lib.core.exception import sqlmapUnsupportedDBMSException
|
||||||
from lib.core.settings import SUPPORTED_DBMS
|
from lib.core.settings import SUPPORTED_DBMS
|
||||||
from lib.techniques.brute.use import columnExists
|
from lib.techniques.brute.use import columnExists
|
||||||
from lib.techniques.brute.use import tableExists
|
from lib.techniques.brute.use import tableExists
|
||||||
from lib.techniques.inband.union.test import unionTest
|
|
||||||
|
|
||||||
def action():
|
def action():
|
||||||
"""
|
"""
|
||||||
|
@ -56,10 +55,6 @@ def action():
|
||||||
|
|
||||||
dataToStdout("%s\n" % conf.dbmsHandler.getFingerprint())
|
dataToStdout("%s\n" % conf.dbmsHandler.getFingerprint())
|
||||||
|
|
||||||
# Techniques options
|
|
||||||
if conf.unionTest and kb.unionPosition is None:
|
|
||||||
conf.dumper.technic("inband injection payload", unionTest())
|
|
||||||
|
|
||||||
# Enumeration options
|
# Enumeration options
|
||||||
if conf.getBanner:
|
if conf.getBanner:
|
||||||
conf.dumper.banner(conf.dbmsHandler.getBanner())
|
conf.dumper.banner(conf.dbmsHandler.getBanner())
|
||||||
|
|
|
@ -235,7 +235,6 @@ def checkSqlInjection(place, parameter, value):
|
||||||
# default) value
|
# default) value
|
||||||
# Parse boundary's <level>
|
# Parse boundary's <level>
|
||||||
if boundary.level > conf.level:
|
if boundary.level > conf.level:
|
||||||
# NOTE: shall we report every single skipped boundary too?
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Skip boundary if it does not match against test's <clause>
|
# Skip boundary if it does not match against test's <clause>
|
||||||
|
@ -377,9 +376,7 @@ def checkSqlInjection(place, parameter, value):
|
||||||
|
|
||||||
# In case of UNION query SQL injection
|
# In case of UNION query SQL injection
|
||||||
elif method == PAYLOAD.METHOD.UNION:
|
elif method == PAYLOAD.METHOD.UNION:
|
||||||
conf.uChar = test.request.char
|
configUnion(test.request.char, test.request.columns)
|
||||||
conf.uCols = test.request.columns
|
|
||||||
configUnion()
|
|
||||||
|
|
||||||
reqPayload, unionVector = unionTest(comment, place, parameter, value, prefix, suffix)
|
reqPayload, unionVector = unionTest(comment, place, parameter, value, prefix, suffix)
|
||||||
|
|
||||||
|
|
|
@ -2066,34 +2066,37 @@ def openFile(filename, mode='r'):
|
||||||
errMsg += "and that it's not locked by another process."
|
errMsg += "and that it's not locked by another process."
|
||||||
raise sqlmapFilePathException, errMsg
|
raise sqlmapFilePathException, errMsg
|
||||||
|
|
||||||
def configUnion():
|
def __configUnionChar(char):
|
||||||
|
if char.isdigit() or char == "NULL":
|
||||||
|
conf.uChar = char
|
||||||
|
elif not char.startswith("'") or not char.endswith("'"):
|
||||||
|
conf.uChar = "'%s'" % char
|
||||||
|
|
||||||
|
def __configUnionCols(columns):
|
||||||
|
if "-" not in columns or len(columns.split("-")) != 2:
|
||||||
|
raise sqlmapSyntaxException, "--union-cols must be a range with hyphon (e.g. 1-10)"
|
||||||
|
|
||||||
|
columns = columns.replace(" ", "")
|
||||||
|
conf.uColsStart, conf.uColsStop = columns.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 conf.uColsStart > conf.uColsStop:
|
||||||
|
errMsg = "--union-cols range has to be from lower to "
|
||||||
|
errMsg += "higher number of columns"
|
||||||
|
raise sqlmapSyntaxException, errMsg
|
||||||
|
|
||||||
|
def configUnion(char, columns):
|
||||||
|
if isinstance(conf.uChar, basestring):
|
||||||
|
__configUnionChar(conf.uChar)
|
||||||
|
elif isinstance(char, basestring):
|
||||||
|
__configUnionChar(char)
|
||||||
|
|
||||||
if isinstance(conf.uCols, basestring):
|
if isinstance(conf.uCols, basestring):
|
||||||
debugMsg = "setting the UNION query SQL injection range of columns"
|
__configUnionCols(conf.uCols)
|
||||||
logger.debug(debugMsg)
|
elif isinstance(columns, basestring):
|
||||||
|
__configUnionCols(columns)
|
||||||
if "-" not in conf.uCols or len(conf.uCols.split("-")) != 2:
|
|
||||||
raise sqlmapSyntaxException, "--union-cols must be a range with hyphon (e.g. 1-10)"
|
|
||||||
|
|
||||||
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 conf.uColsStart > conf.uColsStop:
|
|
||||||
errMsg = "--union-cols range has to be from lower to "
|
|
||||||
errMsg += "higher number of columns"
|
|
||||||
raise sqlmapSyntaxException, errMsg
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
conf.uChar = "'%s'" % conf.uChar
|
|
||||||
|
|
|
@ -76,7 +76,6 @@ optDict = {
|
||||||
|
|
||||||
"Techniques": {
|
"Techniques": {
|
||||||
"timeSec": "integer",
|
"timeSec": "integer",
|
||||||
"unionTest": "boolean",
|
|
||||||
"uCols": "string",
|
"uCols": "string",
|
||||||
"uChar": "string"
|
"uChar": "string"
|
||||||
},
|
},
|
||||||
|
|
|
@ -231,14 +231,10 @@ def cmdLineParser():
|
||||||
help="Seconds to delay the DBMS response "
|
help="Seconds to delay the DBMS response "
|
||||||
"(default 5)")
|
"(default 5)")
|
||||||
|
|
||||||
techniques.add_option("--union-test", dest="unionTest",
|
|
||||||
action="store_true", default=False,
|
|
||||||
help="Test for and use UNION query (inband) SQL injection")
|
|
||||||
|
|
||||||
techniques.add_option("--union-cols", dest="uCols",
|
techniques.add_option("--union-cols", dest="uCols",
|
||||||
help="Range of columns to test for UNION query SQL injection")
|
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",
|
||||||
help="Character to use to bruteforce number of columns")
|
help="Character to use to bruteforce number of columns")
|
||||||
|
|
||||||
# Fingerprint options
|
# Fingerprint options
|
||||||
|
|
|
@ -81,17 +81,11 @@ def __unionConfirm(comment, place, parameter, value, prefix, suffix, count):
|
||||||
# Confirm the inband SQL injection and get the exact column
|
# Confirm the inband SQL injection and get the exact column
|
||||||
# position which can be used to extract data
|
# position which can be used to extract data
|
||||||
if not isinstance(kb.unionPosition, int):
|
if not isinstance(kb.unionPosition, int):
|
||||||
debugMsg = "testing full inband with %s columns" % count
|
|
||||||
logger.debug(debugMsg)
|
|
||||||
|
|
||||||
validPayload, unionVector = __unionPosition(comment, place, parameter, value, prefix, suffix, count)
|
validPayload, unionVector = __unionPosition(comment, place, parameter, value, prefix, suffix, count)
|
||||||
|
|
||||||
# Assure that the above function found the exploitable full inband
|
# Assure that the above function found the exploitable full inband
|
||||||
# SQL injection position
|
# SQL injection position
|
||||||
if not isinstance(kb.unionPosition, int):
|
if not isinstance(kb.unionPosition, int):
|
||||||
debugMsg = "testing single-entry inband with %s columns" % count
|
|
||||||
logger.debug(debugMsg)
|
|
||||||
|
|
||||||
validPayload, unionVector = __unionPosition(comment, place, parameter, value, prefix, suffix, count, where=2)
|
validPayload, unionVector = __unionPosition(comment, place, parameter, value, prefix, suffix, count, where=2)
|
||||||
|
|
||||||
# Assure that the above function found the exploitable partial
|
# Assure that the above function found the exploitable partial
|
||||||
|
@ -125,11 +119,9 @@ def __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix
|
||||||
if kb.dbms == DBMS.ORACLE:
|
if kb.dbms == DBMS.ORACLE:
|
||||||
query += " FROM DUAL"
|
query += " FROM DUAL"
|
||||||
|
|
||||||
if conf.verbose in (1, 2):
|
status = '%d/%d (%d%s)' % (count, conf.uColsStop, round(100.0*count/conf.uColsStop), '%')
|
||||||
status = '%d/%d (%d%s)' % (count, conf.uColsStop, round(100.0*count/conf.uColsStop), '%')
|
debugMsg = "testing number of columns: %s" % status
|
||||||
dataToStdout("\r[%s] [INFO] number of columns: %s" % (time.strftime("%X"), status), True)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
dataToStdout("\n")
|
|
||||||
|
|
||||||
validPayload, unionVector = __unionConfirm(comment, place, parameter, value, prefix, suffix, count)
|
validPayload, unionVector = __unionConfirm(comment, place, parameter, value, prefix, suffix, count)
|
||||||
|
|
||||||
|
@ -152,12 +144,6 @@ def unionTest(comment, place, parameter, value, prefix, suffix):
|
||||||
|
|
||||||
oldTechnique = kb.technique
|
oldTechnique = kb.technique
|
||||||
kb.technique = PAYLOAD.TECHNIQUE.UNION
|
kb.technique = PAYLOAD.TECHNIQUE.UNION
|
||||||
|
|
||||||
if conf.uChar == "NULL":
|
|
||||||
technique = "NULL bruteforcing"
|
|
||||||
else:
|
|
||||||
technique = "char (%s) bruteforcing" % conf.uChar
|
|
||||||
|
|
||||||
validPayload, unionVector = __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix)
|
validPayload, unionVector = __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix)
|
||||||
|
|
||||||
if validPayload:
|
if validPayload:
|
||||||
|
|
12
sqlmap.conf
12
sqlmap.conf
|
@ -251,19 +251,15 @@ longestCommon = False
|
||||||
# Default: 5
|
# Default: 5
|
||||||
timeSec = 5
|
timeSec = 5
|
||||||
|
|
||||||
# Test for and use UNION query (inband) SQL injection.
|
|
||||||
# Valid: True or False
|
|
||||||
unionTest = False
|
|
||||||
|
|
||||||
# Range of columns to test for
|
# Range of columns to test for
|
||||||
# Valid: range of integers
|
# Valid: range of integers
|
||||||
# Default: 1-20
|
# Example: 1-10
|
||||||
uCols = 1-20
|
uCols =
|
||||||
|
|
||||||
# Character to use to bruteforce number of columns
|
# Character to use to bruteforce number of columns
|
||||||
# Valid: string
|
# Valid: string
|
||||||
# Default: NULL
|
# Example: NULL
|
||||||
uChar = NULL
|
uChar =
|
||||||
|
|
||||||
|
|
||||||
[Fingerprint]
|
[Fingerprint]
|
||||||
|
|
167
xml/payloads.xml
167
xml/payloads.xml
|
@ -1856,15 +1856,38 @@ 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 -->
|
<!-- UNION query tests -->
|
||||||
<test>
|
<test>
|
||||||
<title>MySQL NULL UNION query - 4 to 7 columns</title>
|
<title>MySQL NULL UNION query - 1 to 3 columns</title>
|
||||||
<stype>3</stype>
|
<stype>3</stype>
|
||||||
<level>1</level>
|
<level>1</level>
|
||||||
<risk>1</risk>
|
<risk>1</risk>
|
||||||
<clause>1,2,3,4,5</clause>
|
<clause>1,2,3,4,5</clause>
|
||||||
<where>1</where>
|
<where>1</where>
|
||||||
<vector>[UNION]</vector>
|
<vector>[UNION]</vector>
|
||||||
|
<request>
|
||||||
|
<payload/>
|
||||||
|
<comment>#</comment>
|
||||||
|
<char>NULL</char>
|
||||||
|
<columns>1-3</columns>
|
||||||
|
</request>
|
||||||
|
<response>
|
||||||
|
<union/>
|
||||||
|
</response>
|
||||||
|
<details>
|
||||||
|
<dbms>MySQL</dbms>
|
||||||
|
</details>
|
||||||
|
</test>
|
||||||
|
|
||||||
|
<test>
|
||||||
|
<title>MySQL NULL UNION query - 4 to 7 columns</title>
|
||||||
|
<stype>3</stype>
|
||||||
|
<level>2</level>
|
||||||
|
<risk>1</risk>
|
||||||
|
<clause>1,2,3,4,5</clause>
|
||||||
|
<where>1</where>
|
||||||
|
<vector>[UNION]</vector>
|
||||||
<request>
|
<request>
|
||||||
<payload/>
|
<payload/>
|
||||||
<comment>#</comment>
|
<comment>#</comment>
|
||||||
|
@ -1879,6 +1902,72 @@ Formats:
|
||||||
</details>
|
</details>
|
||||||
</test>
|
</test>
|
||||||
|
|
||||||
|
<test>
|
||||||
|
<title>MySQL NULL UNION query - 8 to 12 columns</title>
|
||||||
|
<stype>3</stype>
|
||||||
|
<level>3</level>
|
||||||
|
<risk>1</risk>
|
||||||
|
<clause>1,2,3,4,5</clause>
|
||||||
|
<where>1</where>
|
||||||
|
<vector>[UNION]</vector>
|
||||||
|
<request>
|
||||||
|
<payload/>
|
||||||
|
<comment>#</comment>
|
||||||
|
<char>NULL</char>
|
||||||
|
<columns>8-12</columns>
|
||||||
|
</request>
|
||||||
|
<response>
|
||||||
|
<union/>
|
||||||
|
</response>
|
||||||
|
<details>
|
||||||
|
<dbms>MySQL</dbms>
|
||||||
|
</details>
|
||||||
|
</test>
|
||||||
|
|
||||||
|
<test>
|
||||||
|
<title>MySQL NULL UNION query - 13 to 18 columns</title>
|
||||||
|
<stype>3</stype>
|
||||||
|
<level>4</level>
|
||||||
|
<risk>1</risk>
|
||||||
|
<clause>1,2,3,4,5</clause>
|
||||||
|
<where>1</where>
|
||||||
|
<vector>[UNION]</vector>
|
||||||
|
<request>
|
||||||
|
<payload/>
|
||||||
|
<comment>#</comment>
|
||||||
|
<char>NULL</char>
|
||||||
|
<columns>13-18</columns>
|
||||||
|
</request>
|
||||||
|
<response>
|
||||||
|
<union/>
|
||||||
|
</response>
|
||||||
|
<details>
|
||||||
|
<dbms>MySQL</dbms>
|
||||||
|
</details>
|
||||||
|
</test>
|
||||||
|
|
||||||
|
<test>
|
||||||
|
<title>MySQL NULL UNION query - 19 to 25 columns</title>
|
||||||
|
<stype>3</stype>
|
||||||
|
<level>5</level>
|
||||||
|
<risk>1</risk>
|
||||||
|
<clause>1,2,3,4,5</clause>
|
||||||
|
<where>1</where>
|
||||||
|
<vector>[UNION]</vector>
|
||||||
|
<request>
|
||||||
|
<payload/>
|
||||||
|
<comment>#</comment>
|
||||||
|
<char>NULL</char>
|
||||||
|
<columns>19-25</columns>
|
||||||
|
</request>
|
||||||
|
<response>
|
||||||
|
<union/>
|
||||||
|
</response>
|
||||||
|
<details>
|
||||||
|
<dbms>MySQL</dbms>
|
||||||
|
</details>
|
||||||
|
</test>
|
||||||
|
|
||||||
<test>
|
<test>
|
||||||
<title>Generic NULL UNION query - 1 to 3 columns</title>
|
<title>Generic NULL UNION query - 1 to 3 columns</title>
|
||||||
<stype>3</stype>
|
<stype>3</stype>
|
||||||
|
@ -1897,6 +1986,82 @@ Formats:
|
||||||
<union/>
|
<union/>
|
||||||
</response>
|
</response>
|
||||||
</test>
|
</test>
|
||||||
|
|
||||||
|
<test>
|
||||||
|
<title>Generic NULL UNION query - 4 to 7 columns</title>
|
||||||
|
<stype>3</stype>
|
||||||
|
<level>2</level>
|
||||||
|
<risk>1</risk>
|
||||||
|
<clause>1,2,3,4,5</clause>
|
||||||
|
<where>1</where>
|
||||||
|
<vector>[UNION]</vector>
|
||||||
|
<request>
|
||||||
|
<payload/>
|
||||||
|
<comment>--</comment>
|
||||||
|
<char>NULL</char>
|
||||||
|
<columns>4-7</columns>
|
||||||
|
</request>
|
||||||
|
<response>
|
||||||
|
<union/>
|
||||||
|
</response>
|
||||||
|
</test>
|
||||||
|
|
||||||
|
<test>
|
||||||
|
<title>Generic NULL UNION query - 8 to 12 columns</title>
|
||||||
|
<stype>3</stype>
|
||||||
|
<level>3</level>
|
||||||
|
<risk>1</risk>
|
||||||
|
<clause>1,2,3,4,5</clause>
|
||||||
|
<where>1</where>
|
||||||
|
<vector>[UNION]</vector>
|
||||||
|
<request>
|
||||||
|
<payload/>
|
||||||
|
<comment>--</comment>
|
||||||
|
<char>NULL</char>
|
||||||
|
<columns>8-12</columns>
|
||||||
|
</request>
|
||||||
|
<response>
|
||||||
|
<union/>
|
||||||
|
</response>
|
||||||
|
</test>
|
||||||
|
|
||||||
|
<test>
|
||||||
|
<title>Generic NULL UNION query - 13 to 18 columns</title>
|
||||||
|
<stype>3</stype>
|
||||||
|
<level>4</level>
|
||||||
|
<risk>1</risk>
|
||||||
|
<clause>1,2,3,4,5</clause>
|
||||||
|
<where>1</where>
|
||||||
|
<vector>[UNION]</vector>
|
||||||
|
<request>
|
||||||
|
<payload/>
|
||||||
|
<comment>--</comment>
|
||||||
|
<char>NULL</char>
|
||||||
|
<columns>13-18</columns>
|
||||||
|
</request>
|
||||||
|
<response>
|
||||||
|
<union/>
|
||||||
|
</response>
|
||||||
|
</test>
|
||||||
|
|
||||||
|
<test>
|
||||||
|
<title>Generic NULL UNION query - 19 to 25 columns</title>
|
||||||
|
<stype>3</stype>
|
||||||
|
<level>5</level>
|
||||||
|
<risk>1</risk>
|
||||||
|
<clause>1,2,3,4,5</clause>
|
||||||
|
<where>1</where>
|
||||||
|
<vector>[UNION]</vector>
|
||||||
|
<request>
|
||||||
|
<payload/>
|
||||||
|
<comment>--</comment>
|
||||||
|
<char>NULL</char>
|
||||||
|
<columns>19-25</columns>
|
||||||
|
</request>
|
||||||
|
<response>
|
||||||
|
<union/>
|
||||||
|
</response>
|
||||||
|
</test>
|
||||||
<!-- End of UNION query tests -->
|
<!-- End of UNION query tests -->
|
||||||
|
|
||||||
</root>
|
</root>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user