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