mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2024-11-22 09:36:35 +03:00
Rewrite from scratch the detection engine. Now it performs checks defined in payload.xml. User can specify its own.
All (hopefully) functionalities should still be working. Added two switches, --level and --risk to specify which injection tests and boundaries to use. The main advantage now is that sqlmap is able to identify initially which injection types are present so for instance if boolean-based blind is not supported, but error-based is, sqlmap will keep going and work!
This commit is contained in:
parent
a8b38ba76b
commit
7e3b24afe6
|
@ -15,6 +15,7 @@ from difflib import SequenceMatcher
|
||||||
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import beep
|
from lib.core.common import beep
|
||||||
|
from lib.core.common import calculateDeltaSeconds
|
||||||
from lib.core.common import getUnicode
|
from lib.core.common import getUnicode
|
||||||
from lib.core.common import randomInt
|
from lib.core.common import randomInt
|
||||||
from lib.core.common import randomStr
|
from lib.core.common import randomStr
|
||||||
|
@ -26,8 +27,11 @@ from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
from lib.core.data import paths
|
from lib.core.data import paths
|
||||||
|
from lib.core.datatype import advancedDict
|
||||||
|
from lib.core.datatype import injectionDict
|
||||||
from lib.core.enums import HTTPMETHOD
|
from lib.core.enums import HTTPMETHOD
|
||||||
from lib.core.enums import NULLCONNECTION
|
from lib.core.enums import NULLCONNECTION
|
||||||
|
from lib.core.enums import PAYLOAD
|
||||||
from lib.core.exception import sqlmapConnectionException
|
from lib.core.exception import sqlmapConnectionException
|
||||||
from lib.core.exception import sqlmapGenericException
|
from lib.core.exception import sqlmapGenericException
|
||||||
from lib.core.exception import sqlmapNoneDataException
|
from lib.core.exception import sqlmapNoneDataException
|
||||||
|
@ -35,78 +39,274 @@ from lib.core.exception import sqlmapSiteTooDynamic
|
||||||
from lib.core.exception import sqlmapUserQuitException
|
from lib.core.exception import sqlmapUserQuitException
|
||||||
from lib.core.session import setString
|
from lib.core.session import setString
|
||||||
from lib.core.session import setRegexp
|
from lib.core.session import setRegexp
|
||||||
|
from lib.core.settings import ERROR_SPACE
|
||||||
|
from lib.core.settings import ERROR_EMPTY_CHAR
|
||||||
from lib.request.connect import Connect as Request
|
from lib.request.connect import Connect as Request
|
||||||
|
from plugins.dbms.firebird.syntax import Syntax as Firebird
|
||||||
|
from plugins.dbms.postgresql.syntax import Syntax as PostgreSQL
|
||||||
|
from plugins.dbms.mssqlserver.syntax import Syntax as MSSQLServer
|
||||||
|
from plugins.dbms.oracle.syntax import Syntax as Oracle
|
||||||
|
from plugins.dbms.mysql.syntax import Syntax as MySQL
|
||||||
|
from plugins.dbms.access.syntax import Syntax as Access
|
||||||
|
from plugins.dbms.sybase.syntax import Syntax as Sybase
|
||||||
|
from plugins.dbms.sqlite.syntax import Syntax as SQLite
|
||||||
|
from plugins.dbms.maxdb.syntax import Syntax as MaxDB
|
||||||
|
|
||||||
def checkSqlInjection(place, parameter, value, parenthesis):
|
|
||||||
"""
|
|
||||||
This function checks if the GET, POST, Cookie, User-Agent
|
|
||||||
parameters are affected by a SQL injection vulnerability and
|
|
||||||
identifies the type of SQL injection:
|
|
||||||
|
|
||||||
* Unescaped numeric injection
|
def unescape(string, dbms):
|
||||||
* Single quoted string injection
|
unescaper = {
|
||||||
* Double quoted string injection
|
"Access": Access.unescape,
|
||||||
"""
|
"Firebird": Firebird.unescape,
|
||||||
|
"MaxDB": MaxDB.unescape,
|
||||||
|
"Microsoft SQL Server": MSSQLServer.unescape,
|
||||||
|
"MySQL": MySQL.unescape,
|
||||||
|
"Oracle": Oracle.unescape,
|
||||||
|
"PostgreSQL": PostgreSQL.unescape,
|
||||||
|
"SQLite": SQLite.unescape,
|
||||||
|
"Sybase": Sybase.unescape
|
||||||
|
}
|
||||||
|
|
||||||
logic = conf.logic
|
if isinstance(dbms, list):
|
||||||
randInt = randomInt()
|
dbmsunescaper = unescaper[dbms[0]]
|
||||||
randStr = randomStr()
|
else:
|
||||||
prefix = ""
|
dbmsunescaper = unescaper[dbms]
|
||||||
suffix = ""
|
|
||||||
retVal = None
|
|
||||||
|
|
||||||
if conf.prefix or conf.suffix:
|
return dbmsunescaper(string)
|
||||||
if conf.prefix:
|
|
||||||
prefix = conf.prefix
|
|
||||||
|
|
||||||
if conf.suffix:
|
def checkSqlInjection(place, parameter, value):
|
||||||
suffix = conf.suffix
|
# Store here the details about boundaries and payload used to
|
||||||
|
# successfully inject
|
||||||
|
injection = injectionDict()
|
||||||
|
|
||||||
for case in kb.injections.root.case:
|
for test in conf.tests:
|
||||||
conf.matchRatio = None
|
title = test.title
|
||||||
|
stype = test.stype
|
||||||
|
proceed = True
|
||||||
|
|
||||||
positive = case.test.positive
|
# Parse test's <risk>
|
||||||
negative = case.test.negative
|
if test.risk > conf.risk:
|
||||||
|
debugMsg = "skipping test '%s' because the risk " % title
|
||||||
if not prefix and not suffix and case.name == "custom":
|
debugMsg += "is higher than the provided"
|
||||||
|
logger.debug(debugMsg)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
infoMsg = "testing %s (%s) injection " % (case.desc, logic)
|
# Parse test's <level>
|
||||||
infoMsg += "on %s parameter '%s'" % (place, parameter)
|
if test.level > conf.level:
|
||||||
|
debugMsg = "skipping test '%s' because the level " % title
|
||||||
|
debugMsg += "is higher than the provided"
|
||||||
|
logger.debug(debugMsg)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if "details" in test and "dbms" in test.details:
|
||||||
|
dbms = test.details.dbms
|
||||||
|
else:
|
||||||
|
dbms = None
|
||||||
|
|
||||||
|
# Skip current test if it is the same SQL injection type
|
||||||
|
# already identified by another test
|
||||||
|
if injection.data and stype in injection.data:
|
||||||
|
debugMsg = "skipping test '%s' because " % title
|
||||||
|
debugMsg += "we have already the payload for %s" % PAYLOAD.SQLINJECTION[stype]
|
||||||
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Skip DBMS-specific tests if they do not match the DBMS
|
||||||
|
# identified
|
||||||
|
if injection.dbms is not None and injection.dbms != dbms:
|
||||||
|
debugMsg = "skipping test '%s' because " % title
|
||||||
|
debugMsg += "the back-end DBMS is %s" % injection.dbms
|
||||||
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
|
continue
|
||||||
|
|
||||||
|
infoMsg = "testing '%s'" % title
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
payload = agent.payload(place, parameter, value, negative.format % eval(negative.params))
|
# Parse test's <request>
|
||||||
_ = Request.queryPage(payload, place)
|
payload = agent.cleanupPayload(test.request.payload)
|
||||||
|
|
||||||
payload = agent.payload(place, parameter, value, positive.format % eval(positive.params))
|
if dbms:
|
||||||
trueResult = Request.queryPage(payload, place)
|
payload = unescape(payload, dbms)
|
||||||
|
|
||||||
if trueResult:
|
if "comment" in test.request:
|
||||||
infoMsg = "confirming %s (%s) injection " % (case.desc, logic)
|
comment = test.request.comment
|
||||||
infoMsg += "on %s parameter '%s'" % (place, parameter)
|
else:
|
||||||
logger.info(infoMsg)
|
comment = ""
|
||||||
|
testPayload = "%s%s" % (payload, comment)
|
||||||
|
|
||||||
payload = agent.payload(place, parameter, value, negative.format % eval(negative.params))
|
if conf.prefix is not None and conf.suffix is not None:
|
||||||
|
boundary = advancedDict()
|
||||||
|
|
||||||
randInt = randomInt()
|
boundary.level = 1
|
||||||
randStr = randomStr()
|
boundary.clause = [ 0 ]
|
||||||
|
boundary.where = [ 1, 2, 3 ]
|
||||||
|
# TODO: inspect the conf.prefix and conf.suffix to set
|
||||||
|
# proper ptype
|
||||||
|
boundary.ptype = 1
|
||||||
|
boundary.prefix = conf.prefix
|
||||||
|
boundary.suffix = conf.suffix
|
||||||
|
|
||||||
falseResult = Request.queryPage(payload, place)
|
conf.boundaries.insert(0, boundary)
|
||||||
|
|
||||||
if not falseResult:
|
for boundary in conf.boundaries:
|
||||||
infoMsg = "%s parameter '%s' is %s (%s) injectable " % (place, parameter, case.desc, logic)
|
# Parse boundary's <level>
|
||||||
infoMsg += "with %d parenthesis" % parenthesis
|
if boundary.level > conf.level:
|
||||||
logger.info(infoMsg)
|
# NOTE: shall we report every single skipped boundary too?
|
||||||
|
continue
|
||||||
|
|
||||||
if conf.beep:
|
# Parse test's <clause> and boundary's <clause>
|
||||||
beep()
|
# Skip boundary if it does not match against test's <clause>
|
||||||
|
clauseMatch = False
|
||||||
|
|
||||||
|
for clauseTest in test.clause:
|
||||||
|
if clauseTest in boundary.clause:
|
||||||
|
clauseMatch = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if test.clause != [ 0 ] and boundary.clause != [ 0 ] and not clauseMatch:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Parse test's <where> and boundary's <where>
|
||||||
|
# Skip boundary if it does not match against test's <where>
|
||||||
|
whereMatch = False
|
||||||
|
|
||||||
|
for where in test.where:
|
||||||
|
if where in boundary.where:
|
||||||
|
whereMatch = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not whereMatch:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Parse boundary's <prefix>, <suffix> and <ptype>
|
||||||
|
prefix = boundary.prefix if boundary.prefix else ""
|
||||||
|
suffix = boundary.suffix if boundary.suffix else ""
|
||||||
|
ptype = boundary.ptype
|
||||||
|
injectable = False
|
||||||
|
|
||||||
|
# If the previous injections succeeded, we know which prefix,
|
||||||
|
# postfix and parameter type to use for further tests, no
|
||||||
|
# need to cycle through all of the boundaries anymore
|
||||||
|
condBound = (injection.prefix is not None and injection.suffix is not None)
|
||||||
|
condBound &= (injection.prefix != prefix or injection.suffix != suffix)
|
||||||
|
condType = injection.ptype is not None and injection.ptype != ptype
|
||||||
|
|
||||||
|
if condBound or condType:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# For each test's <where>
|
||||||
|
for where in test.where:
|
||||||
|
# The <where> tag defines where to add our injection
|
||||||
|
# string to the parameter under assessment.
|
||||||
|
if where == 1:
|
||||||
|
origValue = value
|
||||||
|
elif where == 2:
|
||||||
|
origValue = "-%s" % value
|
||||||
|
elif where == 3:
|
||||||
|
origValue = ""
|
||||||
|
|
||||||
|
# Forge payload by prepending with boundary's prefix and
|
||||||
|
# appending with boundary's suffix the test's
|
||||||
|
# ' <payload><command> ' string
|
||||||
|
boundPayload = "%s%s %s %s" % (origValue, prefix, testPayload, suffix)
|
||||||
|
boundPayload = boundPayload.strip()
|
||||||
|
boundPayload = agent.cleanupPayload(boundPayload)
|
||||||
|
reqPayload = agent.payload(place, parameter, value, boundPayload)
|
||||||
|
|
||||||
|
# Parse test's <response>
|
||||||
|
# Check wheather or not the payload was successful
|
||||||
|
for method, check in test.response.items():
|
||||||
|
check = agent.cleanupPayload(check)
|
||||||
|
|
||||||
|
# In case of boolean-based blind SQL injection
|
||||||
|
if method == "comparison":
|
||||||
|
sndPayload = agent.cleanupPayload(test.response.comparison)
|
||||||
|
|
||||||
|
if dbms:
|
||||||
|
sndPayload = unescape(sndPayload, dbms)
|
||||||
|
|
||||||
|
if "comment" in test.response:
|
||||||
|
sndComment = test.response.comment
|
||||||
|
else:
|
||||||
|
sndComment = ""
|
||||||
|
|
||||||
|
sndPayload = "%s%s" % (sndPayload, sndComment)
|
||||||
|
boundPayload = "%s%s %s %s" % (origValue, prefix, sndPayload, suffix)
|
||||||
|
boundPayload = boundPayload.strip()
|
||||||
|
boundPayload = agent.cleanupPayload(boundPayload)
|
||||||
|
cmpPayload = agent.payload(place, parameter, value, boundPayload)
|
||||||
|
|
||||||
|
# Useful to set conf.matchRatio at first
|
||||||
|
conf.matchRatio = None
|
||||||
|
_ = Request.queryPage(cmpPayload, place)
|
||||||
|
|
||||||
|
trueResult = Request.queryPage(reqPayload, place)
|
||||||
|
|
||||||
|
if trueResult:
|
||||||
|
falseResult = Request.queryPage(cmpPayload, place)
|
||||||
|
|
||||||
|
if not falseResult:
|
||||||
|
infoMsg = "%s parameter '%s' is '%s' injectable " % (place, parameter, title)
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
kb.paramMatchRatio[(place, parameter)] = conf.matchRatio
|
||||||
|
injectable = True
|
||||||
|
|
||||||
|
kb.paramMatchRatio[(place, parameter)] = conf.matchRatio
|
||||||
|
|
||||||
|
# In case of error-based or UNION query SQL injections
|
||||||
|
elif method == "grep":
|
||||||
|
reqBody, _ = Request.queryPage(reqPayload, place, content=True)
|
||||||
|
match = re.search(check, reqBody, re.DOTALL | re.IGNORECASE)
|
||||||
|
|
||||||
|
if not match:
|
||||||
|
continue
|
||||||
|
|
||||||
|
output = match.group('result')
|
||||||
|
|
||||||
|
if output:
|
||||||
|
output = output.replace(ERROR_SPACE, " ").replace(ERROR_EMPTY_CHAR, "")
|
||||||
|
|
||||||
|
if output == "1":
|
||||||
|
infoMsg = "%s parameter '%s' is '%s' injectable " % (place, parameter, title)
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
injectable = True
|
||||||
|
|
||||||
|
# In case of time-based blind or stacked queries SQL injections
|
||||||
|
elif method == "time":
|
||||||
|
start = time.time()
|
||||||
|
_ = Request.queryPage(reqPayload, place)
|
||||||
|
duration = calculateDeltaSeconds(start)
|
||||||
|
|
||||||
|
if duration >= conf.timeSec:
|
||||||
|
infoMsg = "%s parameter '%s' is '%s' injectable " % (place, parameter, title)
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
injectable = True
|
||||||
|
|
||||||
|
if injectable is True:
|
||||||
|
injection.place = place
|
||||||
|
injection.parameter = parameter
|
||||||
|
injection.ptype = ptype
|
||||||
|
injection.prefix = prefix
|
||||||
|
injection.suffix = suffix
|
||||||
|
|
||||||
|
injection.data[stype] = (title, where, comment, boundPayload)
|
||||||
|
|
||||||
|
if "details" in test:
|
||||||
|
for detailKey, detailValue in test.details.items():
|
||||||
|
if detailKey == "dbms" and injection.dbms is None:
|
||||||
|
injection.dbms = detailValue
|
||||||
|
elif detailKey == "dbms_version" and injection.dbms_version is None:
|
||||||
|
injection.dbms_version = detailValue
|
||||||
|
elif detailKey == "os" and injection.os is None:
|
||||||
|
injection.os = detailValue
|
||||||
|
|
||||||
retVal = case.name
|
|
||||||
break
|
break
|
||||||
|
|
||||||
kb.paramMatchRatio[(place, parameter)] = conf.matchRatio
|
return injection
|
||||||
|
|
||||||
return retVal
|
|
||||||
|
|
||||||
def heuristicCheckSqlInjection(place, parameter, value):
|
def heuristicCheckSqlInjection(place, parameter, value):
|
||||||
if kb.nullConnection:
|
if kb.nullConnection:
|
||||||
|
|
|
@ -18,6 +18,8 @@ from lib.controller.checks import checkString
|
||||||
from lib.controller.checks import checkRegexp
|
from lib.controller.checks import checkRegexp
|
||||||
from lib.controller.checks import checkConnection
|
from lib.controller.checks import checkConnection
|
||||||
from lib.controller.checks import checkNullConnection
|
from lib.controller.checks import checkNullConnection
|
||||||
|
from lib.core.agent import agent
|
||||||
|
from lib.core.common import dataToStdout
|
||||||
from lib.core.common import getUnicode
|
from lib.core.common import getUnicode
|
||||||
from lib.core.common import paramToDict
|
from lib.core.common import paramToDict
|
||||||
from lib.core.common import parseTargetUrl
|
from lib.core.common import parseTargetUrl
|
||||||
|
@ -25,57 +27,121 @@ from lib.core.common import readInput
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
|
from lib.core.dump import dumper
|
||||||
from lib.core.enums import HTTPMETHOD
|
from lib.core.enums import HTTPMETHOD
|
||||||
|
from lib.core.enums import PAYLOAD
|
||||||
from lib.core.enums import PLACE
|
from lib.core.enums import PLACE
|
||||||
from lib.core.exception import exceptionsTuple
|
from lib.core.exception import exceptionsTuple
|
||||||
from lib.core.exception import sqlmapNotVulnerableException
|
from lib.core.exception import sqlmapNotVulnerableException
|
||||||
from lib.core.exception import sqlmapSilentQuitException
|
from lib.core.exception import sqlmapSilentQuitException
|
||||||
|
from lib.core.exception import sqlmapValueException
|
||||||
from lib.core.exception import sqlmapUserQuitException
|
from lib.core.exception import sqlmapUserQuitException
|
||||||
|
from lib.core.session import setBooleanBased
|
||||||
|
from lib.core.session import setError
|
||||||
from lib.core.session import setInjection
|
from lib.core.session import setInjection
|
||||||
from lib.core.session import setMatchRatio
|
from lib.core.session import setMatchRatio
|
||||||
|
from lib.core.session import setStacked
|
||||||
|
from lib.core.session import setTimeBased
|
||||||
from lib.core.target import initTargetEnv
|
from lib.core.target import initTargetEnv
|
||||||
from lib.core.target import setupTargetEnv
|
from lib.core.target import setupTargetEnv
|
||||||
from lib.utils.parenthesis import checkForParenthesis
|
|
||||||
|
|
||||||
def __selectInjection(injData):
|
def __saveToSessionFile():
|
||||||
|
for inj in kb.injections:
|
||||||
|
place = inj.place
|
||||||
|
parameter = inj.parameter
|
||||||
|
|
||||||
|
for stype, sdata in inj.data.items():
|
||||||
|
payload = sdata[3]
|
||||||
|
|
||||||
|
if stype == 1:
|
||||||
|
kb.booleanTest = payload
|
||||||
|
setBooleanBased(place, parameter, payload)
|
||||||
|
elif stype == 2:
|
||||||
|
kb.errorTest = payload
|
||||||
|
setError(place, parameter, payload)
|
||||||
|
elif stype == 4:
|
||||||
|
kb.stackedTest = payload
|
||||||
|
setStacked(place, parameter, payload)
|
||||||
|
elif stype == 5:
|
||||||
|
kb.timeTest = payload
|
||||||
|
setTimeBased(place, parameter, payload)
|
||||||
|
|
||||||
|
setInjection(inj)
|
||||||
|
|
||||||
|
def __selectInjection():
|
||||||
"""
|
"""
|
||||||
Selection function for injection place, parameters and type.
|
Selection function for injection place, parameters and type.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
message = "there were multiple injection points, please select the "
|
# TODO: when resume from session file, feed kb.injections and call
|
||||||
message += "one to use to go ahead:\n"
|
# __selectInjection()
|
||||||
|
points = []
|
||||||
|
|
||||||
for i in xrange(0, len(injData)):
|
for i in xrange(0, len(kb.injections)):
|
||||||
injPlace = injData[i][0]
|
place = kb.injections[i].place
|
||||||
injParameter = injData[i][1]
|
parameter = kb.injections[i].parameter
|
||||||
injType = injData[i][2]
|
ptype = kb.injections[i].ptype
|
||||||
|
|
||||||
message += "[%d] place: %s, parameter: " % (i, injPlace)
|
point = (place, parameter, ptype)
|
||||||
message += "%s, type: %s" % (injParameter, injType)
|
|
||||||
|
|
||||||
if i == 0:
|
if point not in points:
|
||||||
message += " (default)"
|
points.append(point)
|
||||||
|
|
||||||
message += "\n"
|
if len(points) == 1:
|
||||||
|
kb.injection = kb.injections[0]
|
||||||
|
elif len(points) > 1:
|
||||||
|
message = "there were multiple injection points, please select "
|
||||||
|
message += "the one to use for following injections:\n"
|
||||||
|
|
||||||
message += "[q] Quit"
|
points = []
|
||||||
select = readInput(message, default="0")
|
|
||||||
|
|
||||||
if not select:
|
for i in xrange(0, len(kb.injections)):
|
||||||
index = 0
|
place = kb.injections[i].place
|
||||||
|
parameter = kb.injections[i].parameter
|
||||||
|
ptype = kb.injections[i].ptype
|
||||||
|
point = (place, parameter, ptype)
|
||||||
|
|
||||||
elif select.isdigit() and int(select) < len(injData) and int(select) >= 0:
|
if point not in points:
|
||||||
index = int(select)
|
points.append(point)
|
||||||
|
|
||||||
elif select[0] in ( "Q", "q" ):
|
message += "[%d] place: %s, parameter: " % (i, place)
|
||||||
return "Quit"
|
message += "%s, type: %s" % (parameter, PAYLOAD.PARAMETER[ptype])
|
||||||
|
|
||||||
else:
|
if i == 0:
|
||||||
warnMsg = "invalid choice, retry"
|
message += " (default)"
|
||||||
logger.warn(warnMsg)
|
|
||||||
__selectInjection(injData)
|
|
||||||
|
|
||||||
return injData[index]
|
message += "\n"
|
||||||
|
|
||||||
|
message += "[q] Quit"
|
||||||
|
select = readInput(message, default="0")
|
||||||
|
|
||||||
|
if select.isdigit() and int(select) < len(kb.injections) and int(select) >= 0:
|
||||||
|
index = int(select)
|
||||||
|
elif select[0] in ( "Q", "q" ):
|
||||||
|
raise sqlmapUserQuitException
|
||||||
|
else:
|
||||||
|
errMsg = "invalid choice"
|
||||||
|
raise sqlmapValueException, errMsg
|
||||||
|
|
||||||
|
kb.injection = kb.injections[index]
|
||||||
|
|
||||||
|
def __formatInjection(inj):
|
||||||
|
header = "Place: %s\n" % inj.place
|
||||||
|
header += "Parameter: %s\n" % inj.parameter
|
||||||
|
data = ""
|
||||||
|
|
||||||
|
for stype, sdata in inj.data.items():
|
||||||
|
data += "Type: %s\n" % PAYLOAD.SQLINJECTION[stype]
|
||||||
|
data += "Payload: %s\n\n" % sdata[3]
|
||||||
|
|
||||||
|
return header, data
|
||||||
|
|
||||||
|
def __showInjections():
|
||||||
|
dataToStdout("sqlmap identified the following injection points:\n")
|
||||||
|
|
||||||
|
for inj in kb.injections:
|
||||||
|
header, data = __formatInjection(inj)
|
||||||
|
dumper.technic(header, data)
|
||||||
|
|
||||||
def start():
|
def start():
|
||||||
"""
|
"""
|
||||||
|
@ -230,7 +296,7 @@ def start():
|
||||||
# TODO: consider the following line in __setRequestParams()
|
# TODO: consider the following line in __setRequestParams()
|
||||||
__testableParameters = True
|
__testableParameters = True
|
||||||
|
|
||||||
if not kb.injPlace or not kb.injParameter or not kb.injType:
|
if not kb.injection.place or not kb.injection.parameter:
|
||||||
if not conf.string and not conf.regexp and not conf.eRegexp:
|
if not conf.string and not conf.regexp and not conf.eRegexp:
|
||||||
# NOTE: this is not needed anymore, leaving only to display
|
# NOTE: this is not needed anymore, leaving only to display
|
||||||
# a warning message to the user in case the page is not stable
|
# a warning message to the user in case the page is not stable
|
||||||
|
@ -251,6 +317,10 @@ def start():
|
||||||
paramDict = conf.paramDict[place]
|
paramDict = conf.paramDict[place]
|
||||||
for parameter, value in paramDict.items():
|
for parameter, value in paramDict.items():
|
||||||
testSqlInj = True
|
testSqlInj = True
|
||||||
|
|
||||||
|
# TODO: with the new detection engine, review this
|
||||||
|
# part. Perhaps dynamicity test will not be of any
|
||||||
|
# use
|
||||||
paramKey = (conf.hostname, conf.path, place, parameter)
|
paramKey = (conf.hostname, conf.path, place, parameter)
|
||||||
|
|
||||||
if paramKey in kb.testedParams:
|
if paramKey in kb.testedParams:
|
||||||
|
@ -276,48 +346,33 @@ def start():
|
||||||
kb.testedParams.add(paramKey)
|
kb.testedParams.add(paramKey)
|
||||||
|
|
||||||
if testSqlInj:
|
if testSqlInj:
|
||||||
|
# TODO: with the new detection engine, review this
|
||||||
|
# part. This will be moved to payloads.xml as well
|
||||||
heuristicCheckSqlInjection(place, parameter, value)
|
heuristicCheckSqlInjection(place, parameter, value)
|
||||||
|
|
||||||
for parenthesis in range(0, 4):
|
logMsg = "testing sql injection on %s " % place
|
||||||
logMsg = "testing sql injection on %s " % place
|
logMsg += "parameter '%s'" % parameter
|
||||||
logMsg += "parameter '%s' with " % parameter
|
logger.info(logMsg)
|
||||||
logMsg += "%d parenthesis" % parenthesis
|
|
||||||
logger.info(logMsg)
|
|
||||||
|
|
||||||
injType = checkSqlInjection(place, parameter, value, parenthesis)
|
injection = checkSqlInjection(place, parameter, value)
|
||||||
|
|
||||||
if injType:
|
if injection:
|
||||||
injData.append((place, parameter, injType))
|
kb.injections.append(injection)
|
||||||
break
|
else:
|
||||||
|
|
||||||
else:
|
|
||||||
infoMsg = "%s parameter '%s' is not " % (place, parameter)
|
|
||||||
infoMsg += "injectable with %d parenthesis" % parenthesis
|
|
||||||
logger.info(infoMsg)
|
|
||||||
|
|
||||||
if not injData:
|
|
||||||
warnMsg = "%s parameter '%s' is not " % (place, parameter)
|
warnMsg = "%s parameter '%s' is not " % (place, parameter)
|
||||||
warnMsg += "injectable"
|
warnMsg += "injectable"
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
if not kb.injPlace or not kb.injParameter or not kb.injType:
|
if len(kb.injections) == 0 and not kb.injection.place and not kb.injection.parameter:
|
||||||
if len(injData) == 1:
|
errMsg = "all parameters are not injectable, try "
|
||||||
injDataSelected = injData[0]
|
errMsg += "a higher --level"
|
||||||
|
raise sqlmapNotVulnerableException, errMsg
|
||||||
|
else:
|
||||||
|
__saveToSessionFile()
|
||||||
|
__showInjections()
|
||||||
|
__selectInjection()
|
||||||
|
|
||||||
elif len(injData) > 1:
|
if kb.injection.place and kb.injection.parameter:
|
||||||
injDataSelected = __selectInjection(injData)
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise sqlmapNotVulnerableException, "all parameters are not injectable"
|
|
||||||
|
|
||||||
if injDataSelected == "Quit":
|
|
||||||
return
|
|
||||||
|
|
||||||
else:
|
|
||||||
kb.injPlace, kb.injParameter, kb.injType = injDataSelected
|
|
||||||
setInjection()
|
|
||||||
|
|
||||||
if kb.injPlace and kb.injParameter and kb.injType:
|
|
||||||
if conf.multipleTargets:
|
if conf.multipleTargets:
|
||||||
message = "do you want to exploit this SQL injection? [Y/n] "
|
message = "do you want to exploit this SQL injection? [Y/n] "
|
||||||
exploit = readInput(message, default="Y")
|
exploit = readInput(message, default="Y")
|
||||||
|
@ -328,10 +383,9 @@ def start():
|
||||||
|
|
||||||
if condition:
|
if condition:
|
||||||
if kb.paramMatchRatio:
|
if kb.paramMatchRatio:
|
||||||
conf.matchRatio = kb.paramMatchRatio[(kb.injPlace, kb.injParameter)]
|
conf.matchRatio = kb.paramMatchRatio[(kb.injection.place, kb.injection.parameter)]
|
||||||
setMatchRatio()
|
setMatchRatio()
|
||||||
|
|
||||||
checkForParenthesis()
|
|
||||||
action()
|
action()
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
|
|
@ -12,7 +12,6 @@ import re
|
||||||
from xml.etree import ElementTree as ET
|
from xml.etree import ElementTree as ET
|
||||||
|
|
||||||
from lib.core.common import getCompiledRegex
|
from lib.core.common import getCompiledRegex
|
||||||
from lib.core.common import getInjectionCase
|
|
||||||
from lib.core.common import randomInt
|
from lib.core.common import randomInt
|
||||||
from lib.core.common import randomStr
|
from lib.core.common import randomStr
|
||||||
from lib.core.convert import urlencode
|
from lib.core.convert import urlencode
|
||||||
|
@ -23,6 +22,8 @@ from lib.core.datatype import advancedDict
|
||||||
from lib.core.enums import DBMS
|
from lib.core.enums import DBMS
|
||||||
from lib.core.enums import PLACE
|
from lib.core.enums import PLACE
|
||||||
from lib.core.exception import sqlmapNoneDataException
|
from lib.core.exception import sqlmapNoneDataException
|
||||||
|
from lib.core.settings import ERROR_START_CHAR
|
||||||
|
from lib.core.settings import ERROR_END_CHAR
|
||||||
from lib.core.settings import PAYLOAD_DELIMITER
|
from lib.core.settings import PAYLOAD_DELIMITER
|
||||||
|
|
||||||
class Agent:
|
class Agent:
|
||||||
|
@ -70,28 +71,28 @@ class Agent:
|
||||||
falseValue = " AND %d=%d" % (randInt, randInt + 1)
|
falseValue = " AND %d=%d" % (randInt, randInt + 1)
|
||||||
|
|
||||||
# After identifing the injectable parameter
|
# After identifing the injectable parameter
|
||||||
if kb.injPlace == PLACE.UA:
|
if kb.injection.place == PLACE.UA:
|
||||||
retValue = kb.injParameter.replace(kb.injParameter,
|
retValue = kb.injection.parameter.replace(kb.injection.parameter,
|
||||||
self.addPayloadDelimiters("%s%s" % (negValue, kb.injParameter + falseValue + newValue)))
|
self.addPayloadDelimiters("%s%s" % (negValue, kb.injection.parameter + falseValue + newValue)))
|
||||||
elif kb.injParameter:
|
elif kb.injection.parameter:
|
||||||
paramString = conf.parameters[kb.injPlace]
|
paramString = conf.parameters[kb.injection.place]
|
||||||
paramDict = conf.paramDict[kb.injPlace]
|
paramDict = conf.paramDict[kb.injection.place]
|
||||||
value = paramDict[kb.injParameter]
|
value = paramDict[kb.injection.parameter]
|
||||||
|
|
||||||
if "POSTxml" in conf.paramDict and kb.injPlace == PLACE.POST:
|
if "POSTxml" in conf.paramDict and kb.injection.place == PLACE.POST:
|
||||||
root = ET.XML(paramString)
|
root = ET.XML(paramString)
|
||||||
iterator = root.getiterator(kb.injParameter)
|
iterator = root.getiterator(kb.injection.parameter)
|
||||||
|
|
||||||
for child in iterator:
|
for child in iterator:
|
||||||
child.text = self.addPayloadDelimiters(negValue + value + falseValue + newValue)
|
child.text = self.addPayloadDelimiters(negValue + value + falseValue + newValue)
|
||||||
|
|
||||||
retValue = ET.tostring(root)
|
retValue = ET.tostring(root)
|
||||||
elif kb.injPlace == PLACE.URI:
|
elif kb.injection.place == PLACE.URI:
|
||||||
retValue = paramString.replace("*",
|
retValue = paramString.replace("*",
|
||||||
self.addPayloadDelimiters("%s%s" % (negValue, falseValue + newValue)))
|
self.addPayloadDelimiters("%s%s" % (negValue, falseValue + newValue)))
|
||||||
else:
|
else:
|
||||||
retValue = paramString.replace("%s=%s" % (kb.injParameter, value),
|
retValue = paramString.replace("%s=%s" % (kb.injection.parameter, value),
|
||||||
"%s=%s" % (kb.injParameter, self.addPayloadDelimiters(negValue + value + falseValue + newValue)))
|
"%s=%s" % (kb.injection.parameter, self.addPayloadDelimiters(negValue + value + falseValue + newValue)))
|
||||||
|
|
||||||
# Before identifing the injectable parameter
|
# Before identifing the injectable parameter
|
||||||
elif parameter == PLACE.UA:
|
elif parameter == PLACE.UA:
|
||||||
|
@ -125,6 +126,20 @@ class Agent:
|
||||||
|
|
||||||
return payload
|
return payload
|
||||||
|
|
||||||
|
def cleanupPayload(self, payload):
|
||||||
|
randInt = randomInt()
|
||||||
|
randInt1 = randomInt()
|
||||||
|
randStr = randomStr()
|
||||||
|
|
||||||
|
payload = payload.replace("[RANDNUM]", str(randInt))
|
||||||
|
payload = payload.replace("[RANDNUM1]", str(randInt1))
|
||||||
|
payload = payload.replace("[RANDSTR]", randStr)
|
||||||
|
payload = payload.replace("[ERROR_START_CHAR]", ERROR_START_CHAR)
|
||||||
|
payload = payload.replace("[ERROR_END_CHAR]", ERROR_END_CHAR)
|
||||||
|
payload = payload.replace("[SLEEPTIME]", str(conf.timeSec))
|
||||||
|
|
||||||
|
return payload
|
||||||
|
|
||||||
def prefixQuery(self, string):
|
def prefixQuery(self, string):
|
||||||
"""
|
"""
|
||||||
This method defines how the input string has to be escaped
|
This method defines how the input string has to be escaped
|
||||||
|
@ -135,24 +150,9 @@ class Agent:
|
||||||
if conf.direct:
|
if conf.direct:
|
||||||
return self.payloadDirect(string)
|
return self.payloadDirect(string)
|
||||||
|
|
||||||
logic = conf.logic
|
query = "%s " % kb.injection.prefix
|
||||||
query = str()
|
|
||||||
case = getInjectionCase(kb.injType)
|
|
||||||
|
|
||||||
if kb.parenthesis is not None:
|
|
||||||
parenthesis = kb.parenthesis
|
|
||||||
else:
|
|
||||||
raise sqlmapNoneDataException, "unable to get the number of parenthesis"
|
|
||||||
|
|
||||||
if case is None:
|
|
||||||
raise sqlmapNoneDataException, "unsupported injection type"
|
|
||||||
|
|
||||||
if conf.prefix:
|
|
||||||
query = "%s " % conf.prefix.strip()
|
|
||||||
else:
|
|
||||||
query = case.usage.prefix.format % eval(case.usage.prefix.params)
|
|
||||||
|
|
||||||
query += string
|
query += string
|
||||||
|
query = self.cleanupPayload(query)
|
||||||
|
|
||||||
return query
|
return query
|
||||||
|
|
||||||
|
@ -165,27 +165,11 @@ class Agent:
|
||||||
if conf.direct:
|
if conf.direct:
|
||||||
return self.payloadDirect(string)
|
return self.payloadDirect(string)
|
||||||
|
|
||||||
logic = conf.logic
|
if comment is not None:
|
||||||
case = getInjectionCase(kb.injType)
|
|
||||||
|
|
||||||
if case is None:
|
|
||||||
raise sqlmapNoneDataException, "unsupported injection type"
|
|
||||||
|
|
||||||
randInt = randomInt()
|
|
||||||
randStr = randomStr()
|
|
||||||
|
|
||||||
if kb.parenthesis is not None:
|
|
||||||
parenthesis = kb.parenthesis
|
|
||||||
else:
|
|
||||||
raise sqlmapNoneDataException, "unable to get the number of parenthesis"
|
|
||||||
|
|
||||||
if comment:
|
|
||||||
string += comment
|
string += comment
|
||||||
|
|
||||||
if conf.suffix:
|
string += " %s" % kb.injection.suffix
|
||||||
string += " %s" % conf.suffix
|
string = self.cleanupPayload(string)
|
||||||
else:
|
|
||||||
string += case.usage.suffix.format % eval(case.usage.suffix.params)
|
|
||||||
|
|
||||||
return string
|
return string
|
||||||
|
|
||||||
|
|
|
@ -667,6 +667,7 @@ def setPaths():
|
||||||
paths.WORDLIST = os.path.join(paths.SQLMAP_TXT_PATH, "wordlist.txt")
|
paths.WORDLIST = os.path.join(paths.SQLMAP_TXT_PATH, "wordlist.txt")
|
||||||
paths.PHPIDS_RULES_XML = os.path.join(paths.SQLMAP_XML_PATH, "phpids_rules.xml")
|
paths.PHPIDS_RULES_XML = os.path.join(paths.SQLMAP_XML_PATH, "phpids_rules.xml")
|
||||||
paths.ERRORS_XML = os.path.join(paths.SQLMAP_XML_PATH, "errors.xml")
|
paths.ERRORS_XML = os.path.join(paths.SQLMAP_XML_PATH, "errors.xml")
|
||||||
|
paths.PAYLOADS_XML = os.path.join(paths.SQLMAP_XML_PATH, "payloads.xml")
|
||||||
paths.INJECTIONS_XML = os.path.join(paths.SQLMAP_XML_PATH, "injections.xml")
|
paths.INJECTIONS_XML = os.path.join(paths.SQLMAP_XML_PATH, "injections.xml")
|
||||||
paths.LIVE_TESTS_XML = os.path.join(paths.SQLMAP_XML_PATH, "livetests.xml")
|
paths.LIVE_TESTS_XML = os.path.join(paths.SQLMAP_XML_PATH, "livetests.xml")
|
||||||
paths.QUERIES_XML = os.path.join(paths.SQLMAP_XML_PATH, "queries.xml")
|
paths.QUERIES_XML = os.path.join(paths.SQLMAP_XML_PATH, "queries.xml")
|
||||||
|
@ -894,7 +895,7 @@ def parseUnionPage(output, expression, partial=False, condition=None, sort=True)
|
||||||
|
|
||||||
if partial or not condition:
|
if partial or not condition:
|
||||||
logOutput = "".join(["%s%s%s" % (DUMP_START_MARKER, replaceNewlineTabs(value), DUMP_STOP_MARKER) for value in output])
|
logOutput = "".join(["%s%s%s" % (DUMP_START_MARKER, replaceNewlineTabs(value), DUMP_STOP_MARKER) for value in output])
|
||||||
dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], expression, logOutput))
|
dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.url, kb.injection.place, conf.parameters[kb.injection.place], expression, logOutput))
|
||||||
|
|
||||||
if sort:
|
if sort:
|
||||||
output = set(output)
|
output = set(output)
|
||||||
|
@ -1296,17 +1297,6 @@ def calculateDeltaSeconds(start, epsilon=0.05):
|
||||||
"""
|
"""
|
||||||
return int(time.time() - start + epsilon)
|
return int(time.time() - start + epsilon)
|
||||||
|
|
||||||
def getInjectionCase(name):
|
|
||||||
retVal = None
|
|
||||||
|
|
||||||
for case in kb.injections.root.case:
|
|
||||||
if case.name == name:
|
|
||||||
retVal = case
|
|
||||||
|
|
||||||
break
|
|
||||||
|
|
||||||
return retVal
|
|
||||||
|
|
||||||
def initCommonOutputs():
|
def initCommonOutputs():
|
||||||
kb.commonOutputs = {}
|
kb.commonOutputs = {}
|
||||||
key = None
|
key = None
|
||||||
|
|
|
@ -56,3 +56,21 @@ class advancedDict(dict):
|
||||||
else:
|
else:
|
||||||
self.__setitem__(item, value)
|
self.__setitem__(item, value)
|
||||||
|
|
||||||
|
def injectionDict():
|
||||||
|
injection = advancedDict()
|
||||||
|
|
||||||
|
injection.place = None
|
||||||
|
injection.parameter = None
|
||||||
|
injection.ptype = None
|
||||||
|
injection.prefix = None
|
||||||
|
injection.suffix = None
|
||||||
|
|
||||||
|
# data is a dict with stype as key and a tuple as value with
|
||||||
|
# title, where, comment and reqPayload
|
||||||
|
injection.data = {}
|
||||||
|
|
||||||
|
injection.dbms = None
|
||||||
|
injection.dbms_version = None
|
||||||
|
injection.os = None
|
||||||
|
|
||||||
|
return injection
|
||||||
|
|
|
@ -17,14 +17,14 @@ class PRIORITY:
|
||||||
HIGHEST = 100
|
HIGHEST = 100
|
||||||
|
|
||||||
class DBMS:
|
class DBMS:
|
||||||
MYSQL = "MySQL"
|
|
||||||
ORACLE = "Oracle"
|
|
||||||
POSTGRESQL = "PostgreSQL"
|
|
||||||
MSSQL = "Microsoft SQL Server"
|
|
||||||
SQLITE = "SQLite"
|
|
||||||
ACCESS = "Microsoft Access"
|
ACCESS = "Microsoft Access"
|
||||||
FIREBIRD = "Firebird"
|
FIREBIRD = "Firebird"
|
||||||
MAXDB = "SAP MaxDB"
|
MAXDB = "SAP MaxDB"
|
||||||
|
MSSQL = "Microsoft SQL Server"
|
||||||
|
MYSQL = "MySQL"
|
||||||
|
ORACLE = "Oracle"
|
||||||
|
POSTGRESQL = "PostgreSQL"
|
||||||
|
SQLITE = "SQLite"
|
||||||
SYBASE = "Sybase"
|
SYBASE = "Sybase"
|
||||||
|
|
||||||
class PLACE:
|
class PLACE:
|
||||||
|
@ -53,3 +53,39 @@ class HASH:
|
||||||
ORACLE_OLD = r'(?i)\A[01-9a-f]{16}\Z'
|
ORACLE_OLD = r'(?i)\A[01-9a-f]{16}\Z'
|
||||||
MD5_GENERIC = r'(?i)\A[0-9a-f]{32}\Z'
|
MD5_GENERIC = r'(?i)\A[0-9a-f]{32}\Z'
|
||||||
SHA1_GENERIC = r'(?i)\A[0-9a-f]{40}\Z'
|
SHA1_GENERIC = r'(?i)\A[0-9a-f]{40}\Z'
|
||||||
|
|
||||||
|
class PAYLOAD:
|
||||||
|
SQLINJECTION = {
|
||||||
|
1: "boolean-based blind",
|
||||||
|
2: "error-based",
|
||||||
|
3: "UNION query",
|
||||||
|
4: "stacked queries",
|
||||||
|
5: "AND/OR time-based blind"
|
||||||
|
}
|
||||||
|
|
||||||
|
PARAMETER = {
|
||||||
|
1: "Unescaped numeric",
|
||||||
|
2: "Single quoted string",
|
||||||
|
3: "LIKE single quoted string",
|
||||||
|
4: "Double quoted string",
|
||||||
|
5: "LIKE double quoted string"
|
||||||
|
}
|
||||||
|
|
||||||
|
RISK = {
|
||||||
|
0: "No risk",
|
||||||
|
1: "Low risk",
|
||||||
|
2: "Medium risk",
|
||||||
|
3: "High risk"
|
||||||
|
}
|
||||||
|
|
||||||
|
CLAUSE = {
|
||||||
|
0: "Always",
|
||||||
|
1: "WHERE",
|
||||||
|
2: "GROUP BY",
|
||||||
|
3: "ORDER BY",
|
||||||
|
4: "LIMIT",
|
||||||
|
5: "OFFSET",
|
||||||
|
6: "TOP",
|
||||||
|
7: "Table name",
|
||||||
|
8: "Column name"
|
||||||
|
}
|
||||||
|
|
|
@ -64,6 +64,7 @@ from lib.core.settings import SUPPORTED_OS
|
||||||
from lib.core.settings import VERSION_STRING
|
from lib.core.settings import VERSION_STRING
|
||||||
from lib.core.update import update
|
from lib.core.update import update
|
||||||
from lib.parse.configfile import configFileParser
|
from lib.parse.configfile import configFileParser
|
||||||
|
from lib.parse.payloads import loadPayloads
|
||||||
from lib.request.connect import Connect as Request
|
from lib.request.connect import Connect as Request
|
||||||
from lib.request.proxy import ProxyHTTPSHandler
|
from lib.request.proxy import ProxyHTTPSHandler
|
||||||
from lib.request.certhandler import HTTPSCertAuthHandler
|
from lib.request.certhandler import HTTPSCertAuthHandler
|
||||||
|
@ -1069,6 +1070,7 @@ def __setConfAttributes():
|
||||||
debugMsg = "initializing the configuration"
|
debugMsg = "initializing the configuration"
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
|
conf.boundaries = []
|
||||||
conf.cj = None
|
conf.cj = None
|
||||||
conf.dataEncoding = "utf-8"
|
conf.dataEncoding = "utf-8"
|
||||||
conf.dbmsConnector = None
|
conf.dbmsConnector = None
|
||||||
|
@ -1094,6 +1096,7 @@ def __setConfAttributes():
|
||||||
conf.seqMatcher = difflib.SequenceMatcher(None)
|
conf.seqMatcher = difflib.SequenceMatcher(None)
|
||||||
conf.sessionFP = None
|
conf.sessionFP = None
|
||||||
conf.start = True
|
conf.start = True
|
||||||
|
conf.tests = []
|
||||||
conf.threadContinue = True
|
conf.threadContinue = True
|
||||||
conf.threadException = False
|
conf.threadException = False
|
||||||
conf.trafficFP = None
|
conf.trafficFP = None
|
||||||
|
@ -1121,6 +1124,12 @@ def __setKnowledgeBaseAttributes():
|
||||||
|
|
||||||
kb.data = advancedDict()
|
kb.data = advancedDict()
|
||||||
|
|
||||||
|
# Injection types
|
||||||
|
kb.booleanTest = None
|
||||||
|
kb.errorTest = None
|
||||||
|
kb.stackedTest = None
|
||||||
|
kb.timeTest = None
|
||||||
|
|
||||||
# Basic back-end DBMS fingerprint
|
# Basic back-end DBMS fingerprint
|
||||||
kb.dbms = None
|
kb.dbms = None
|
||||||
kb.dbmsDetected = False
|
kb.dbmsDetected = False
|
||||||
|
@ -1131,16 +1140,15 @@ def __setKnowledgeBaseAttributes():
|
||||||
kb.dep = None
|
kb.dep = None
|
||||||
kb.docRoot = None
|
kb.docRoot = None
|
||||||
kb.dynamicMarkings = []
|
kb.dynamicMarkings = []
|
||||||
kb.errorTest = None
|
|
||||||
kb.formNames = advancedDict()
|
kb.formNames = advancedDict()
|
||||||
kb.headersCount = 0
|
kb.headersCount = 0
|
||||||
kb.headersFp = {}
|
kb.headersFp = {}
|
||||||
kb.hintValue = None
|
kb.hintValue = None
|
||||||
kb.htmlFp = []
|
kb.htmlFp = []
|
||||||
kb.injParameter = None
|
kb.injection = advancedDict()
|
||||||
kb.injPlace = None
|
kb.injection.parameter = None
|
||||||
kb.injType = None
|
kb.injection.place = None
|
||||||
kb.injections = xmlobject.XMLFile(path=paths.INJECTIONS_XML)
|
kb.injections = []
|
||||||
kb.keywords = set(getFileItems(paths.SQL_KEYWORDS))
|
kb.keywords = set(getFileItems(paths.SQL_KEYWORDS))
|
||||||
kb.lastErrorPage = None
|
kb.lastErrorPage = None
|
||||||
kb.lastRequestUID = 0
|
kb.lastRequestUID = 0
|
||||||
|
@ -1160,16 +1168,13 @@ def __setKnowledgeBaseAttributes():
|
||||||
|
|
||||||
kb.pageStable = None
|
kb.pageStable = None
|
||||||
kb.paramMatchRatio = {}
|
kb.paramMatchRatio = {}
|
||||||
kb.parenthesis = None
|
|
||||||
kb.partRun = None
|
kb.partRun = None
|
||||||
kb.proxyAuthHeader = None
|
kb.proxyAuthHeader = None
|
||||||
kb.queryCounter = 0
|
kb.queryCounter = 0
|
||||||
kb.resumedQueries = {}
|
kb.resumedQueries = {}
|
||||||
kb.stackedTest = None
|
|
||||||
kb.tamperFunctions = []
|
kb.tamperFunctions = []
|
||||||
kb.targetUrls = set()
|
kb.targetUrls = set()
|
||||||
kb.testedParams = set()
|
kb.testedParams = set()
|
||||||
kb.timeTest = None
|
|
||||||
kb.unionComment = ""
|
kb.unionComment = ""
|
||||||
kb.unionCount = None
|
kb.unionCount = None
|
||||||
kb.unionPosition = None
|
kb.unionPosition = None
|
||||||
|
@ -1378,5 +1383,6 @@ def init(inputOptions=advancedDict()):
|
||||||
__setWriteFile()
|
__setWriteFile()
|
||||||
__setMetasploit()
|
__setMetasploit()
|
||||||
|
|
||||||
|
loadPayloads()
|
||||||
update()
|
update()
|
||||||
__loadQueries()
|
__loadQueries()
|
||||||
|
|
|
@ -63,6 +63,8 @@ optDict = {
|
||||||
},
|
},
|
||||||
|
|
||||||
"Detection": {
|
"Detection": {
|
||||||
|
"level": "integer",
|
||||||
|
"risk": "integer",
|
||||||
"string": "string",
|
"string": "string",
|
||||||
"regexp": "string",
|
"regexp": "string",
|
||||||
"eString": "string",
|
"eString": "string",
|
||||||
|
|
|
@ -15,6 +15,7 @@ from lib.core.common import readInput
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
|
from lib.core.enums import PAYLOAD
|
||||||
from lib.core.enums import PLACE
|
from lib.core.enums import PLACE
|
||||||
from lib.core.settings import MSSQL_ALIASES
|
from lib.core.settings import MSSQL_ALIASES
|
||||||
from lib.core.settings import MYSQL_ALIASES
|
from lib.core.settings import MYSQL_ALIASES
|
||||||
|
@ -68,47 +69,33 @@ def setMatchRatio():
|
||||||
)
|
)
|
||||||
|
|
||||||
if condition:
|
if condition:
|
||||||
dataToSessionFile("[%s][%s][%s][Match ratio][%s]\n" % (conf.url, kb.injPlace, safeFormatString(conf.parameters[kb.injPlace]), conf.matchRatio))
|
dataToSessionFile("[%s][%s][%s][Match ratio][%s]\n" % (conf.url, kb.injection.place, safeFormatString(conf.parameters[kb.injection.place]), conf.matchRatio))
|
||||||
|
|
||||||
def setInjection():
|
def setInjection(inj):
|
||||||
"""
|
"""
|
||||||
Save information retrieved about injection place and parameter in the
|
Save information retrieved about injection place and parameter in the
|
||||||
session file.
|
session file.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if kb.injPlace == PLACE.UA:
|
if inj.place == PLACE.UA:
|
||||||
kb.injParameter = conf.agent
|
inj.parameter = conf.agent
|
||||||
|
|
||||||
condition = (
|
condition = (
|
||||||
kb.injPlace and kb.injParameter and ( not kb.resumedQueries
|
( not kb.resumedQueries
|
||||||
or ( kb.resumedQueries.has_key(conf.url) and
|
or ( kb.resumedQueries.has_key(conf.url) and
|
||||||
( not kb.resumedQueries[conf.url].has_key("Injection point")
|
( not kb.resumedQueries[conf.url].has_key("Injection point")
|
||||||
or not kb.resumedQueries[conf.url].has_key("Injection parameter")
|
or not kb.resumedQueries[conf.url].has_key("Injection parameter")
|
||||||
or not kb.resumedQueries[conf.url].has_key("Injection type")
|
|
||||||
) ) )
|
) ) )
|
||||||
)
|
)
|
||||||
|
|
||||||
if condition:
|
if condition:
|
||||||
dataToSessionFile("[%s][%s][%s][Injection point][%s]\n" % (conf.url, kb.injPlace, safeFormatString(conf.parameters[kb.injPlace]), kb.injPlace))
|
for stype in inj.data.keys():
|
||||||
dataToSessionFile("[%s][%s][%s][Injection parameter][%s]\n" % (conf.url, kb.injPlace, safeFormatString(conf.parameters[kb.injPlace]), kb.injParameter))
|
dataToSessionFile("[%s][%s][%s][Injection type][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), PAYLOAD.SQLINJECTION[stype]))
|
||||||
dataToSessionFile("[%s][%s][%s][Injection type][%s]\n" % (conf.url, kb.injPlace, safeFormatString(conf.parameters[kb.injPlace]), kb.injType))
|
dataToSessionFile("[%s][%s][%s][Injection point][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), inj.place))
|
||||||
|
dataToSessionFile("[%s][%s][%s][Injection parameter][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), inj.parameter))
|
||||||
def setParenthesis(parenthesisCount):
|
dataToSessionFile("[%s][%s][%s][Injection parameter type][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), PAYLOAD.PARAMETER[inj.ptype]))
|
||||||
"""
|
dataToSessionFile("[%s][%s][%s][Injection prefix][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), inj.prefix))
|
||||||
@param parenthesisCount: number of parenthesis to be set into the
|
dataToSessionFile("[%s][%s][%s][Injection suffix][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), inj.suffix))
|
||||||
knowledge base as fingerprint.
|
|
||||||
@type parenthesisCount: C{int}
|
|
||||||
"""
|
|
||||||
|
|
||||||
condition = (
|
|
||||||
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
|
|
||||||
not kb.resumedQueries[conf.url].has_key("Parenthesis") )
|
|
||||||
)
|
|
||||||
|
|
||||||
if condition:
|
|
||||||
dataToSessionFile("[%s][%s][%s][Parenthesis][%s]\n" % (conf.url, kb.injPlace, safeFormatString(conf.parameters[kb.injPlace]), parenthesisCount))
|
|
||||||
|
|
||||||
kb.parenthesis = parenthesisCount
|
|
||||||
|
|
||||||
def setDbms(dbms):
|
def setDbms(dbms):
|
||||||
"""
|
"""
|
||||||
|
@ -124,7 +111,7 @@ def setDbms(dbms):
|
||||||
)
|
)
|
||||||
|
|
||||||
if condition:
|
if condition:
|
||||||
dataToSessionFile("[%s][%s][%s][DBMS][%s]\n" % (conf.url, kb.injPlace, safeFormatString(conf.parameters[kb.injPlace]), safeFormatString(dbms)))
|
dataToSessionFile("[%s][%s][%s][DBMS][%s]\n" % (conf.url, kb.injection.place, safeFormatString(conf.parameters[kb.injection.place]), safeFormatString(dbms)))
|
||||||
|
|
||||||
firstRegExp = "(%s|%s|%s|%s)" % ("|".join([alias for alias in MSSQL_ALIASES]),
|
firstRegExp = "(%s|%s|%s|%s)" % ("|".join([alias for alias in MSSQL_ALIASES]),
|
||||||
"|".join([alias for alias in MYSQL_ALIASES]),
|
"|".join([alias for alias in MYSQL_ALIASES]),
|
||||||
|
@ -184,28 +171,43 @@ def setOs():
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
if condition:
|
if condition:
|
||||||
dataToSessionFile("[%s][%s][%s][OS][%s]\n" % (conf.url, kb.injPlace, safeFormatString(conf.parameters[kb.injPlace]), safeFormatString(kb.os)))
|
dataToSessionFile("[%s][%s][%s][OS][%s]\n" % (conf.url, kb.injection.place, safeFormatString(conf.parameters[kb.injection.place]), safeFormatString(kb.os)))
|
||||||
|
|
||||||
def setStacked():
|
def setBooleanBased(place, parameter, payload):
|
||||||
|
condition = (
|
||||||
|
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
|
||||||
|
not kb.resumedQueries[conf.url].has_key("Boolean-based blind injection") )
|
||||||
|
)
|
||||||
|
|
||||||
|
if condition:
|
||||||
|
dataToSessionFile("[%s][%s][%s][Boolean-based blind injection][%s]\n" % (conf.url, place, safeFormatString(conf.parameters[place]), payload))
|
||||||
|
|
||||||
|
def setStacked(place, parameter, payload):
|
||||||
condition = (
|
condition = (
|
||||||
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
|
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
|
||||||
not kb.resumedQueries[conf.url].has_key("Stacked queries") )
|
not kb.resumedQueries[conf.url].has_key("Stacked queries") )
|
||||||
)
|
)
|
||||||
|
|
||||||
if not isinstance(kb.stackedTest, basestring):
|
|
||||||
return
|
|
||||||
|
|
||||||
if condition:
|
if condition:
|
||||||
dataToSessionFile("[%s][%s][%s][Stacked queries][%s]\n" % (conf.url, kb.injPlace, safeFormatString(conf.parameters[kb.injPlace]), kb.stackedTest))
|
dataToSessionFile("[%s][%s][%s][Stacked queries][%s]\n" % (conf.url, place, safeFormatString(conf.parameters[place]), payload))
|
||||||
|
|
||||||
def setError():
|
def setError(place, parameter, payload):
|
||||||
condition = (
|
condition = (
|
||||||
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
|
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
|
||||||
not kb.resumedQueries[conf.url].has_key("Error based injection") )
|
not kb.resumedQueries[conf.url].has_key("Error-based injection") )
|
||||||
)
|
)
|
||||||
|
|
||||||
if condition:
|
if condition:
|
||||||
dataToSessionFile("[%s][%s][%s][Error based injection][Yes]\n" % (conf.url, kb.injPlace, safeFormatString(conf.parameters[kb.injPlace])))
|
dataToSessionFile("[%s][%s][%s][Error-based injection][%s]\n" % (conf.url, place, safeFormatString(conf.parameters[place]), payload))
|
||||||
|
|
||||||
|
def setTimeBased(place, parameter, payload):
|
||||||
|
condition = (
|
||||||
|
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
|
||||||
|
not kb.resumedQueries[conf.url].has_key("Time-based blind injection") )
|
||||||
|
)
|
||||||
|
|
||||||
|
if condition:
|
||||||
|
dataToSessionFile("[%s][%s][%s][Time-based blind injection][%s]\n" % (conf.url, place, safeFormatString(conf.parameters[place]), payload))
|
||||||
|
|
||||||
def setUnion(comment=None, count=None, position=None, negative=False, falseCond=False, payload=None):
|
def setUnion(comment=None, count=None, position=None, negative=False, falseCond=False, payload=None):
|
||||||
"""
|
"""
|
||||||
|
@ -226,7 +228,7 @@ def setUnion(comment=None, count=None, position=None, negative=False, falseCond=
|
||||||
)
|
)
|
||||||
|
|
||||||
if condition:
|
if condition:
|
||||||
dataToSessionFile("[%s][%s][%s][Union comment][%s]\n" % (conf.url, kb.injPlace, safeFormatString(conf.parameters[kb.injPlace]), safeFormatString(comment)))
|
dataToSessionFile("[%s][%s][%s][Union comment][%s]\n" % (conf.url, kb.injection.place, safeFormatString(conf.parameters[kb.injection.place]), safeFormatString(comment)))
|
||||||
|
|
||||||
kb.unionComment = comment
|
kb.unionComment = comment
|
||||||
|
|
||||||
|
@ -237,7 +239,7 @@ def setUnion(comment=None, count=None, position=None, negative=False, falseCond=
|
||||||
)
|
)
|
||||||
|
|
||||||
if condition:
|
if condition:
|
||||||
dataToSessionFile("[%s][%s][%s][Union count][%d]\n" % (conf.url, kb.injPlace, safeFormatString(conf.parameters[kb.injPlace]), count))
|
dataToSessionFile("[%s][%s][%s][Union count][%d]\n" % (conf.url, kb.injection.place, safeFormatString(conf.parameters[kb.injection.place]), count))
|
||||||
|
|
||||||
kb.unionCount = count
|
kb.unionCount = count
|
||||||
|
|
||||||
|
@ -248,7 +250,7 @@ def setUnion(comment=None, count=None, position=None, negative=False, falseCond=
|
||||||
)
|
)
|
||||||
|
|
||||||
if condition:
|
if condition:
|
||||||
dataToSessionFile("[%s][%s][%s][Union position][%s]\n" % (conf.url, kb.injPlace, safeFormatString(conf.parameters[kb.injPlace]), position))
|
dataToSessionFile("[%s][%s][%s][Union position][%s]\n" % (conf.url, kb.injection.place, safeFormatString(conf.parameters[kb.injection.place]), position))
|
||||||
|
|
||||||
kb.unionPosition = position
|
kb.unionPosition = position
|
||||||
|
|
||||||
|
@ -260,7 +262,7 @@ def setUnion(comment=None, count=None, position=None, negative=False, falseCond=
|
||||||
)
|
)
|
||||||
|
|
||||||
if condition:
|
if condition:
|
||||||
dataToSessionFile("[%s][%s][%s][Union negative][Yes]\n" % (conf.url, kb.injPlace, safeFormatString(conf.parameters[kb.injPlace])))
|
dataToSessionFile("[%s][%s][%s][Union negative][Yes]\n" % (conf.url, kb.injection.place, safeFormatString(conf.parameters[kb.injection.place])))
|
||||||
|
|
||||||
kb.unionNegative = True
|
kb.unionNegative = True
|
||||||
|
|
||||||
|
@ -272,7 +274,7 @@ def setUnion(comment=None, count=None, position=None, negative=False, falseCond=
|
||||||
)
|
)
|
||||||
|
|
||||||
if condition:
|
if condition:
|
||||||
dataToSessionFile("[%s][%s][%s][Union false condition][Yes]\n" % (conf.url, kb.injPlace, safeFormatString(conf.parameters[kb.injPlace])))
|
dataToSessionFile("[%s][%s][%s][Union false condition][Yes]\n" % (conf.url, kb.injection.place, safeFormatString(conf.parameters[kb.injection.place])))
|
||||||
|
|
||||||
kb.unionFalseCond = True
|
kb.unionFalseCond = True
|
||||||
|
|
||||||
|
@ -284,7 +286,7 @@ def setUnion(comment=None, count=None, position=None, negative=False, falseCond=
|
||||||
)
|
)
|
||||||
|
|
||||||
if condition:
|
if condition:
|
||||||
dataToSessionFile("[%s][%s][%s][Union payload][%s]\n" % (conf.url, kb.injPlace, safeFormatString(conf.parameters[kb.injPlace]), payload))
|
dataToSessionFile("[%s][%s][%s][Union payload][%s]\n" % (conf.url, kb.injection.place, safeFormatString(conf.parameters[kb.injection.place]), payload))
|
||||||
|
|
||||||
kb.unionTest = payload
|
kb.unionTest = payload
|
||||||
|
|
||||||
|
@ -295,7 +297,7 @@ def setRemoteTempPath():
|
||||||
)
|
)
|
||||||
|
|
||||||
if condition:
|
if condition:
|
||||||
dataToSessionFile("[%s][%s][%s][Remote temp path][%s]\n" % (conf.url, kb.injPlace, safeFormatString(conf.parameters[kb.injPlace]), safeFormatString(conf.tmpPath)))
|
dataToSessionFile("[%s][%s][%s][Remote temp path][%s]\n" % (conf.url, kb.injection.place, safeFormatString(conf.parameters[kb.injection.place]), safeFormatString(conf.tmpPath)))
|
||||||
|
|
||||||
def resumeConfKb(expression, url, value):
|
def resumeConfKb(expression, url, value):
|
||||||
if expression == "String" and url == conf.url:
|
if expression == "String" and url == conf.url:
|
||||||
|
@ -352,6 +354,12 @@ def resumeConfKb(expression, url, value):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
elif expression == "Injection type" and url == conf.url:
|
||||||
|
kb.injection.stype = unSafeFormatString(value[:-1])
|
||||||
|
|
||||||
|
logMsg = "resuming injection type '%s' from session file" % kb.injection.stype
|
||||||
|
logger.info(logMsg)
|
||||||
|
|
||||||
elif expression == "Injection point" and url == conf.url:
|
elif expression == "Injection point" and url == conf.url:
|
||||||
injPlace = value[:-1]
|
injPlace = value[:-1]
|
||||||
|
|
||||||
|
@ -365,7 +373,7 @@ def resumeConfKb(expression, url, value):
|
||||||
warnMsg += "injectable point"
|
warnMsg += "injectable point"
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
else:
|
else:
|
||||||
kb.injPlace = injPlace
|
kb.injection.place = injPlace
|
||||||
|
|
||||||
elif expression == "Injection parameter" and url == conf.url:
|
elif expression == "Injection parameter" and url == conf.url:
|
||||||
injParameter = unSafeFormatString(value[:-1])
|
injParameter = unSafeFormatString(value[:-1])
|
||||||
|
@ -374,8 +382,8 @@ def resumeConfKb(expression, url, value):
|
||||||
logger.info(logMsg)
|
logger.info(logMsg)
|
||||||
|
|
||||||
condition = (
|
condition = (
|
||||||
not conf.paramDict.has_key(kb.injPlace) or
|
not conf.paramDict.has_key(kb.injection.place) or
|
||||||
not conf.paramDict[kb.injPlace].has_key(injParameter)
|
not conf.paramDict[kb.injection.place].has_key(injParameter)
|
||||||
)
|
)
|
||||||
|
|
||||||
if condition:
|
if condition:
|
||||||
|
@ -385,19 +393,24 @@ def resumeConfKb(expression, url, value):
|
||||||
warnMsg += "injectable point"
|
warnMsg += "injectable point"
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
else:
|
else:
|
||||||
kb.injParameter = injParameter
|
kb.injection.parameter = injParameter
|
||||||
|
|
||||||
elif expression == "Injection type" and url == conf.url:
|
elif expression == "Injection parameter type" and url == conf.url:
|
||||||
kb.injType = unSafeFormatString(value[:-1])
|
kb.injection.ptype = unSafeFormatString(value[:-1])
|
||||||
|
|
||||||
logMsg = "resuming injection type '%s' from session file" % kb.injType
|
logMsg = "resuming injection parameter type '%s' from session file" % kb.injection.ptype
|
||||||
logger.info(logMsg)
|
logger.info(logMsg)
|
||||||
|
|
||||||
elif expression == "Parenthesis" and url == conf.url:
|
elif expression == "Injection prefix" and url == conf.url:
|
||||||
kb.parenthesis = int(value[:-1])
|
kb.injection.prefix = unSafeFormatString(value[:-1])
|
||||||
|
|
||||||
logMsg = "resuming %d number of " % kb.parenthesis
|
logMsg = "resuming injection prefix '%s' from session file" % kb.injection.prefix
|
||||||
logMsg += "parenthesis from session file"
|
logger.info(logMsg)
|
||||||
|
|
||||||
|
elif expression == "Injection suffix" and url == conf.url:
|
||||||
|
kb.injection.suffix = unSafeFormatString(value[:-1])
|
||||||
|
|
||||||
|
logMsg = "resuming injection suffix '%s' from session file" % kb.injection.suffix
|
||||||
logger.info(logMsg)
|
logger.info(logMsg)
|
||||||
|
|
||||||
elif expression == "DBMS" and url == conf.url:
|
elif expression == "DBMS" and url == conf.url:
|
||||||
|
@ -455,6 +468,20 @@ def resumeConfKb(expression, url, value):
|
||||||
else:
|
else:
|
||||||
conf.os = os
|
conf.os = os
|
||||||
|
|
||||||
|
elif expression == "Boolean-based blind injection" and url == conf.url:
|
||||||
|
kb.booleanTest = unSafeFormatString(value[:-1])
|
||||||
|
|
||||||
|
logMsg = "resuming boolean-based blind injection "
|
||||||
|
logMsg += "'%s' from session file" % kb.booleanTest
|
||||||
|
logger.info(logMsg)
|
||||||
|
|
||||||
|
elif expression == "Error-based injection" and url == conf.url:
|
||||||
|
kb.errorTest = unSafeFormatString(value[:-1])
|
||||||
|
|
||||||
|
logMsg = "resuming error-based injection "
|
||||||
|
logMsg += "'%s' from session file" % kb.errorTest
|
||||||
|
logger.info(logMsg)
|
||||||
|
|
||||||
elif expression == "Stacked queries" and url == conf.url:
|
elif expression == "Stacked queries" and url == conf.url:
|
||||||
kb.stackedTest = unSafeFormatString(value[:-1])
|
kb.stackedTest = unSafeFormatString(value[:-1])
|
||||||
|
|
||||||
|
@ -462,11 +489,11 @@ def resumeConfKb(expression, url, value):
|
||||||
logMsg += "'%s' from session file" % kb.stackedTest
|
logMsg += "'%s' from session file" % kb.stackedTest
|
||||||
logger.info(logMsg)
|
logger.info(logMsg)
|
||||||
|
|
||||||
elif expression == "Error based injection" and url == conf.url:
|
elif expression == "Time-based blind injection" and url == conf.url:
|
||||||
kb.errorTest = unSafeFormatString(value[:-1]) == 'Yes'
|
kb.timeTest = unSafeFormatString(value[:-1])
|
||||||
|
|
||||||
logMsg = "resuming error based injection "
|
logMsg = "resuming time-based blind injection "
|
||||||
logMsg += "'%s' from session file" % kb.errorTest
|
logMsg += "'%s' from session file" % kb.timeTest
|
||||||
logger.info(logMsg)
|
logger.info(logMsg)
|
||||||
|
|
||||||
elif expression == "Union comment" and url == conf.url:
|
elif expression == "Union comment" and url == conf.url:
|
||||||
|
|
|
@ -183,6 +183,14 @@ def cmdLineParser():
|
||||||
"HTTP responses when using blind SQL "
|
"HTTP responses when using blind SQL "
|
||||||
"injection technique.")
|
"injection technique.")
|
||||||
|
|
||||||
|
detection.add_option("--level", dest="level", default=1, type="int",
|
||||||
|
help="Level of tests to perform (1-5, "
|
||||||
|
"default 1)")
|
||||||
|
|
||||||
|
detection.add_option("--risk", dest="risk", default=1, type="int",
|
||||||
|
help="Risk of tests to perform (0-3, "
|
||||||
|
"default 1)")
|
||||||
|
|
||||||
detection.add_option("--string", dest="string",
|
detection.add_option("--string", dest="string",
|
||||||
help="String to match in page when the "
|
help="String to match in page when the "
|
||||||
"query is valid")
|
"query is valid")
|
||||||
|
|
70
lib/parse/payloads.py
Normal file
70
lib/parse/payloads.py
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
$Id$
|
||||||
|
|
||||||
|
Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/)
|
||||||
|
See the file 'doc/COPYING' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from xml.etree import ElementTree as et
|
||||||
|
|
||||||
|
from lib.core.data import conf
|
||||||
|
from lib.core.data import paths
|
||||||
|
from lib.core.datatype import advancedDict
|
||||||
|
|
||||||
|
def cleanupVals(values, tag):
|
||||||
|
count = 0
|
||||||
|
|
||||||
|
for value in values:
|
||||||
|
if value.isdigit():
|
||||||
|
value = int(value)
|
||||||
|
|
||||||
|
values[count] = value
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
if len(values) == 1 and tag not in ("clause", "where"):
|
||||||
|
values = values[0]
|
||||||
|
|
||||||
|
return values
|
||||||
|
|
||||||
|
def parseXmlNode(node):
|
||||||
|
for element in node.getiterator('boundary'):
|
||||||
|
boundary = advancedDict()
|
||||||
|
|
||||||
|
for child in element.getchildren():
|
||||||
|
if child.text:
|
||||||
|
values = cleanupVals(child.text.split(','), child.tag)
|
||||||
|
boundary[child.tag] = values
|
||||||
|
else:
|
||||||
|
boundary[child.tag] = None
|
||||||
|
|
||||||
|
conf.boundaries.append(boundary)
|
||||||
|
|
||||||
|
for element in node.getiterator('test'):
|
||||||
|
test = advancedDict()
|
||||||
|
|
||||||
|
for child in element.getchildren():
|
||||||
|
if child.text and child.text.strip():
|
||||||
|
values = cleanupVals(child.text.split(','), child.tag)
|
||||||
|
test[child.tag] = values
|
||||||
|
else:
|
||||||
|
if len(child.getchildren()) == 0:
|
||||||
|
test[child.tag] = None
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
test[child.tag] = advancedDict()
|
||||||
|
|
||||||
|
for gchild in child.getchildren():
|
||||||
|
if gchild.tag in test[child.tag]:
|
||||||
|
prevtext = test[child.tag][gchild.tag]
|
||||||
|
test[child.tag][gchild.tag] = [prevtext, gchild.text]
|
||||||
|
else:
|
||||||
|
test[child.tag][gchild.tag] = gchild.text
|
||||||
|
|
||||||
|
conf.tests.append(test)
|
||||||
|
|
||||||
|
def loadPayloads():
|
||||||
|
doc = et.parse(paths.PAYLOADS_XML)
|
||||||
|
root = doc.getroot()
|
||||||
|
parseXmlNode(root)
|
|
@ -338,7 +338,7 @@ class Connect:
|
||||||
toUrlencode = { PLACE.GET: True, PLACE.POST: True, PLACE.COOKIE: conf.cookieUrlencode, PLACE.UA: True, PLACE.URI: False }
|
toUrlencode = { PLACE.GET: True, PLACE.POST: True, PLACE.COOKIE: conf.cookieUrlencode, PLACE.UA: True, PLACE.URI: False }
|
||||||
|
|
||||||
if not place:
|
if not place:
|
||||||
place = kb.injPlace
|
place = kb.injection.place
|
||||||
|
|
||||||
payload = agent.extractPayload(value)
|
payload = agent.extractPayload(value)
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ def direct(query, content=True):
|
||||||
return None
|
return None
|
||||||
elif content:
|
elif content:
|
||||||
if conf.hostname not in kb.resumedQueries or ( conf.hostname in kb.resumedQueries and query not in kb.resumedQueries[conf.hostname] ):
|
if conf.hostname not in kb.resumedQueries or ( conf.hostname in kb.resumedQueries and query not in kb.resumedQueries[conf.hostname] ):
|
||||||
dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.hostname, kb.injPlace, conf.parameters[kb.injPlace], query, base64pickle(output)))
|
dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.hostname, kb.injection.place, conf.parameters[kb.injection.place], query, base64pickle(output)))
|
||||||
|
|
||||||
if len(output) == 1:
|
if len(output) == 1:
|
||||||
if len(output[0]) == 1:
|
if len(output[0]) == 1:
|
||||||
|
|
|
@ -45,7 +45,7 @@ def __goInference(payload, expression, charsetType=None, firstChar=None, lastCha
|
||||||
else:
|
else:
|
||||||
length = None
|
length = None
|
||||||
|
|
||||||
dataToSessionFile("[%s][%s][%s][%s][" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], expression))
|
dataToSessionFile("[%s][%s][%s][%s][" % (conf.url, kb.injection.place, conf.parameters[kb.injection.place], expression))
|
||||||
|
|
||||||
count, value = bisection(payload, expression, length, charsetType, firstChar, lastChar)
|
count, value = bisection(payload, expression, length, charsetType, firstChar, lastChar)
|
||||||
|
|
||||||
|
@ -353,7 +353,7 @@ def getValue(expression, blind=True, inband=True, error=True, fromUser=False, ex
|
||||||
|
|
||||||
expression = expression.replace("DISTINCT ", "")
|
expression = expression.replace("DISTINCT ", "")
|
||||||
|
|
||||||
if error and conf.errorTest:
|
if error and kb.errorTest:
|
||||||
value = goError(expression)
|
value = goError(expression)
|
||||||
|
|
||||||
if not value:
|
if not value:
|
||||||
|
@ -435,7 +435,7 @@ def goError(expression, suppressOutput=False, returnPayload=False):
|
||||||
result = errorUse(expression, returnPayload)
|
result = errorUse(expression, returnPayload)
|
||||||
|
|
||||||
if not returnPayload:
|
if not returnPayload:
|
||||||
dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], expression, replaceNewlineTabs(result)))
|
dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.url, kb.injection.place, conf.parameters[kb.injection.place], expression, replaceNewlineTabs(result)))
|
||||||
|
|
||||||
if suppressOutput:
|
if suppressOutput:
|
||||||
conf.verbose = popValue()
|
conf.verbose = popValue()
|
||||||
|
|
|
@ -23,7 +23,7 @@ def timeTest():
|
||||||
return kb.timeTest
|
return kb.timeTest
|
||||||
|
|
||||||
infoMsg = "testing time-based blind sql injection on parameter "
|
infoMsg = "testing time-based blind sql injection on parameter "
|
||||||
infoMsg += "'%s' with %s condition syntax" % (kb.injParameter, conf.logic)
|
infoMsg += "'%s' with %s condition syntax" % (kb.injection.parameter, conf.logic)
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
timeQuery = getDelayQuery(andCond=True)
|
timeQuery = getDelayQuery(andCond=True)
|
||||||
|
@ -37,18 +37,18 @@ def timeTest():
|
||||||
if duration >= conf.timeSec:
|
if duration >= conf.timeSec:
|
||||||
infoMsg = "the target url is affected by a time-based blind "
|
infoMsg = "the target url is affected by a time-based blind "
|
||||||
infoMsg += "sql injection with AND condition syntax on parameter "
|
infoMsg += "sql injection with AND condition syntax on parameter "
|
||||||
infoMsg += "'%s'" % kb.injParameter
|
infoMsg += "'%s'" % kb.injection.parameter
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
kb.timeTest = agent.removePayloadDelimiters(payload, False)
|
kb.timeTest = agent.removePayloadDelimiters(payload, False)
|
||||||
else:
|
else:
|
||||||
warnMsg = "the target url is not affected by a time-based blind "
|
warnMsg = "the target url is not affected by a time-based blind "
|
||||||
warnMsg += "sql injection with AND condition syntax on parameter "
|
warnMsg += "sql injection with AND condition syntax on parameter "
|
||||||
warnMsg += "'%s'" % kb.injParameter
|
warnMsg += "'%s'" % kb.injection.parameter
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
infoMsg = "testing time-based blind sql injection on parameter "
|
infoMsg = "testing time-based blind sql injection on parameter "
|
||||||
infoMsg += "'%s' with stacked queries syntax" % kb.injParameter
|
infoMsg += "'%s' with stacked queries syntax" % kb.injection.parameter
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
timeQuery = getDelayQuery(andCond=True)
|
timeQuery = getDelayQuery(andCond=True)
|
||||||
|
@ -59,14 +59,14 @@ def timeTest():
|
||||||
if duration >= conf.timeSec:
|
if duration >= conf.timeSec:
|
||||||
infoMsg = "the target url is affected by a time-based blind sql "
|
infoMsg = "the target url is affected by a time-based blind sql "
|
||||||
infoMsg += "injection with stacked queries syntax on parameter "
|
infoMsg += "injection with stacked queries syntax on parameter "
|
||||||
infoMsg += "'%s'" % kb.injParameter
|
infoMsg += "'%s'" % kb.injection.parameter
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
kb.timeTest = agent.removePayloadDelimiters(payload, False)
|
kb.timeTest = agent.removePayloadDelimiters(payload, False)
|
||||||
else:
|
else:
|
||||||
warnMsg = "the target url is not affected by a time-based blind "
|
warnMsg = "the target url is not affected by a time-based blind "
|
||||||
warnMsg += "sql injection with stacked queries syntax on parameter "
|
warnMsg += "sql injection with stacked queries syntax on parameter "
|
||||||
warnMsg += "'%s'" % kb.injParameter
|
warnMsg += "'%s'" % kb.injection.parameter
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
kb.timeTest = False
|
kb.timeTest = False
|
||||||
|
|
|
@ -27,7 +27,7 @@ def errorTest():
|
||||||
return kb.errorTest
|
return kb.errorTest
|
||||||
|
|
||||||
infoMsg = "testing error-based sql injection on parameter "
|
infoMsg = "testing error-based sql injection on parameter "
|
||||||
infoMsg += "'%s' with %s condition syntax" % (kb.injParameter, conf.logic)
|
infoMsg += "'%s' with %s condition syntax" % (kb.injection.parameter, conf.logic)
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
randInt = getUnicode(randomInt(1))
|
randInt = getUnicode(randomInt(1))
|
||||||
|
@ -36,13 +36,13 @@ def errorTest():
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
infoMsg = "the target url is affected by an error-based sql "
|
infoMsg = "the target url is affected by an error-based sql "
|
||||||
infoMsg += "injection on parameter '%s'" % kb.injParameter
|
infoMsg += "injection on parameter '%s'" % kb.injection.parameter
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
kb.errorTest = agent.removePayloadDelimiters(usedPayload, False)
|
kb.errorTest = agent.removePayloadDelimiters(usedPayload, False)
|
||||||
else:
|
else:
|
||||||
warnMsg = "the target url is not affected by an error-based sql "
|
warnMsg = "the target url is not affected by an error-based sql "
|
||||||
warnMsg += "injection on parameter '%s'" % kb.injParameter
|
warnMsg += "injection on parameter '%s'" % kb.injection.parameter
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
kb.errorTest = False
|
kb.errorTest = False
|
||||||
|
|
|
@ -157,7 +157,7 @@ def unionTest():
|
||||||
technique = "char (%s) bruteforcing" % conf.uChar
|
technique = "char (%s) bruteforcing" % conf.uChar
|
||||||
|
|
||||||
infoMsg = "testing inband sql injection on parameter "
|
infoMsg = "testing inband sql injection on parameter "
|
||||||
infoMsg += "'%s' with %s technique" % (kb.injParameter, technique)
|
infoMsg += "'%s' with %s technique" % (kb.injection.parameter, technique)
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
validPayload = None
|
validPayload = None
|
||||||
|
@ -174,12 +174,12 @@ def unionTest():
|
||||||
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 "
|
||||||
infoMsg += "inband sql injection vulnerability "
|
infoMsg += "inband sql injection vulnerability "
|
||||||
infoMsg += "on parameter '%s' with %d columns" % (kb.injParameter, kb.unionCount)
|
infoMsg += "on parameter '%s' with %d columns" % (kb.injection.parameter, kb.unionCount)
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
else:
|
else:
|
||||||
infoMsg = "the target url is not affected by an exploitable "
|
infoMsg = "the target url is not affected by an exploitable "
|
||||||
infoMsg += "inband sql injection vulnerability "
|
infoMsg += "inband sql injection vulnerability "
|
||||||
infoMsg += "on parameter '%s'" % kb.injParameter
|
infoMsg += "on parameter '%s'" % kb.injection.parameter
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
validPayload = agent.removePayloadDelimiters(validPayload, False)
|
validPayload = agent.removePayloadDelimiters(validPayload, False)
|
||||||
|
|
|
@ -26,7 +26,7 @@ def stackedTest():
|
||||||
return kb.stackedTest
|
return kb.stackedTest
|
||||||
|
|
||||||
infoMsg = "testing stacked queries sql injection on parameter "
|
infoMsg = "testing stacked queries sql injection on parameter "
|
||||||
infoMsg += "'%s'" % kb.injParameter
|
infoMsg += "'%s'" % kb.injection.parameter
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
query = getDelayQuery()
|
query = getDelayQuery()
|
||||||
|
@ -36,13 +36,13 @@ def stackedTest():
|
||||||
|
|
||||||
if duration >= conf.timeSec:
|
if duration >= conf.timeSec:
|
||||||
infoMsg = "the target url is affected by a stacked queries "
|
infoMsg = "the target url is affected by a stacked queries "
|
||||||
infoMsg += "sql injection on parameter '%s'" % kb.injParameter
|
infoMsg += "sql injection on parameter '%s'" % kb.injection.parameter
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
kb.stackedTest = agent.removePayloadDelimiters(payload, False)
|
kb.stackedTest = agent.removePayloadDelimiters(payload, False)
|
||||||
else:
|
else:
|
||||||
warnMsg = "the target url is not affected by a stacked queries "
|
warnMsg = "the target url is not affected by a stacked queries "
|
||||||
warnMsg += "sql injection on parameter '%s'" % kb.injParameter
|
warnMsg += "sql injection on parameter '%s'" % kb.injection.parameter
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
kb.stackedTest = False
|
kb.stackedTest = False
|
||||||
|
|
|
@ -74,7 +74,7 @@ def queryOutputLength(expression, payload):
|
||||||
if output:
|
if output:
|
||||||
return 0, output, regExpr
|
return 0, output, regExpr
|
||||||
|
|
||||||
dataToSessionFile("[%s][%s][%s][%s][" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], lengthExpr))
|
dataToSessionFile("[%s][%s][%s][%s][" % (conf.url, kb.injection.place, conf.parameters[kb.injection.place], lengthExpr))
|
||||||
|
|
||||||
start = time.time()
|
start = time.time()
|
||||||
lengthExprUnescaped = unescaper.unescape(lengthExpr)
|
lengthExprUnescaped = unescaper.unescape(lengthExpr)
|
||||||
|
@ -156,7 +156,7 @@ def resume(expression, payload):
|
||||||
infoMsg += "%s" % resumedValue.split("\n")[0]
|
infoMsg += "%s" % resumedValue.split("\n")[0]
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], expression, replaceNewlineTabs(resumedValue)))
|
dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.url, kb.injection.place, conf.parameters[kb.injection.place], expression, replaceNewlineTabs(resumedValue)))
|
||||||
|
|
||||||
return resumedValue
|
return resumedValue
|
||||||
elif len(resumedValue) < int(length):
|
elif len(resumedValue) < int(length):
|
||||||
|
@ -164,7 +164,7 @@ def resume(expression, payload):
|
||||||
infoMsg += "%s..." % resumedValue.split("\n")[0]
|
infoMsg += "%s..." % resumedValue.split("\n")[0]
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
dataToSessionFile("[%s][%s][%s][%s][%s" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], expression, replaceNewlineTabs(resumedValue)))
|
dataToSessionFile("[%s][%s][%s][%s][%s" % (conf.url, kb.injection.place, conf.parameters[kb.injection.place], expression, replaceNewlineTabs(resumedValue)))
|
||||||
|
|
||||||
if select:
|
if select:
|
||||||
newExpr = expression.replace(regExpr, safeStringFormat(substringQuery, (regExpr, len(resumedValue) + 1, int(length))), 1)
|
newExpr = expression.replace(regExpr, safeStringFormat(substringQuery, (regExpr, len(resumedValue) + 1, int(length))), 1)
|
||||||
|
|
|
@ -79,7 +79,7 @@ class Filesystem(GenericFilesystem):
|
||||||
fcEncodedStr = fcEncodedList[0]
|
fcEncodedStr = fcEncodedList[0]
|
||||||
fcEncodedStrLen = len(fcEncodedStr)
|
fcEncodedStrLen = len(fcEncodedStr)
|
||||||
|
|
||||||
if kb.injPlace == PLACE.GET and fcEncodedStrLen > 8000:
|
if kb.injection.place == PLACE.GET and fcEncodedStrLen > 8000:
|
||||||
warnMsg = "the injection is on a GET parameter and the file "
|
warnMsg = "the injection is on a GET parameter and the file "
|
||||||
warnMsg += "to be written hexadecimal value is %d " % fcEncodedStrLen
|
warnMsg += "to be written hexadecimal value is %d " % fcEncodedStrLen
|
||||||
warnMsg += "bytes, this might cause errors in the file "
|
warnMsg += "bytes, this might cause errors in the file "
|
||||||
|
|
|
@ -164,7 +164,7 @@ class Fingerprint(GenericFingerprint):
|
||||||
infoMsg = "confirming MySQL"
|
infoMsg = "confirming MySQL"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
payload = agent.fullPayload("AND ISNULL(1/0)" if kb.injPlace != PLACE.URI else "AND ISNULL(1 DIV 0)")
|
payload = agent.fullPayload("AND ISNULL(1/0)" if kb.injection.place != PLACE.URI else "AND ISNULL(1 DIV 0)")
|
||||||
result = Request.queryPage(payload)
|
result = Request.queryPage(payload)
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
|
|
14
sqlmap.conf
14
sqlmap.conf
|
@ -192,6 +192,20 @@ tamper =
|
||||||
# content from HTTP responses when using blind SQL injection technique.
|
# content from HTTP responses when using blind SQL injection technique.
|
||||||
[Detection]
|
[Detection]
|
||||||
|
|
||||||
|
# Level of tests to perform
|
||||||
|
# The higher the value is, the higher the number of HTTP(s) requests are
|
||||||
|
# as well as the better chances to detect a tricky SQL injection.
|
||||||
|
# Valid: Integer between 1 and 5
|
||||||
|
# Default: 1
|
||||||
|
level = 1
|
||||||
|
|
||||||
|
# Risk of tests to perform
|
||||||
|
# Note: boolean-based blind SQL injection tests with AND are considered
|
||||||
|
# risk 1, with OR are considered risk 3.
|
||||||
|
# Valid: Integer between 0 and 3
|
||||||
|
# Default: 1
|
||||||
|
risk = 1
|
||||||
|
|
||||||
# String to match within the page content when the query is valid, only
|
# String to match within the page content when the query is valid, only
|
||||||
# needed if the page content dynamically changes at each refresh.
|
# needed if the page content dynamically changes at each refresh.
|
||||||
# Refer to the user's manual for further details.
|
# Refer to the user's manual for further details.
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
<root>
|
|
||||||
<case name="custom" desc="custom">
|
|
||||||
<test>
|
|
||||||
<positive format="%s%s%s %s %s%d=%d %s" params="value, prefix, ")" * parenthesis, logic, "(" * parenthesis, randInt, randInt, suffix"/>
|
|
||||||
<negative format="%s%s%s %s %s%d=%d %s" params="value, prefix, ")" * parenthesis, logic, "(" * parenthesis, randInt, randInt + 1, suffix"/>
|
|
||||||
</test>
|
|
||||||
<usage>
|
|
||||||
<prefix format="%s " params="')' * parenthesis"/>
|
|
||||||
<suffix format=" %s %s" params="logic, '(' * parenthesis"/>
|
|
||||||
</usage>
|
|
||||||
</case>
|
|
||||||
<case name="numeric" desc="unescaped numeric">
|
|
||||||
<test>
|
|
||||||
<positive format="%s%s %s %s%d=%d" params="value, ")" * parenthesis, logic, "(" * parenthesis, randInt, randInt"/>
|
|
||||||
<negative format="%s%s %s %s%d=%d" params="value, ")" * parenthesis, logic, "(" * parenthesis, randInt, randInt + 1"/>
|
|
||||||
</test>
|
|
||||||
<usage>
|
|
||||||
<prefix format="%s " params="')' * parenthesis"/>
|
|
||||||
<suffix format=" %s %s%d=%d" params="logic, '(' * parenthesis, randInt, randInt"/>
|
|
||||||
</usage>
|
|
||||||
</case>
|
|
||||||
<case name="stringsingle" desc="single quoted string">
|
|
||||||
<test>
|
|
||||||
<positive format="%s'%s %s %s'%s'='%s" params="value, ")" * parenthesis, logic, "(" * parenthesis, randStr, randStr"/>
|
|
||||||
<negative format="%s'%s %s %s'%s'='%s" params="value, ")" * parenthesis, logic, "(" * parenthesis, randStr, randStr + randomStr(1)"/>
|
|
||||||
</test>
|
|
||||||
<usage>
|
|
||||||
<prefix format="'%s " params="')' * parenthesis"/>
|
|
||||||
<suffix format=" %s %s'%s'='%s" params="logic, '(' * parenthesis, randStr, randStr"/>
|
|
||||||
</usage>
|
|
||||||
</case>
|
|
||||||
<case name="likesingle" desc="LIKE single quoted string">
|
|
||||||
<test>
|
|
||||||
<positive format="%s'%s %s %s'%s' LIKE '%s" params="value, ")" * parenthesis, logic, "(" * parenthesis, randStr, randStr"/>
|
|
||||||
<negative format="%s'%s %s %s'%s' LIKE '%s" params="value, ")" * parenthesis, logic, "(" * parenthesis, randStr, randStr + randomStr(1)"/>
|
|
||||||
</test>
|
|
||||||
<usage>
|
|
||||||
<prefix format="'%s " params="')' * parenthesis"/>
|
|
||||||
<suffix format=" %s %s'%s' LIKE '%s" params="logic, '(' * parenthesis, randStr, randStr"/>
|
|
||||||
</usage>
|
|
||||||
</case>
|
|
||||||
<case name="stringdouble" desc="double quoted string">
|
|
||||||
<test>
|
|
||||||
<positive format="%s"%s %s %s"%s"="%s" params="value, ")" * parenthesis, logic, "(" * parenthesis, randStr, randStr"/>
|
|
||||||
<negative format="%s"%s %s %s"%s"="%s" params="value, ")" * parenthesis, logic, "(" * parenthesis, randStr, randStr + randomStr(1)"/>
|
|
||||||
</test>
|
|
||||||
<usage>
|
|
||||||
<prefix format=""%s " params="')' * parenthesis"/>
|
|
||||||
<suffix format=" %s %s"%s"="%s" params="logic, '(' * parenthesis, randStr, randStr"/>
|
|
||||||
</usage>
|
|
||||||
</case>
|
|
||||||
<case name="likedouble" desc="LIKE double quoted string">
|
|
||||||
<test>
|
|
||||||
<positive format="%s"%s %s %s"%s" LIKE "%s" params="value, ")" * parenthesis, logic, "(" * parenthesis, randStr, randStr"/>
|
|
||||||
<negative format="%s"%s %s %s"%s" LIKE "%s" params="value, ")" * parenthesis, logic, "(" * parenthesis, randStr, randStr + randomStr(1)"/>
|
|
||||||
</test>
|
|
||||||
<usage>
|
|
||||||
<prefix format=""%s " params="')' * parenthesis"/>
|
|
||||||
<suffix format=" %s %s"%s" LIKE "%s" params="logic, '(' * parenthesis, randStr, randStr"/>
|
|
||||||
</usage>
|
|
||||||
</case>
|
|
||||||
</root>
|
|
1290
xml/payloads.xml
Normal file
1290
xml/payloads.xml
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user