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:
Bernardo Damele
2010-12-01 17:09:52 +00:00
parent c00ea7f5e5
commit 089c16a1b8
11 changed files with 187 additions and 288 deletions

View File

@@ -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

View File

@@ -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")

View File

@@ -158,6 +158,9 @@ class Agent:
return string
def cleanupPayload(self, payload):
if payload is None:
return
randInt = randomInt()
randInt1 = randomInt()
randStr = randomStr()

View File

@@ -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()

View File

@@ -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:

View File

@@ -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:

View File

@@ -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()

View File

@@ -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

View File

@@ -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