lots of refactoring regarding removal of already obsolete session file mechanism

This commit is contained in:
Miroslav Stampar 2012-06-21 10:09:10 +00:00
parent 1e67b4f0b9
commit ec44e88db8
9 changed files with 135 additions and 398 deletions

View File

@ -738,13 +738,6 @@ def dataToStdout(data, forceOutput=False):
logging._releaseLock()
setFormatterPrependFlag(len(data) == 1 and data not in ('\n', '\r') or len(data) > 2 and data[0] == '\r' and data[-1] != '\n')
def dataToSessionFile(data):
if not conf.sessionFile or kb.suppressSession:
return
conf.sessionFP.write(data)
conf.sessionFP.flush()
def dataToTrafficFile(data):
if not conf.trafficFile:
return

View File

@ -143,14 +143,16 @@ class EXPECTED:
INT = "int"
class HASHDB_KEYS:
KB_ABS_FILE_PATHS = "KB_ABS_FILE_PATHS"
KB_CHARS = "KB_CHARS"
KB_BRUTE_TABLES = "KB_BRUTE_TABLES"
KB_BRUTE_COLUMNS = "KB_BRUTE_COLUMNS"
DBMS = "DBMS"
CONF_TMP_PATH = "CONF_TMP_PATH"
KB_XP_CMDSHELL_AVAILABLE = "KB_XP_CMDSHELL_AVAILABLE"
KB_INJECTIONS = "KB_INJECTIONS"
KB_ABS_FILE_PATHS = "KB_ABS_FILE_PATHS"
KB_BRUTE_COLUMNS = "KB_BRUTE_COLUMNS"
KB_BRUTE_TABLES = "KB_BRUTE_TABLES"
KB_CHARS = "KB_CHARS"
KB_DYNAMIC_MARKINGS = "KB_DYNAMIC_MARKINGS"
KB_INJECTIONS = "KB_INJECTIONS"
KB_XP_CMDSHELL_AVAILABLE = "KB_XP_CMDSHELL_AVAILABLE"
OS = "OS"
class REDIRECTION:
YES = "Y"

View File

@ -1497,13 +1497,11 @@ def __setKnowledgeBaseAttributes(flushAll=True):
kb.reflectiveMechanism = True
kb.reflectiveCounters = {REFLECTIVE_COUNTER.MISS:0, REFLECTIVE_COUNTER.HIT:0}
kb.responseTimes = []
kb.resumedQueries = {}
kb.resumeValues = True
kb.safeCharEncode = False
kb.singleLogFlags = set()
kb.skipOthersDbms = None
kb.stickyFlag = False
kb.suppressSession = False
kb.suppressResumeInfo = False
kb.technique = None
kb.testMode = False

View File

@ -11,7 +11,7 @@ import re
from lib.core.common import Backend
from lib.core.common import Format
from lib.core.common import dataToSessionFile
from lib.core.common import hashDBWrite
from lib.core.common import intersect
from lib.core.common import readInput
from lib.core.common import singleTimeWarnMessage
@ -20,42 +20,25 @@ from lib.core.convert import base64unpickle
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
from lib.core.enums import HASHDB_KEYS
from lib.core.enums import OS
from lib.core.settings import SUPPORTED_DBMS
from lib.core.settings import UNKNOWN_DBMS_VERSION
def safeFormatString(value):
retVal = value
if retVal:
retVal = retVal.replace("[", "__LEFT_SQUARE_BRACKET__").replace("]", "__RIGHT_SQUARE_BRACKET__")
return retVal
def unSafeFormatString(value):
retVal = value
if retVal:
retVal = retVal.replace("__LEFT_SQUARE_BRACKET__", "[").replace("__RIGHT_SQUARE_BRACKET__", "]")
return retVal
def setDbms(dbms):
"""
@param dbms: database management system to be set into the knowledge
base as fingerprint.
@type dbms: C{str}
"""
condition = (
not kb.resumedQueries
or ( kb.resumedQueries.has_key(conf.url) and
not kb.resumedQueries[conf.url].has_key("DBMS") )
)
if condition:
dataToSessionFile("[%s][%s][%s][DBMS][%s]\n" % (conf.url, kb.injection.place, safeFormatString(conf.parameters[kb.injection.place]), safeFormatString(dbms)))
hashDBWrite(HASHDB_KEYS.DBMS, dbms)
firstRegExp = "(%s)" % ("|".join([alias for alias in SUPPORTED_DBMS]))
dbmsRegExp = re.search("^%s" % firstRegExp, dbms, re.I)
_ = "(%s)" % ("|".join([alias for alias in SUPPORTED_DBMS]))
_ = re.search("^%s" % _, dbms, re.I)
if dbmsRegExp:
dbms = dbmsRegExp.group(1)
if _:
dbms = _.group(1)
Backend.setDbms(dbms)
@ -76,11 +59,6 @@ def setOs():
"""
infoMsg = ""
condition = (
not kb.resumedQueries
or ( kb.resumedQueries.has_key(conf.url) and
not kb.resumedQueries[conf.url].has_key("OS") )
)
if not kb.bannerFp:
return
@ -105,82 +83,4 @@ def setOs():
if infoMsg:
logger.info(infoMsg)
if condition:
dataToSessionFile("[%s][%s][%s][OS][%s]\n" % (conf.url, kb.injection.place, safeFormatString(conf.parameters[kb.injection.place]), Backend.getOs()))
def resumeConfKb(expression, url, value):
if expression == "Dynamic markings" and url == conf.url:
kb.dynamicMarkings = base64unpickle(value[:-1])
infoMsg = "resuming dynamic markings from session file"
logger.info(infoMsg)
elif expression == "DBMS" and url == conf.url:
dbms = unSafeFormatString(value[:-1])
dbms = dbms.lower()
dbmsVersion = [UNKNOWN_DBMS_VERSION]
firstRegExp = "(%s)" % ("|".join([alias for alias in SUPPORTED_DBMS]))
dbmsRegExp = re.search("%s ([\d\.]+)" % firstRegExp, dbms)
if dbmsRegExp:
dbms = dbmsRegExp.group(1)
dbmsVersion = [ dbmsRegExp.group(2) ]
if conf.dbms and conf.dbms.lower() != dbms:
message = "you provided '%s' as back-end DBMS, " % conf.dbms
message += "but from a past scan information on the target URL "
message += "sqlmap assumes the back-end DBMS is %s. " % dbms
message += "Do you really want to force the back-end "
message += "DBMS value? [y/N] "
test = readInput(message, default="N")
if not test or test[0] in ("n", "N"):
conf.dbms = None
Backend.setDbms(dbms)
Backend.setVersionList(dbmsVersion)
else:
infoMsg = "resuming back-end DBMS '%s' " % dbms
infoMsg += "from session file"
logger.info(infoMsg)
Backend.setDbms(dbms)
Backend.setVersionList(dbmsVersion)
elif expression == "OS" and url == conf.url:
os = unSafeFormatString(value[:-1])
if os and os != 'None':
infoMsg = "resuming back-end DBMS operating system '%s' " % os
infoMsg += "from session file"
logger.info(infoMsg)
if conf.os and conf.os.lower() != os.lower():
message = "you provided '%s' as back-end DBMS operating " % conf.os
message += "system, but from a past scan information on the "
message += "target URL sqlmap assumes the back-end DBMS "
message += "operating system is %s. " % os
message += "Do you really want to force the back-end DBMS "
message += "OS value? [y/N] "
test = readInput(message, default="N")
if not test or test[0] in ("n", "N"):
conf.os = os
else:
conf.os = os
Backend.setOs(conf.os)
elif expression == "Remote temp path" and url == conf.url and conf.tmpPath is None:
conf.tmpPath = unSafeFormatString(value[:-1])
infoMsg = "resuming remote absolute path of temporary "
infoMsg += "files directory '%s' from session file" % conf.tmpPath
logger.info(infoMsg)
elif conf.freshQueries:
pass
elif expression == "xp_cmdshell availability" and url == conf.url:
kb.xpCmdshellAvailable = True if unSafeFormatString(value[:-1]).lower() == "true" else False
infoMsg = "resuming xp_cmdshell availability"
logger.info(infoMsg)
hashDBWrite(HASHDB_KEYS.OS, Backend.getOs())

View File

@ -14,7 +14,7 @@ import re
import tempfile
import time
from lib.core.common import dataToSessionFile
from lib.core.common import Backend
from lib.core.common import hashDBRetrieve
from lib.core.common import intersect
from lib.core.common import paramToDict
@ -37,14 +37,15 @@ from lib.core.exception import sqlmapUserQuitException
from lib.core.option import authHandler
from lib.core.option import __setDBMS
from lib.core.option import __setKnowledgeBaseAttributes
from lib.core.session import resumeConfKb
from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR
from lib.core.settings import HOST_ALIASES
from lib.core.settings import REFERER_ALIASES
from lib.core.settings import RESULTS_FILE_FORMAT
from lib.core.settings import SOAP_REGEX
from lib.core.settings import SUPPORTED_DBMS
from lib.core.settings import UNENCODED_ORIGINAL_VALUE
from lib.core.settings import UNICODE_ENCODING
from lib.core.settings import UNKNOWN_DBMS_VERSION
from lib.core.settings import URI_INJECTABLE_REGEX
from lib.core.settings import USER_AGENT_ALIASES
from lib.utils.hashdb import HashDB
@ -243,78 +244,79 @@ def __resumeHashDBValues():
if injection not in kb.injections:
kb.injections.append(injection)
def __setOutputResume():
__resumeDBMS()
__resumeOS()
def __resumeDBMS():
"""
Check and set the output text file and the resume functionality.
Resume stored DBMS information from HashDB
"""
if not conf.sessionFile:
conf.sessionFile = "%s%ssession" % (conf.outputPath, os.sep)
value = hashDBRetrieve(HASHDB_KEYS.DBMS)
logger.info("using '%s' as a session file" % conf.sessionFile)
if not value:
return
if os.path.exists(conf.sessionFile):
if not conf.flushSession:
try:
readSessionFP = codecs.open(conf.sessionFile, "r", UNICODE_ENCODING, 'replace')
__url_cache = set()
__expression_cache = {}
dbms = value.lower()
dbmsVersion = [UNKNOWN_DBMS_VERSION]
_ = "(%s)" % ("|".join([alias for alias in SUPPORTED_DBMS]))
_ = re.search("%s ([\d\.]+)" % _, dbms, re.I)
for line in readSessionFP.readlines(): # xreadlines doesn't return unicode strings when codec.open() is used
if line.count("][") == 4:
line = line.split("][")
if _:
dbms = _.group(1).lower()
dbmsVersion = [_.group(2)]
if len(line) != 5:
continue
if conf.dbms:
if conf.dbms.lower() != dbms:
message = "you provided '%s' as back-end DBMS, " % conf.dbms
message += "but from a past scan information on the target URL "
message += "sqlmap assumes the back-end DBMS is %s. " % dbms
message += "Do you really want to force the back-end "
message += "DBMS value? [y/N] "
test = readInput(message, default="N")
url, _, _, expression, value = line
if not test or test[0] in ("n", "N"):
conf.dbms = None
Backend.setDbms(dbms)
Backend.setVersionList(dbmsVersion)
else:
infoMsg = "resuming back-end DBMS '%s' " % dbms
logger.info(infoMsg)
if not value:
continue
Backend.setDbms(dbms)
Backend.setVersionList(dbmsVersion)
if url[0] == "[":
url = url[1:]
def __resumeOS():
"""
Resume stored OS information from HashDB
"""
value = value.rstrip('\r\n') # Strips both chars independently
value = hashDBRetrieve(HASHDB_KEYS.OS)
if url not in ( conf.url, conf.hostname ):
continue
if not value:
return
if url not in __url_cache:
kb.resumedQueries[url] = {}
kb.resumedQueries[url][expression] = value
__url_cache.add(url)
__expression_cache[url] = set(expression)
os = value
resumeConfKb(expression, url, value)
if os and os != 'None':
infoMsg = "resuming back-end DBMS operating system '%s' " % os
logger.info(infoMsg)
if expression not in __expression_cache[url]:
kb.resumedQueries[url][expression] = value
__expression_cache[url].add(value)
elif len(value) >= len(kb.resumedQueries[url][expression]):
kb.resumedQueries[url][expression] = value
if conf.os and conf.os.lower() != os.lower():
message = "you provided '%s' as back-end DBMS operating " % conf.os
message += "system, but from a past scan information on the "
message += "target URL sqlmap assumes the back-end DBMS "
message += "operating system is %s. " % os
message += "Do you really want to force the back-end DBMS "
message += "OS value? [y/N] "
test = readInput(message, default="N")
if kb.injection.place is not None and kb.injection.parameter is not None:
kb.injections.append(kb.injection)
except IOError, msg:
errMsg = "unable to properly open the session file (%s)" % msg
raise sqlmapFilePathException, errMsg
else:
readSessionFP.close()
if not test or test[0] in ("n", "N"):
conf.os = os
else:
try:
os.remove(conf.sessionFile)
logger.info("flushing session file")
except OSError, msg:
errMsg = "unable to flush the session file (%s)" % msg
raise sqlmapFilePathException, errMsg
conf.os = os
try:
conf.sessionFP = codecs.open(conf.sessionFile, "a", UNICODE_ENCODING)
dataToSessionFile("\n[%s]\n" % time.strftime("%X %x"))
except IOError:
errMsg = "unable to write on the session file specified"
raise sqlmapFilePathException, errMsg
Backend.setOs(conf.os)
def __setResultsFile():
"""
@ -435,7 +437,6 @@ def initTargetEnv():
conf.paramDict = {}
conf.parameters = {}
conf.sessionFile = None
conf.hashDBFile = None
__setKnowledgeBaseAttributes(False)
@ -445,7 +446,6 @@ def initTargetEnv():
def setupTargetEnv():
__createTargetDirs()
__setRequestParams()
__setOutputResume()
__setHashDB()
__resumeHashDBValues()
__setResultsFile()

View File

@ -126,7 +126,6 @@ def liveTest():
name = None
log = []
session = []
switches = dict(global_)
if case.hasAttribute("name"):
@ -143,14 +142,9 @@ def liveTest():
if item.hasAttribute("value"):
log.append(replaceVars(item.getAttribute("value"), vars_))
if case.getElementsByTagName("session"):
for item in case.getElementsByTagName("session")[0].getElementsByTagName("item"):
if item.hasAttribute("value"):
session.append(replaceVars(item.getAttribute("value"), vars_))
msg = "running live test case '%s' (%d/%d)" % (name, count, length)
logger.info(msg)
result = runCase(switches, log, session)
result = runCase(switches, log)
if result:
logger.info("test passed")
else:
@ -178,7 +172,6 @@ def initCase(switches=None):
if key in cmdLineOptions.__dict__:
cmdLineOptions.__dict__[key] = value
conf.sessionFile = None
init(cmdLineOptions, True)
__setVerbosity()
@ -190,7 +183,7 @@ def cleanCase():
conf.verbose = 1
__setVerbosity()
def runCase(switches=None, log=None, session=None):
def runCase(switches=None, log=None):
retVal = True
initCase(switches)
@ -198,19 +191,6 @@ def runCase(switches=None, log=None, session=None):
if result == False: #if None ignore
retVal = False
if session and retVal:
ifile = open(conf.sessionFile, 'r')
content = ifile.read()
ifile.close()
for item in session:
if item.startswith("r'") and item.endswith("'"):
if not re.search(item[2:-1], content, re.DOTALL):
retVal = False
break
elif content.find(item) < 0:
retVal = False
break
if log and retVal:
ifile = open(conf.dumper.getOutputFile(), 'r')
content = ifile.read()

View File

@ -50,12 +50,11 @@ from lib.core.unescaper import unescaper
from lib.request.connect import Connect as Request
from lib.request.direct import direct
from lib.techniques.blind.inference import bisection
from lib.techniques.blind.inference import queryOutputLength
from lib.techniques.dns.test import dnsTest
from lib.techniques.dns.use import dnsUse
from lib.techniques.error.use import errorUse
from lib.techniques.union.use import unionUse
from lib.utils.resume import queryOutputLength
from lib.utils.resume import resume
def __goInference(payload, expression, charsetType=None, firstChar=None, lastChar=None, dump=False):
start = time.time()
@ -488,8 +487,4 @@ def goStacked(expression, silent=False):
Request.queryPage(payload, content=False, silent=silent, noteResponseTime=False, timeBasedCompare=True)
def checkBooleanExpression(expression, expectingNone=True):
kb.suppressSession = True
value = getValue(unescaper.unescape(expression), expected=EXPECTED.BOOL, suppressOutput=True, expectingNone=expectingNone)
kb.suppressSession = False
return value
return getValue(unescaper.unescape(expression), expected=EXPECTED.BOOL, suppressOutput=True, expectingNone=expectingNone)

View File

@ -7,12 +7,14 @@ Copyright (c) 2006-2012 sqlmap developers (http://www.sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
import re
import threading
import time
from extra.safe2bin.safe2bin import safecharencode
from lib.core.agent import agent
from lib.core.common import Backend
from lib.core.common import calculateDeltaSeconds
from lib.core.common import dataToStdout
from lib.core.common import decodeHexValue
from lib.core.common import decodeIntToUnicode
@ -24,6 +26,7 @@ from lib.core.common import getPartRun
from lib.core.common import hashDBRetrieve
from lib.core.common import hashDBWrite
from lib.core.common import incrementCounter
from lib.core.common import randomStr
from lib.core.common import safeStringFormat
from lib.core.common import setFormatterPrependFlag
from lib.core.common import singleTimeWarnMessage
@ -31,6 +34,7 @@ from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
from lib.core.data import queries
from lib.core.enums import CHARSET_TYPE
from lib.core.enums import DBMS
from lib.core.enums import PAYLOAD
from lib.core.exception import sqlmapThreadException
@ -546,3 +550,56 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
_ = finalValue or partialValue
return getCounter(kb.technique), safecharencode(_) if kb.safeCharEncode else _
def queryOutputLength(expression, payload):
"""
Returns the query output length.
"""
lengthQuery = queries[Backend.getIdentifiedDbms()].length.query
select = re.search("\ASELECT\s+", expression, re.I)
selectTopExpr = re.search("\ASELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM", expression, re.I)
selectDistinctExpr = re.search("\ASELECT\s+DISTINCT\((.+?)\)\s+FROM", expression, re.I)
selectFromExpr = re.search("\ASELECT\s+(.+?)\s+FROM", expression, re.I)
selectExpr = re.search("\ASELECT\s+(.+)$", expression, re.I)
miscExpr = re.search("\A(.+)", expression, re.I)
if selectTopExpr or selectDistinctExpr or selectFromExpr or selectExpr:
if selectTopExpr:
regExpr = selectTopExpr.groups()[0]
elif selectDistinctExpr:
regExpr = selectDistinctExpr.groups()[0]
elif selectFromExpr:
regExpr = selectFromExpr.groups()[0]
elif selectExpr:
regExpr = selectExpr.groups()[0]
elif miscExpr:
regExpr = miscExpr.groups()[0]
if ( select and re.search("\A(COUNT|LTRIM)\(", regExpr, re.I) ) or len(regExpr) <= 1:
return None, None, None
if selectDistinctExpr:
lengthExpr = "SELECT %s FROM (%s)" % (lengthQuery % regExpr, expression)
if Backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
lengthExpr += " AS %s" % randomStr(lowercase=True)
elif select:
lengthExpr = expression.replace(regExpr, lengthQuery % regExpr, 1)
else:
lengthExpr = lengthQuery % expression
infoMsg = "retrieving the length of query output"
logger.info(infoMsg)
start = time.time()
lengthExprUnescaped = unescaper.unescape(lengthExpr)
count, length = bisection(payload, lengthExprUnescaped, charsetType=CHARSET_TYPE.DIGITS)
debugMsg = "performed %d queries in %d seconds" % (count, calculateDeltaSeconds(start))
logger.debug(debugMsg)
if length == " ":
length = 0
return count, length, regExpr

View File

@ -1,188 +0,0 @@
#!/usr/bin/env python
"""
$Id$
Copyright (c) 2006-2012 sqlmap developers (http://www.sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
import re
import time
from lib.core.common import calculateDeltaSeconds
from lib.core.common import dataToSessionFile
from lib.core.common import dataToStdout
from lib.core.common import Backend
from lib.core.common import safeStringFormat
from lib.core.common import randomStr
from lib.core.common import replaceNewlineTabs
from lib.core.common import restoreDumpMarkedChars
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
from lib.core.data import queries
from lib.core.enums import DBMS
from lib.core.enums import CHARSET_TYPE
from lib.core.unescaper import unescaper
from lib.techniques.blind.inference import bisection
def queryOutputLength(expression, payload):
"""
Returns the query output length.
"""
lengthQuery = queries[Backend.getIdentifiedDbms()].length.query
select = re.search("\ASELECT\s+", expression, re.I)
selectTopExpr = re.search("\ASELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM", expression, re.I)
selectDistinctExpr = re.search("\ASELECT\s+DISTINCT\((.+?)\)\s+FROM", expression, re.I)
selectFromExpr = re.search("\ASELECT\s+(.+?)\s+FROM", expression, re.I)
selectExpr = re.search("\ASELECT\s+(.+)$", expression, re.I)
miscExpr = re.search("\A(.+)", expression, re.I)
if selectTopExpr or selectDistinctExpr or selectFromExpr or selectExpr:
if selectTopExpr:
regExpr = selectTopExpr.groups()[0]
elif selectDistinctExpr:
regExpr = selectDistinctExpr.groups()[0]
elif selectFromExpr:
regExpr = selectFromExpr.groups()[0]
elif selectExpr:
regExpr = selectExpr.groups()[0]
elif miscExpr:
regExpr = miscExpr.groups()[0]
if ( select and re.search("\A(COUNT|LTRIM)\(", regExpr, re.I) ) or len(regExpr) <= 1:
return None, None, None
if selectDistinctExpr:
lengthExpr = "SELECT %s FROM (%s)" % (lengthQuery % regExpr, expression)
if Backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
lengthExpr += " AS %s" % randomStr(lowercase=True)
elif select:
lengthExpr = expression.replace(regExpr, lengthQuery % regExpr, 1)
else:
lengthExpr = lengthQuery % expression
infoMsg = "retrieving the length of query output"
logger.info(infoMsg)
start = time.time()
lengthExprUnescaped = unescaper.unescape(lengthExpr)
count, length = bisection(payload, lengthExprUnescaped, charsetType=CHARSET_TYPE.DIGITS)
debugMsg = "performed %d queries in %d seconds" % (count, calculateDeltaSeconds(start))
logger.debug(debugMsg)
if length == " ":
length = 0
return count, length, regExpr
def resume(expression, payload):
"""
This function can be called to resume part or entire output of a
SQL injection query output.
"""
try:
if "sqlmapfile" in expression or "sqlmapoutput" in expression or conf.freshQueries:
return None
condition = (
kb.resumedQueries and conf.url in kb.resumedQueries
and expression in kb.resumedQueries[conf.url]
)
if not condition:
return None
resumedValue = kb.resumedQueries[conf.url][expression]
if not resumedValue:
return None
resumedValue = restoreDumpMarkedChars(resumedValue, True)
if resumedValue[-1] == "]":
resumedValue = resumedValue[:-1]
infoMsg = "read from file '%s': " % conf.sessionFile
if "\n" in resumedValue:
infoMsg += "%s..." % resumedValue.split("\n")[0]
else:
infoMsg += resumedValue
if not kb.suppressResumeInfo:
dataToStdout("[%s] [INFO] %s\n" % (time.strftime("%X"), infoMsg))
return resumedValue
# If we called this function without providing a payload it means
# that we have called it from lib/request/inject __goInband() or
# from __goError() function so we return to the calling function
# so that the query output will be retrieved taking advantage
# of either error-based or inband SQL injection vulnerability.
if not payload:
return None
if not Backend.getIdentifiedDbms():
return None
substringQuery = queries[Backend.getIdentifiedDbms()].substring.query
select = re.search("\ASELECT ", expression, re.I)
_, length, regExpr = queryOutputLength(expression, payload)
if not length:
return None
if len(resumedValue) == int(length):
infoMsg = "read from file '%s': " % conf.sessionFile
infoMsg += "%s" % resumedValue.split("\n")[0]
logger.info(infoMsg)
dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.url, kb.injection.place, conf.parameters[kb.injection.place], expression, replaceNewlineTabs(resumedValue)))
return resumedValue
elif len(resumedValue) < int(length):
infoMsg = "resumed from file '%s': " % conf.sessionFile
infoMsg += "%s..." % resumedValue.split("\n")[0]
logger.info(infoMsg)
dataToSessionFile("[%s][%s][%s][%s][%s" % (conf.url, kb.injection.place, conf.parameters[kb.injection.place], expression, replaceNewlineTabs(resumedValue)))
if select:
newExpr = expression.replace(regExpr, safeStringFormat(substringQuery, (regExpr, len(resumedValue) + 1, int(length))), 1)
else:
newExpr = safeStringFormat(substringQuery, (expression, len(resumedValue) + 1, int(length)))
missingCharsLength = int(length) - len(resumedValue)
infoMsg = "retrieving pending %d query " % missingCharsLength
infoMsg += "output characters"
logger.info(infoMsg)
start = time.time()
count, finalValue = bisection(payload, newExpr, length=missingCharsLength)
debugMsg = "performed %d queries in %d seconds" % (count, calculateDeltaSeconds(start))
logger.debug(debugMsg)
if len(finalValue) != ( int(length) - len(resumedValue) ):
warnMsg = "the total length of the query is not "
warnMsg += "right, sqlmap is going to retrieve the "
warnMsg += "query value from the beginning now"
logger.warn(warnMsg)
return None
return "%s%s" % (resumedValue, finalValue)
return None
except ValueError:
errMsg = "invalid resume value for expression: '%s'" % expression
logger.error(errMsg)
return None