Implementation for an Issue #674

This commit is contained in:
Miroslav Stampar 2014-07-02 22:27:51 +02:00
parent 1eecabaea8
commit e6d0d5a1c7
5 changed files with 54 additions and 11 deletions

View File

@ -135,6 +135,7 @@ from lib.core.threads import getCurrentThreadData
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.parse.payloads import loadPayloads
from lib.parse.sitemap import parseSitemap
from lib.request.basic import checkCharEncoding from lib.request.basic import checkCharEncoding
from lib.request.connect import Connect as Request from lib.request.connect import Connect as Request
from lib.request.dns import DNSServer from lib.request.dns import DNSServer
@ -504,10 +505,13 @@ def _setCrawler():
if not conf.crawlDepth: if not conf.crawlDepth:
return return
if not conf.bulkFile: if not any((conf.bulkFile, conf.sitemapUrl)):
crawl(conf.url) crawl(conf.url)
else: else:
if conf.bulkFile:
targets = getFileItems(conf.bulkFile) targets = getFileItems(conf.bulkFile)
else:
targets = parseSitemap(conf.sitemapUrl)
for i in xrange(len(targets)): for i in xrange(len(targets)):
try: try:
target = targets[i] target = targets[i]
@ -618,10 +622,33 @@ def _setBulkMultipleTargets():
errMsg += "does not exist" errMsg += "does not exist"
raise SqlmapFilePathException(errMsg) raise SqlmapFilePathException(errMsg)
found = False
for line in getFileItems(conf.bulkFile): for line in getFileItems(conf.bulkFile):
if re.match(r"[^ ]+\?(.+)", line, re.I) or CUSTOM_INJECTION_MARK_CHAR in line: if re.match(r"[^ ]+\?(.+)", line, re.I) or CUSTOM_INJECTION_MARK_CHAR in line:
found = True
kb.targets.add((line.strip(), None, None, None)) kb.targets.add((line.strip(), None, None, None))
if not found and not conf.forms and not conf.crawlDepth:
warnMsg = "no usable links found (with GET parameters)"
logger.warn(warnMsg)
def _setSitemapTargets():
if not conf.sitemapUrl:
return
infoMsg = "parsing sitemap '%s'" % conf.sitemapUrl
logger.info(infoMsg)
found = False
for item in parseSitemap(conf.sitemapUrl):
if re.match(r"[^ ]+\?(.+)", item, re.I):
found = True
kb.targets.add((item.strip(), None, None, None))
if not found and not conf.forms and not conf.crawlDepth:
warnMsg = "no usable links found (with GET parameters)"
logger.warn(warnMsg)
def _findPageForms(): def _findPageForms():
if not conf.forms or conf.crawlDepth: if not conf.forms or conf.crawlDepth:
return return
@ -632,11 +659,14 @@ def _findPageForms():
infoMsg = "searching for forms" infoMsg = "searching for forms"
logger.info(infoMsg) logger.info(infoMsg)
if not conf.bulkFile: if not any((conf.bulkFile, conf.sitemapUrl)):
page, _ = Request.queryPage(content=True) page, _ = Request.queryPage(content=True)
findPageForms(page, conf.url, True, True) findPageForms(page, conf.url, True, True)
else: else:
if conf.bulkFile:
targets = getFileItems(conf.bulkFile) targets = getFileItems(conf.bulkFile)
else:
targets = parseSitemap(conf.sitemapUrl)
for i in xrange(len(targets)): for i in xrange(len(targets)):
try: try:
target = targets[i] target = targets[i]
@ -1449,13 +1479,16 @@ def _cleanupOptions():
if conf.dFile: if conf.dFile:
conf.dFile = ntToPosixSlashes(normalizePath(conf.dFile)) conf.dFile = ntToPosixSlashes(normalizePath(conf.dFile))
if conf.sitemapUrl and not conf.sitemapUrl.lower().startswith("http"):
conf.sitemapUrl = "http%s://%s" % ('s' if conf.forceSSL else '', conf.sitemapUrl)
if conf.msfPath: if conf.msfPath:
conf.msfPath = ntToPosixSlashes(normalizePath(conf.msfPath)) conf.msfPath = ntToPosixSlashes(normalizePath(conf.msfPath))
if conf.tmpPath: if conf.tmpPath:
conf.tmpPath = ntToPosixSlashes(normalizePath(conf.tmpPath)) conf.tmpPath = ntToPosixSlashes(normalizePath(conf.tmpPath))
if conf.googleDork or conf.logFile or conf.bulkFile or conf.forms or conf.crawlDepth: if any((conf.googleDork, conf.logFile, conf.bulkFile, conf.sitemapUrl, conf.forms, conf.crawlDepth)):
conf.multipleTargets = True conf.multipleTargets = True
if conf.optimize: if conf.optimize:
@ -1631,6 +1664,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
kb.extendTests = None kb.extendTests = None
kb.errorIsNone = True kb.errorIsNone = True
kb.fileReadMode = False kb.fileReadMode = False
kb.followSitemapRecursion = None
kb.forcedDbms = None kb.forcedDbms = None
kb.forcePartialUnion = False kb.forcePartialUnion = False
kb.headersFp = {} kb.headersFp = {}
@ -2130,8 +2164,8 @@ def _basicOptionValidation():
errMsg = "maximum number of used threads is %d avoiding potential connection issues" % MAX_NUMBER_OF_THREADS errMsg = "maximum number of used threads is %d avoiding potential connection issues" % MAX_NUMBER_OF_THREADS
raise SqlmapSyntaxException(errMsg) raise SqlmapSyntaxException(errMsg)
if conf.forms and not any((conf.url, conf.bulkFile)): if conf.forms and not any((conf.url, conf.bulkFile, conf.sitemapUrl)):
errMsg = "switch '--forms' requires usage of option '-u' ('--url') or '-m'" errMsg = "switch '--forms' requires usage of option '-u' ('--url'), '-m' or '-x'"
raise SqlmapSyntaxException(errMsg) raise SqlmapSyntaxException(errMsg)
if conf.requestFile and conf.url and conf.url != DUMMY_URL: if conf.requestFile and conf.url and conf.url != DUMMY_URL:
@ -2266,7 +2300,7 @@ def init():
parseTargetUrl() parseTargetUrl()
parseTargetDirect() parseTargetDirect()
if any((conf.url, conf.logFile, conf.bulkFile, conf.requestFile, conf.googleDork, conf.liveTest)): if any((conf.url, conf.logFile, conf.bulkFile, conf.sitemapUrl, conf.requestFile, conf.googleDork, conf.liveTest)):
_setHTTPTimeout() _setHTTPTimeout()
_setHTTPExtraHeaders() _setHTTPExtraHeaders()
_setHTTPCookies() _setHTTPCookies()
@ -2279,6 +2313,7 @@ def init():
_setSafeUrl() _setSafeUrl()
_setGoogleDorking() _setGoogleDorking()
_setBulkMultipleTargets() _setBulkMultipleTargets()
_setSitemapTargets()
_urllib2Opener() _urllib2Opener()
_checkTor() _checkTor()
_setCrawler() _setCrawler()

View File

@ -19,6 +19,7 @@ optDict = {
"sessionFile": "string", "sessionFile": "string",
"googleDork": "string", "googleDork": "string",
"configFile": "string", "configFile": "string",
"sitemapUrl": "string",
}, },
"Request": { "Request": {

View File

@ -75,6 +75,8 @@ def cmdLineParser():
target.add_option("-c", dest="configFile", target.add_option("-c", dest="configFile",
help="Load options from a configuration INI file") help="Load options from a configuration INI file")
target.add_option("-x", dest="sitemapUrl", help="Load target URLs from remote sitemap(.xml) file")
# Request options # Request options
request = OptionGroup(parser, "Request", "These options can be used " request = OptionGroup(parser, "Request", "These options can be used "
"to specify how to connect to the target URL") "to specify how to connect to the target URL")
@ -807,8 +809,8 @@ def cmdLineParser():
if not any((args.direct, args.url, args.logFile, args.bulkFile, args.googleDork, args.configFile, \ if not any((args.direct, args.url, args.logFile, args.bulkFile, args.googleDork, args.configFile, \
args.requestFile, args.updateAll, args.smokeTest, args.liveTest, args.wizard, args.dependencies, \ args.requestFile, args.updateAll, args.smokeTest, args.liveTest, args.wizard, args.dependencies, \
args.purgeOutput, args.pickledOptions)): args.purgeOutput, args.pickledOptions, args.sitemapUrl)):
errMsg = "missing a mandatory option (-d, -u, -l, -m, -r, -g, -c, --wizard, --update, --purge-output or --dependencies), " errMsg = "missing a mandatory option (-d, -u, -l, -m, -r, -g, -c, -x, --wizard, --update, --purge-output or --dependencies), "
errMsg += "use -h for basic or -hh for advanced help" errMsg += "use -h for basic or -hh for advanced help"
parser.error(errMsg) parser.error(errMsg)

View File

@ -84,11 +84,12 @@ def configFileParser(configFile):
condition &= not config.has_option("Target", "bulkFile") condition &= not config.has_option("Target", "bulkFile")
condition &= not config.has_option("Target", "googleDork") condition &= not config.has_option("Target", "googleDork")
condition &= not config.has_option("Target", "requestFile") condition &= not config.has_option("Target", "requestFile")
condition &= not config.has_option("Target", "sitemapUrl")
condition &= not config.has_option("Target", "wizard") condition &= not config.has_option("Target", "wizard")
if condition: if condition:
errMsg = "missing a mandatory option in the configuration file " errMsg = "missing a mandatory option in the configuration file "
errMsg += "(direct, url, logFile, bulkFile, googleDork, requestFile or wizard)" errMsg += "(direct, url, logFile, bulkFile, googleDork, requestFile, sitemapUrl or wizard)"
raise SqlmapMissingMandatoryOptionException(errMsg) raise SqlmapMissingMandatoryOptionException(errMsg)
for family, optionData in optDict.items(): for family, optionData in optDict.items():

View File

@ -32,6 +32,10 @@ requestFile =
# Example: +ext:php +inurl:"&id=" +intext:"powered by " # Example: +ext:php +inurl:"&id=" +intext:"powered by "
googleDork = googleDork =
# Load target URLs from remote sitemap(.xml) file
# Example: http://192.168.1.121/sitemap.xml
sitemapUrl =
# These options can be used to specify how to connect to the target URL. # These options can be used to specify how to connect to the target URL.
[Request] [Request]