mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2026-01-05 22:29:14 +00:00
Added tag <epayload> to the payloads.xml's <test> tag to define which payload to use when exploiting the test type.
Removed some useless tests. Moved <error> from queries.xml to payloads.xml as it makes more sense. Beeps at sql inj found only if --beep is provided. Minor fix in order to be able to pickle advancedDict() objects. Minor code refactoring. Removed useless folders.
This commit is contained in:
@@ -33,6 +33,7 @@ from lib.core.datatype import injectionDict
|
||||
from lib.core.enums import HTTPMETHOD
|
||||
from lib.core.enums import NULLCONNECTION
|
||||
from lib.core.enums import PAYLOAD
|
||||
from lib.core.enums import PLACE
|
||||
from lib.core.exception import sqlmapConnectionException
|
||||
from lib.core.exception import sqlmapGenericException
|
||||
from lib.core.exception import sqlmapNoneDataException
|
||||
@@ -331,14 +332,28 @@ def checkSqlInjection(place, parameter, value):
|
||||
# Feed with the boundaries details only the first time a
|
||||
# test has been successful
|
||||
if injection.place is None or injection.parameter is None:
|
||||
if place == PLACE.UA:
|
||||
injection.parameter = conf.agent
|
||||
else:
|
||||
injection.parameter = parameter
|
||||
|
||||
injection.place = place
|
||||
injection.parameter = parameter
|
||||
injection.ptype = ptype
|
||||
injection.prefix = prefix
|
||||
injection.suffix = suffix
|
||||
|
||||
if "epayload" in test:
|
||||
epayload = "%s%s" % (test.epayload, comment)
|
||||
else:
|
||||
epayload = None
|
||||
|
||||
# Feed with test details every time a test is successful
|
||||
injection.data[stype] = (title, agent.removePayloadDelimiters(reqPayload, False), where, comment)
|
||||
injection.data[stype] = advancedDict()
|
||||
injection.data[stype].title = title
|
||||
injection.data[stype].payload = agent.removePayloadDelimiters(reqPayload, False)
|
||||
injection.data[stype].where = where
|
||||
injection.data[stype].epayload = epayload
|
||||
injection.data[stype].comment = comment
|
||||
|
||||
if "details" in test:
|
||||
for detailKey, detailValue in test.details.items():
|
||||
@@ -351,7 +366,8 @@ def checkSqlInjection(place, parameter, value):
|
||||
elif detailKey == "os" and injection.os is None:
|
||||
injection.os = detailValue
|
||||
|
||||
beep()
|
||||
if conf.beep:
|
||||
beep()
|
||||
|
||||
# There is no need to perform this test for other
|
||||
# <where> tags
|
||||
@@ -703,7 +719,6 @@ def checkConnection(suppressOutput=False):
|
||||
try:
|
||||
page, _ = Request.queryPage(content=True)
|
||||
conf.seqMatcher.set_seq1(page)
|
||||
|
||||
except sqlmapConnectionException, errMsg:
|
||||
errMsg = getUnicode(errMsg)
|
||||
raise sqlmapConnectionException, errMsg
|
||||
|
||||
@@ -107,10 +107,9 @@ def __formatInjection(inj):
|
||||
data += "Parameter: %s\n" % inj.parameter
|
||||
|
||||
for stype, sdata in inj.data.items():
|
||||
stype = PAYLOAD.SQLINJECTION[stype] if isinstance(stype, int) else stype
|
||||
data += " Type: %s\n" % stype
|
||||
data += " Title: %s\n" % sdata[0]
|
||||
data += " Payload: %s\n\n" % sdata[1]
|
||||
data += " Title: %s\n" % sdata.title
|
||||
data += " Payload: %s\n\n" % sdata.payload
|
||||
|
||||
return data
|
||||
|
||||
@@ -136,7 +135,7 @@ def __saveToSessionFile():
|
||||
parameter = inj.parameter
|
||||
|
||||
for stype, sdata in inj.data.items():
|
||||
payload = sdata[1]
|
||||
payload = sdata.payload
|
||||
|
||||
if stype == 1:
|
||||
kb.booleanTest = payload
|
||||
@@ -303,7 +302,8 @@ def start():
|
||||
# TODO: consider the following line in __setRequestParams()
|
||||
__testableParameters = True
|
||||
|
||||
if not kb.injection.place or not kb.injection.parameter:
|
||||
if (len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None)) \
|
||||
and (kb.injection.place is None or kb.injection.parameter is None):
|
||||
if not conf.string and not conf.regexp and not conf.eRegexp:
|
||||
# NOTE: this is not needed anymore, leaving only to display
|
||||
# a warning message to the user in case the page is not stable
|
||||
@@ -394,7 +394,7 @@ def start():
|
||||
__showInjections()
|
||||
__selectInjection()
|
||||
|
||||
if kb.injection.place and kb.injection.parameter:
|
||||
if kb.injection.place is not None and kb.injection.parameter is not None:
|
||||
if conf.multipleTargets:
|
||||
message = "do you want to exploit this SQL injection? [Y/n] "
|
||||
exploit = readInput(message, default="Y")
|
||||
|
||||
@@ -158,6 +158,9 @@ class Agent:
|
||||
return string
|
||||
|
||||
def cleanupPayload(self, payload):
|
||||
if payload is None:
|
||||
return
|
||||
|
||||
randInt = randomInt()
|
||||
randInt1 = randomInt()
|
||||
randStr = randomStr()
|
||||
|
||||
@@ -37,7 +37,7 @@ class advancedDict(dict):
|
||||
try:
|
||||
return self.__getitem__(item)
|
||||
except KeyError:
|
||||
raise sqlmapDataException, "Unable to access item '%s'" % item
|
||||
raise sqlmapDataException, "unable to access item '%s'" % item
|
||||
|
||||
def __setattr__(self, item, value):
|
||||
"""
|
||||
@@ -56,6 +56,12 @@ class advancedDict(dict):
|
||||
else:
|
||||
self.__setitem__(item, value)
|
||||
|
||||
def __getstate__(self):
|
||||
return self.__dict__
|
||||
|
||||
def __setstate__(self, dict):
|
||||
self.__dict__ = dict
|
||||
|
||||
def injectionDict():
|
||||
injection = advancedDict()
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ import re
|
||||
from lib.core.common import dataToSessionFile
|
||||
from lib.core.common import formatFingerprintString
|
||||
from lib.core.common import readInput
|
||||
from lib.core.convert import base64pickle
|
||||
from lib.core.convert import base64unpickle
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
@@ -78,30 +80,15 @@ def setInjection(inj):
|
||||
session file.
|
||||
"""
|
||||
|
||||
if inj.place == PLACE.UA:
|
||||
inj.parameter = conf.agent
|
||||
|
||||
condition = (
|
||||
( not kb.resumedQueries
|
||||
or ( kb.resumedQueries.has_key(conf.url) and
|
||||
( not kb.resumedQueries[conf.url].has_key("Injection point")
|
||||
or not kb.resumedQueries[conf.url].has_key("Injection parameter")
|
||||
) ) )
|
||||
not kb.resumedQueries[conf.url].has_key("Injection data")
|
||||
) )
|
||||
)
|
||||
|
||||
if condition:
|
||||
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))
|
||||
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))
|
||||
dataToSessionFile("[%s][%s][%s][Injection suffix][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), inj.suffix))
|
||||
|
||||
for stype, sdata in inj.data.items():
|
||||
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 title][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), sdata[0]))
|
||||
dataToSessionFile("[%s][%s][%s][Injection payload][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), sdata[1]))
|
||||
dataToSessionFile("[%s][%s][%s][Injection where][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), sdata[2]))
|
||||
dataToSessionFile("[%s][%s][%s][Injection comment][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), sdata[3]))
|
||||
dataToSessionFile("[%s][%s][%s][Injection data][%s]\n" % (conf.url, inj.place, safeFormatString(conf.parameters[inj.place]), base64pickle(inj)))
|
||||
|
||||
def setDbms(dbms):
|
||||
"""
|
||||
@@ -370,96 +357,11 @@ def resumeConfKb(expression, url, value):
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
elif expression == "Injection point" and url == conf.url:
|
||||
injPlace = value[:-1]
|
||||
elif expression == "Injection data" and url == conf.url:
|
||||
injection = base64unpickle(value[:-1])
|
||||
kb.injections.append(injection)
|
||||
|
||||
logMsg = "resuming injection point '%s' from session file" % injPlace
|
||||
logger.info(logMsg)
|
||||
|
||||
if not conf.paramDict.has_key(injPlace):
|
||||
warnMsg = "none of the parameters you provided "
|
||||
warnMsg += "matches the resumable injection point. "
|
||||
warnMsg += "sqlmap is going to reidentify the "
|
||||
warnMsg += "injectable point"
|
||||
logger.warn(warnMsg)
|
||||
else:
|
||||
if kb.injection.place is not None and kb.injection.parameter is not None:
|
||||
kb.injections.append(kb.injection)
|
||||
kb.injection = injectionDict()
|
||||
|
||||
kb.injection.place = injPlace
|
||||
|
||||
elif expression == "Injection parameter" and url == conf.url:
|
||||
injParameter = unSafeFormatString(value[:-1])
|
||||
|
||||
logMsg = "resuming injection parameter '%s' from session file" % injParameter
|
||||
logger.info(logMsg)
|
||||
|
||||
condition = (
|
||||
not conf.paramDict.has_key(kb.injection.place) or
|
||||
not conf.paramDict[kb.injection.place].has_key(injParameter)
|
||||
)
|
||||
|
||||
if condition:
|
||||
warnMsg = "none of the parameters you provided "
|
||||
warnMsg += "matches the resumable injection parameter. "
|
||||
warnMsg += "sqlmap is going to reidentify the "
|
||||
warnMsg += "injectable point"
|
||||
logger.warn(warnMsg)
|
||||
else:
|
||||
kb.injection.parameter = injParameter
|
||||
|
||||
elif expression == "Injection parameter type" and url == conf.url:
|
||||
kb.injection.ptype = unSafeFormatString(value[:-1])
|
||||
|
||||
logMsg = "resuming injection parameter type '%s' from session file" % kb.injection.ptype
|
||||
logger.info(logMsg)
|
||||
|
||||
elif expression == "Injection prefix" and url == conf.url:
|
||||
kb.injection.prefix = unSafeFormatString(value[:-1])
|
||||
|
||||
logMsg = "resuming injection prefix '%s' from session file" % kb.injection.prefix
|
||||
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)
|
||||
|
||||
elif expression == "Injection type" and url == conf.url:
|
||||
stype = unSafeFormatString(value[:-1])
|
||||
kb.injection.data[stype] = []
|
||||
|
||||
logMsg = "resuming injection type '%s' from session file" % stype
|
||||
logger.info(logMsg)
|
||||
|
||||
elif expression == "Injection title" and url == conf.url:
|
||||
title = unSafeFormatString(value[:-1])
|
||||
kb.injection.data[kb.injection.data.keys()[0]].append(title)
|
||||
|
||||
logMsg = "resuming injection title '%s' from session file" % title
|
||||
logger.info(logMsg)
|
||||
|
||||
elif expression == "Injection payload" and url == conf.url:
|
||||
payload = unSafeFormatString(value[:-1])
|
||||
kb.injection.data[kb.injection.data.keys()[0]].append(payload)
|
||||
|
||||
logMsg = "resuming injection payload '%s' from session file" % payload
|
||||
logger.info(logMsg)
|
||||
|
||||
elif expression == "Injection where" and url == conf.url:
|
||||
where = unSafeFormatString(value[:-1])
|
||||
kb.injection.data[kb.injection.data.keys()[0]].append(where)
|
||||
|
||||
logMsg = "resuming injection where '%s' from session file" % where
|
||||
logger.info(logMsg)
|
||||
|
||||
elif expression == "Injection comment" and url == conf.url:
|
||||
comment = unSafeFormatString(value[:-1])
|
||||
kb.injection.data[kb.injection.data.keys()[0]].append(comment)
|
||||
|
||||
logMsg = "resuming injection comment '%s' from session file" % comment
|
||||
logMsg = "resuming injection data"
|
||||
logger.info(logMsg)
|
||||
|
||||
elif expression == "Boolean-based blind injection" and url == conf.url:
|
||||
|
||||
@@ -14,6 +14,9 @@ from lib.core.data import paths
|
||||
from lib.core.datatype import advancedDict
|
||||
|
||||
def cleanupVals(values, tag):
|
||||
if isinstance(values, basestring):
|
||||
return values
|
||||
|
||||
count = 0
|
||||
|
||||
for value in values:
|
||||
@@ -48,7 +51,7 @@ def parseXmlNode(node):
|
||||
|
||||
for child in element.getchildren():
|
||||
if child.text and child.text.strip():
|
||||
values = cleanupVals(child.text.split(','), child.tag)
|
||||
values = cleanupVals(child.text.split(',') if child.tag != "epayload" else child.text, child.tag)
|
||||
test[child.tag] = values
|
||||
else:
|
||||
if len(child.getchildren()) == 0:
|
||||
|
||||
@@ -401,8 +401,8 @@ def goStacked(expression, silent=False):
|
||||
return direct(expression), None
|
||||
|
||||
comment = queries[kb.dbms].comment.query
|
||||
query = agent.prefixQuery("; %s" % expression)
|
||||
query = agent.suffixQuery("%s;%s" % (query, comment))
|
||||
query = agent.prefixQuery("; %s" % expression)
|
||||
query = agent.suffixQuery("%s;%s" % (query, comment))
|
||||
|
||||
debugMsg = "query: %s" % query
|
||||
logger.debug(debugMsg)
|
||||
@@ -412,7 +412,7 @@ def goStacked(expression, silent=False):
|
||||
|
||||
return payload, page
|
||||
|
||||
def goError(expression, suppressOutput=False, returnPayload=False):
|
||||
def goError(expression, suppressOutput=False):
|
||||
"""
|
||||
Retrieve the output of a SQL query taking advantage of an error-based
|
||||
SQL injection vulnerability on the affected parameter.
|
||||
@@ -436,10 +436,8 @@ def goError(expression, suppressOutput=False, returnPayload=False):
|
||||
result = resume(expression, None)
|
||||
|
||||
if not result:
|
||||
result = errorUse(expression, returnPayload)
|
||||
|
||||
if not returnPayload:
|
||||
dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.url, kb.injection.place, conf.parameters[kb.injection.place], expression, replaceNewlineTabs(result)))
|
||||
result = errorUse(expression)
|
||||
dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.url, kb.injection.place, conf.parameters[kb.injection.place], expression, replaceNewlineTabs(result)))
|
||||
|
||||
if suppressOutput:
|
||||
conf.verbose = popValue()
|
||||
|
||||
@@ -28,45 +28,37 @@ from lib.utils.resume import resume
|
||||
from lib.core.settings import ERROR_SPACE
|
||||
from lib.core.settings import ERROR_EMPTY_CHAR
|
||||
|
||||
def errorUse(expression, returnPayload=False):
|
||||
def errorUse(expression):
|
||||
"""
|
||||
Retrieve the output of a SQL query taking advantage of an error SQL
|
||||
injection vulnerability on the affected parameter.
|
||||
"""
|
||||
|
||||
output = None
|
||||
logic = conf.logic
|
||||
randInt = randomInt(1)
|
||||
query = agent.prefixQuery(queries[kb.misc.testedDbms].error.query)
|
||||
query = agent.suffixQuery(query)
|
||||
startLimiter = ""
|
||||
endLimiter = ""
|
||||
output = None
|
||||
randInt = randomInt(1)
|
||||
query = agent.cleanupPayload(kb.injection.data[2].epayload)
|
||||
query = agent.prefixQuery(query)
|
||||
query = agent.suffixQuery(query)
|
||||
check = "%s(?P<result>.*?)%s" % (kb.misc.start, kb.misc.stop)
|
||||
|
||||
expressionUnescaped = expression
|
||||
|
||||
if kb.dbmsDetected:
|
||||
_, _, _, _, _, _, fieldToCastStr = agent.getFields(expression)
|
||||
nulledCastedField = agent.nullAndCastField(fieldToCastStr)
|
||||
_, _, _, _, _, _, fieldToCastStr = agent.getFields(expression)
|
||||
nulledCastedField = agent.nullAndCastField(fieldToCastStr)
|
||||
|
||||
if kb.dbms == DBMS.MYSQL:
|
||||
nulledCastedField = nulledCastedField.replace("AS CHAR)", "AS CHAR(100))") # fix for that 'Subquery returns more than 1 row'
|
||||
if kb.dbms == DBMS.MYSQL:
|
||||
nulledCastedField = nulledCastedField.replace("AS CHAR)", "AS CHAR(100))") # fix for that 'Subquery returns more than 1 row'
|
||||
|
||||
expressionReplaced = expression.replace(fieldToCastStr, nulledCastedField, 1)
|
||||
expressionUnescaped = unescaper.unescape(expressionReplaced)
|
||||
startLimiter = unescaper.unescape("'%s'" % kb.misc.start)
|
||||
endLimiter = unescaper.unescape("'%s'" % kb.misc.stop)
|
||||
else:
|
||||
expressionUnescaped = kb.misc.handler.unescape(expression)
|
||||
startLimiter = kb.misc.handler.unescape("'%s'" % kb.misc.start)
|
||||
endLimiter = kb.misc.handler.unescape("'%s'" % kb.misc.stop)
|
||||
expression = expression.replace(fieldToCastStr, nulledCastedField, 1)
|
||||
expression = safeStringFormat(query, expression)
|
||||
expression = unescaper.unescape(expression)
|
||||
|
||||
forgedQuery = safeStringFormat(query, (logic, randInt, startLimiter, expressionUnescaped, endLimiter))
|
||||
debugMsg = "query: %s" % forgedQuery
|
||||
debugMsg = "query: %s" % expression
|
||||
logger.debug(debugMsg)
|
||||
|
||||
payload = agent.payload(newValue=forgedQuery)
|
||||
result = Request.queryPage(payload, content=True)
|
||||
match = re.search('%s(?P<result>.*?)%s' % (kb.misc.start, kb.misc.stop), result[0], re.DOTALL | re.IGNORECASE)
|
||||
payload = agent.payload(newValue=expression)
|
||||
reqBody, _ = Request.queryPage(payload, content=True)
|
||||
match = re.search(check, reqBody, re.DOTALL | re.IGNORECASE)
|
||||
|
||||
if match:
|
||||
output = match.group('result')
|
||||
@@ -78,7 +70,4 @@ def errorUse(expression, returnPayload=False):
|
||||
infoMsg = "retrieved: %s" % replaceNewlineTabs(output, stdout=True)
|
||||
logger.info(infoMsg)
|
||||
|
||||
if returnPayload:
|
||||
return output, payload
|
||||
else:
|
||||
return output
|
||||
return output
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
$Id$
|
||||
|
||||
Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/)
|
||||
See the file 'doc/COPYING' for copying permission
|
||||
"""
|
||||
|
||||
pass
|
||||
Reference in New Issue
Block a user