diff --git a/lib/controller/checks.py b/lib/controller/checks.py index acd93762d..db0a64fbb 100644 --- a/lib/controller/checks.py +++ b/lib/controller/checks.py @@ -308,7 +308,7 @@ def checkConnection(): try: kb.defaultResult = Request.queryPage() except sqlmapConnectionException, exceptionMsg: - if conf.googleDork: + if conf.multipleTargets: exceptionMsg += ", skipping to next url" logger.warn(exceptionMsg) return False diff --git a/lib/controller/controller.py b/lib/controller/controller.py index a5635d0fb..dfcd9aca1 100644 --- a/lib/controller/controller.py +++ b/lib/controller/controller.py @@ -92,11 +92,11 @@ def start(): """ if conf.url: - kb.targetUrls.add(conf.url) + kb.targetUrls[conf.url] = None if conf.configFile and not kb.targetUrls: errMsg = "you did not edit the configuration file properly, set " - errMsg += "the target url" + errMsg += "the target url, list of targets or google dork" logger.error(errMsg) hostCount = 0 @@ -105,15 +105,17 @@ def start(): cookieStr = "" setCookieAsInjectable = True - for targetUrl in kb.targetUrls: - if conf.googleDork: + for targetUrl, _ in kb.targetUrls.items(): + if conf.multipleTargets: hostCount += 1 message = "url %d: %s, " % (hostCount, targetUrl) message += "do you want to test this url? [Y/n/q] " test = readInput(message, default="Y") - if test[0] in ("n", "N"): + if not test: + pass + elif test[0] in ("n", "N"): continue elif test[0] in ("q", "Q"): break @@ -166,7 +168,7 @@ def start(): errMsg += "to the user's manual paragraph 'String match' " errMsg += "for details" - if conf.googleDork: + if conf.multipleTargets: errMsg += ", skipping to next url" logger.warn(errMsg) @@ -219,12 +221,12 @@ def start(): kb.injPlace, kb.injParameter, kb.injType = injDataSelected setInjection() - if not conf.googleDork and ( not kb.injPlace or not kb.injParameter or not kb.injType ): + if not conf.multipleTargets and ( not kb.injPlace or not kb.injParameter or not kb.injType ): raise sqlmapNotVulnerableException, "all parameters are not injectable" elif kb.injPlace and kb.injParameter and kb.injType: condition = False - if conf.googleDork: + if conf.multipleTargets: message = "do you want to exploit this SQL injection? [Y/n] " exploit = readInput(message, default="Y") diff --git a/lib/core/common.py b/lib/core/common.py index 0744484f8..1d6f75edf 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -97,7 +97,7 @@ def paramToDict(place, parameters=None): warnMsg = "the testable parameter '%s' " % paramStr warnMsg += "you provided is not into the %s" % place - if conf.googleDork: + if conf.multipleTargets: warnMsg += ", skipping to next url" logger.warn(warnMsg) diff --git a/lib/core/dump.py b/lib/core/dump.py index d36734d98..3316f84a4 100644 --- a/lib/core/dump.py +++ b/lib/core/dump.py @@ -219,7 +219,7 @@ class Dump: db = "All" table = tableValues["__infos__"]["table"] - if not conf.googleDork: + if not conf.multipleTargets: dumpDbPath = "%s%s%s" % (conf.dumpPath, os.sep, db) if not os.path.isdir(dumpDbPath): @@ -259,7 +259,7 @@ class Dump: blank = " " * (maxlength - len(column)) self.__write("| %s%s" % (column, blank), n=False) - if not conf.googleDork and field == fields: + if not conf.multipleTargets and field == fields: dataToDumpFile(dumpFP, "\"%s\"" % column) else: dataToDumpFile(dumpFP, "\"%s\"," % column) @@ -267,7 +267,7 @@ class Dump: field += 1 self.__write("|\n%s" % separator) - if not conf.googleDork: + if not conf.multipleTargets: dataToDumpFile(dumpFP, "\n") for i in range(count): @@ -293,12 +293,12 @@ class Dump: field += 1 self.__write("|") - if not conf.googleDork: + if not conf.multipleTargets: dataToDumpFile(dumpFP, "\n") self.__write("%s\n" % separator) - if not conf.googleDork: + if not conf.multipleTargets: dataToDumpFile(dumpFP, "\n") dumpFP.close() diff --git a/lib/core/option.py b/lib/core/option.py index 44114cd3f..351ad9cc7 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -129,6 +129,48 @@ def __setGoogleDorking(): raise sqlmapGenericException, errMsg +def __feedTargetsDict(reqFile): + pass + #kb.targetUrls = googleObj.getTargetUrls() + #conf.data + #conf.cookie + + +def __setMultipleTargets(): + """ + Define a configuration parameter if we are running in multiple target + mode. + """ + + listType = None + + if conf.googleDork or conf.list: + conf.multipleTargets = True + + if not conf.list: + return + + if not os.path.exists(conf.list): + errMsg = "the specified list of target urls does not exist" + raise sqlmapFilePathException, errMsg + + if os.path.isfile(conf.list): + __feedTargetsDict(conf.list) + elif os.path.isdir(conf.list): + files = os.listdir(conf.list) + files.sort() + + for reqFile in files: + if not re.search("([\d]+)\-request", reqFile): + continue + + __feedTargetsDict(reqFile) + else: + errMsg = "the specified list of target urls is not a file " + errMsg += "nor a directory" + raise sqlmapFilePathException, errMsg + + def __setRemoteDBMS(): """ Checks and set the back-end DBMS option. @@ -422,20 +464,21 @@ def __setConfAttributes(): debugMsg = "initializing the configuration" logger.debug(debugMsg) - conf.cj = None - conf.dbmsHandler = None - conf.dumpPath = None - conf.httpHeaders = [] - conf.hostname = None - conf.loggedToOut = None - conf.outputPath = None - conf.paramDict = {} - conf.parameters = {} - conf.path = None - conf.port = None - conf.scheme = None - conf.sessionFP = None - conf.start = True + conf.cj = None + conf.dbmsHandler = None + conf.dumpPath = None + conf.httpHeaders = [] + conf.hostname = None + conf.loggedToOut = None + conf.multipleTargets = False + conf.outputPath = None + conf.paramDict = {} + conf.parameters = {} + conf.path = None + conf.port = None + conf.scheme = None + conf.sessionFP = None + conf.start = True def __setKnowledgeBaseAttributes(): @@ -462,7 +505,7 @@ def __setKnowledgeBaseAttributes(): kb.injType = None kb.parenthesis = None kb.resumedQueries = {} - kb.targetUrls = set() + kb.targetUrls = {} kb.timeTest = None kb.unionComment = "" kb.unionCount = None @@ -582,6 +625,7 @@ def init(inputOptions=advancedDict()): __setHTTPProxy() __setThreads() __setRemoteDBMS() + __setMultipleTargets() __setGoogleDorking() __urllib2Opener() diff --git a/lib/core/optiondict.py b/lib/core/optiondict.py index 5a97430fe..dfe918d49 100644 --- a/lib/core/optiondict.py +++ b/lib/core/optiondict.py @@ -28,6 +28,7 @@ optDict = { # Family: { "parameter_name": "parameter_datatype", "Request": { "url": "string", + "list": "string", "googleDork": "string", "testParameter": "string", "method": "string", diff --git a/lib/parse/cmdline.py b/lib/parse/cmdline.py index 24b4120c7..34468218d 100644 --- a/lib/parse/cmdline.py +++ b/lib/parse/cmdline.py @@ -49,6 +49,8 @@ def cmdLineParser(): request.add_option("-u", "--url", dest="url", help="Target url") + request.add_option("-l", dest="list", help="List of target urls") + request.add_option("-g", dest="googleDork", help="Process Google dork results as target urls") @@ -271,7 +273,7 @@ def cmdLineParser(): (args, _) = parser.parse_args() - if not args.url and not args.googleDork and not args.configFile and not args.updateAll: + if not args.url and not args.list and not args.googleDork and not args.configFile and not args.updateAll: errMsg = "missing a mandatory parameter ('-u', '-g', '-c' or '--update'), " errMsg += "-h for help" parser.error(errMsg) diff --git a/lib/request/connect.py b/lib/request/connect.py index b3c301c22..d26ad95af 100644 --- a/lib/request/connect.py +++ b/lib/request/connect.py @@ -162,7 +162,7 @@ class Connect: except (urllib2.URLError, socket.error), _: warnMsg = "unable to connect to the target url" - if conf.googleDork: + if conf.multipleTargets: warnMsg += ", skipping to next url" logger.warn(warnMsg) @@ -174,7 +174,7 @@ class Connect: except socket.timeout, _: warnMsg = "connection timed out to the target url" - if conf.googleDork: + if conf.multipleTargets: warnMsg += ", skipping to next url" logger.warn(warnMsg) @@ -188,7 +188,7 @@ class Connect: warnMsg += "status code, try to force the HTTP User-Agent " warnMsg += "header with option --user-agent or -a" - if conf.googleDork: + if conf.multipleTargets: warnMsg += ", skipping to next url" logger.warn(warnMsg) diff --git a/lib/utils/google.py b/lib/utils/google.py index 746c7f178..3ef479792 100644 --- a/lib/utils/google.py +++ b/lib/utils/google.py @@ -68,11 +68,15 @@ class Google: your Google dork search results """ - targetUrls = set() + targetUrls = {} + targetUrlsSet = set() for match in self.__matches: if re.search("(.*?)\?(.+)", match, re.I): - targetUrls.add(match) + targetUrlsSet.add(match) + + for targetUrl in targetUrlsSet: + targetUrls[targetUrl] = None return targetUrls diff --git a/sqlmap.conf b/sqlmap.conf index 8dab6a477..21262dde5 100644 --- a/sqlmap.conf +++ b/sqlmap.conf @@ -3,7 +3,7 @@ # Target URL. # Example: http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2 # PHP and MySQL (local) -#url = http://127.0.0.1/sqlmap/mysql/get_int.php?id=1 +url = http://127.0.0.1/sqlmap/mysql/get_int.php?id=1 # PHP and Oracle (local) #url = http://127.0.0.1/sqlmap/oracle/get_int.php?id=1 # PHP and PostgreSQL (local) @@ -18,6 +18,10 @@ #url = http://192.168.192.10/sqlmap/get_int.asp?id=1 # ASP.NET and MySQL (local) #url = http://192.168.192.10/sqlmap/get_int.aspx?id=1 +#url = + +# List of targets +list = # Rather than providing a target url, let Google return target # hosts as result of your Google dork expression. For a list of Google