diff --git a/doc/ChangeLog b/doc/ChangeLog index 1ea7867c8..5fcf66cd9 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -3,6 +3,10 @@ sqlmap (0.6.3-1) stable; urgency=low * Major enhancement to support stacked queries when the web application supports it which will be used in the long run by takeover functionality; + * Major enhancement to get list of targets to test from Burp proxy + (http://portswigger.net/suite/) requests log file path or WebScarab + proxy (http://www.owasp.org/index.php/Category:OWASP_WebScarab_Project) + 'conversations/' folder path; * Minor enhancement to test if the injectable parameter is affected by a time based blind SQL injection technique; * Minor enhancement to fingerprint the web server operating system and @@ -28,6 +32,7 @@ sqlmap (0.6.3-1) stable; urgency=low * Minor bug fix to correctly enumerate columns on Microsoft SQL Server; * Minor bug fix to correctly dump table entries when the column is provided; + * Updated documentation. -- Bernardo Damele A. G. Day, X YYY 2008 10:00:00 +0000 @@ -218,14 +223,14 @@ sqlmap (0.4-1) stable; urgency=low the remote DBMS; * Major improvements in union.UnionCheck() and union.UnionUse() functions to make it possible to exploit inband SQL injection also - with database comment characters ('--' and '#') in UNION SELECT + with database comment characters ('--' and '#') in UNION query statements; * Added the possibility to save the output into a file while performing the queries (-o OUTPUTFILE) so it is possible to stop and resume the same query output retrieving in a second time (--resume); * Added support to specify the database table column to enumerate (-C COL); - * Added inband SQL injection (UNION SELECT) support (--union-use); + * Added inband SQL injection (UNION query) support (--union-use); * Complete code refactoring, a lot of minor and some major fixes in libraries, many minor improvements; * Reviewed the directory tree structure; diff --git a/doc/README.html b/doc/README.html index 583ba0679..da2b257be 100644 --- a/doc/README.html +++ b/doc/README.html @@ -8,7 +8,7 @@

sqlmap user's manual

by -Bernardo Damele A. G.

version 0.6.3, DDth of November 2008 +Bernardo Damele A. G.version 0.6.3, DDth of December 2008
This document is the user's manual to use sqlmap. @@ -349,7 +349,7 @@ $ python sqlmap.py -h sqlmap/0.6.3 coded by Bernardo Damele A. G. <bernardo.damele@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com> -Usage: sqlmap.py [options] {-u <URL> | -g <google dork> | -c <config file>} +Usage: sqlmap.py [options] {-u "<URL>" | -g "<google dork>" | -c "<config file>"} Options: --version show program's version number and exit @@ -384,8 +384,8 @@ Options: using the default blind SQL injection technique. --time-test Test for Time based blind SQL injection - --union-test Test for UNION SELECT (inband) SQL injection - --union-use Use the UNION SELECT (inband) SQL injection to + --union-test Test for UNION query (inband) SQL injection + --union-use Use the UNION query (inband) SQL injection to retrieve the queries output. No need to go blind Fingerprint: @@ -487,7 +487,7 @@ headers and level 5 show also HTTP responses page content.

-$ python sqlmap.py -u http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2 -v 1
+$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 1
 
 [hh:mm:01] [INFO] testing connection to the target url
 [hh:mm:01] [INFO] testing if the url is stable, wait a few seconds
@@ -525,7 +525,7 @@ back-end DBMS:    MySQL >= 5.0.0
 

-$ python sqlmap.py -u http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2 -v 2
+$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 2
 
 [hh:mm:34] [DEBUG] initializing the configuration
 [hh:mm:34] [DEBUG] initializing the knowledge base
@@ -548,7 +548,7 @@ $ python sqlmap.py -u http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat
 

-$ python sqlmap.py -u http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2 -v 3
+$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 3
 
 [...]
 [hh:mm:28] [INFO] testing connection to the target url
@@ -575,7 +575,7 @@ Connection: close
 

-$ python sqlmap.py -u http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2 -v 4
+$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 4
 
 [...]
 [hh:mm:32] [INFO] testing connection to the target url
@@ -620,7 +620,7 @@ Content-Type: text/html
 

-$ python sqlmap.py -u http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2 -v 5
+$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 5
 
 [...]
 [hh:mm:23] [INFO] testing connection to the target url
@@ -675,6 +675,13 @@ Content-Type: text/html
 

+

List of targets

+ +

Option: -l

+ +

TODO

+ +

Process Google dork results as target urls

Option: -g

@@ -733,7 +740,7 @@ injection test and inject directly only against the provided parameter(s).

 $ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" -v 1 \
-  -p id
+  -p "id"
 
 [hh:mm:48] [INFO] testing connection to the target url
 [hh:mm:48] [INFO] testing if the url is stable, wait a few seconds
@@ -769,7 +776,7 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&ca
 
 $ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 1 \
-  -p user-agent --user-agent "sqlmap/0.6.3 (http://sqlmap.sourceforge.net)"
+  -p "user-agent" --user-agent "sqlmap/0.6.3 (http://sqlmap.sourceforge.net)"
 
 [hh:mm:40] [WARNING] the testable parameter 'user-agent' you provided is not into the GET
 [hh:mm:40] [INFO] testing connection to the target url
@@ -816,7 +823,7 @@ tested for SQL injection like the GET parameters.

-$ python sqlmap.py -u http://192.168.1.121/sqlmap/oracle/post_int.php --method POST \
+$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/post_int.php" --method POST \
   --data "id=1&cat=2"
 
 [hh:mm:53] [INFO] testing connection to the target url
@@ -1216,7 +1223,7 @@ request. The valid value is a float, for instance 0.5.

TODO

-

Test for UNION SELECT query SQL injection

+

Test for UNION query SQL injection

Option: --union-test

@@ -1266,7 +1273,7 @@ affected by an inband SQL injection. In case this vulnerability is exploitable it is strongly recommended to use it.

-

Use the UNION SELECT query SQL injection

+

Use the UNION query SQL injection

Option: --union-use

diff --git a/doc/README.pdf b/doc/README.pdf index d99406f46..d418440f6 100644 Binary files a/doc/README.pdf and b/doc/README.pdf differ diff --git a/doc/README.sgml b/doc/README.sgml index ee2494a18..818a8586a 100644 --- a/doc/README.sgml +++ b/doc/README.sgml @@ -4,7 +4,7 @@ sqlmap user's manual <author>by <htmlurl url="mailto:bernardo.damele@gmail.com" name="Bernardo Damele A. G."> -<date>version 0.6.3, DDth of November 2008 +<date>version 0.6.3, DDth of December 2008 <abstract> This document is the user's manual to use <htmlurl url="http://sqlmap.sourceforge.net" name="sqlmap">. Check the project <htmlurl url="http://sqlmap.sourceforge.net" name="homepage"> @@ -309,7 +309,7 @@ $ python sqlmap.py -h sqlmap/0.6.3 coded by Bernardo Damele A. G. <bernardo.damele@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com> -Usage: sqlmap.py [options] {-u <URL> | -g <google dork> | -c <config file>} +Usage: sqlmap.py [options] {-u "<URL>" | -g "<google dork>" | -c "<config file>"} Options: --version show program's version number and exit @@ -344,8 +344,8 @@ Options: using the default blind SQL injection technique. --time-test Test for Time based blind SQL injection - --union-test Test for UNION SELECT (inband) SQL injection - --union-use Use the UNION SELECT (inband) SQL injection to + --union-test Test for UNION query (inband) SQL injection + --union-use Use the UNION query (inband) SQL injection to retrieve the queries output. No need to go blind Fingerprint: @@ -446,7 +446,7 @@ headers and level 5 show also HTTP responses page content. Example on a <bf>MySQL 5.0.51</bf> target (verbosity level <bf>1</bf>): <tscreen><verb> -$ python sqlmap.py -u http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2 -v 1 +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 1 [hh:mm:01] [INFO] testing connection to the target url [hh:mm:01] [INFO] testing if the url is stable, wait a few seconds @@ -482,7 +482,7 @@ back-end DBMS: MySQL >= 5.0.0 Example on a <bf>MySQL 5.0.51</bf> target (verbosity level <bf>2</bf>): <tscreen><verb> -$ python sqlmap.py -u http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2 -v 2 +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 2 [hh:mm:34] [DEBUG] initializing the configuration [hh:mm:34] [DEBUG] initializing the knowledge base @@ -503,7 +503,7 @@ $ python sqlmap.py -u http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat Example on a <bf>MySQL 5.0.51</bf> target (verbosity level <bf>3</bf>): <tscreen><verb> -$ python sqlmap.py -u http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2 -v 3 +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 3 [...] [hh:mm:28] [INFO] testing connection to the target url @@ -528,7 +528,7 @@ Connection: close Example on a <bf>MySQL 5.0.51</bf> target (verbosity level <bf>4</bf>): <tscreen><verb> -$ python sqlmap.py -u http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2 -v 4 +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 4 [...] [hh:mm:32] [INFO] testing connection to the target url @@ -571,7 +571,7 @@ Content-Type: text/html Example on a <bf>MySQL 5.0.51</bf> target (verbosity level <bf>5</bf>): <tscreen><verb> -$ python sqlmap.py -u http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2 -v 5 +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 5 [...] [hh:mm:23] [INFO] testing connection to the target url @@ -624,6 +624,15 @@ Content-Type: text/html </verb></tscreen> +<sect2>List of targets + +<p> +Option: <tt>-l</tt> + +<p> +TODO + + <sect2>Process Google dork results as target urls <p> @@ -685,7 +694,7 @@ Example on a <bf>PostgreSQL 8.2.7</bf> target: <tscreen><verb> $ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&cat=2" -v 1 \ - -p id + -p "id" [hh:mm:48] [INFO] testing connection to the target url [hh:mm:48] [INFO] testing if the url is stable, wait a few seconds @@ -718,7 +727,7 @@ Example on a <bf>MySQL 5.0.51</bf> target: <tscreen><verb> $ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2" -v 1 \ - -p user-agent --user-agent "sqlmap/0.6.3 (http://sqlmap.sourceforge.net)" + -p "user-agent" --user-agent "sqlmap/0.6.3 (http://sqlmap.sourceforge.net)" [hh:mm:40] [WARNING] the testable parameter 'user-agent' you provided is not into the GET [hh:mm:40] [INFO] testing connection to the target url @@ -765,7 +774,7 @@ tested for SQL injection like the <tt>GET</tt> parameters. Example on an <bf>Oracle XE 10.2.0.1</bf> target: <tscreen><verb> -$ python sqlmap.py -u http://192.168.1.121/sqlmap/oracle/post_int.php --method POST \ +$ python sqlmap.py -u "http://192.168.1.121/sqlmap/oracle/post_int.php" --method POST \ --data "id=1&cat=2" [hh:mm:53] [INFO] testing connection to the target url @@ -1158,7 +1167,7 @@ Option: <tt>--time-test</tt> TODO -<sect2>Test for UNION SELECT query SQL injection +<sect2>Test for UNION query SQL injection <p> Option: <tt>--union-test</tt> @@ -1207,7 +1216,7 @@ affected by an inband SQL injection. In case this vulnerability is exploitable it is strongly recommended to use it. -<sect2>Use the UNION SELECT query SQL injection +<sect2>Use the UNION query SQL injection <p> Option: <tt>--union-use</tt> diff --git a/doc/THANKS b/doc/THANKS index 7bdb270e7..38474a788 100644 --- a/doc/THANKS +++ b/doc/THANKS @@ -51,8 +51,11 @@ Will Holcomb <wholcomb@gmail.com> Luke Jahnke <luke.jahnke@gmail.com> for reporting a bug when running against MySQL < 5.0 +Anant Kochhar <anant.kochhar@secureyes.net> + for providing me with feedback on the user's manual + Nico Leidecker <nico@leidecker.info> - for providing with feedback on a few features + for providing me with feedback on a few features Pavol Luptak <pavol.luptak@nethemba.com> for reporting a bug when injecting on a POST data parameter @@ -62,6 +65,10 @@ Michael Majchrowicz <mmajchrowicz@gmail.com> for providing really appreciated feedback for suggesting a lot of ideas and features +Ferruh Mavituna <ferruh@mavituna.com> + for providing me with ideas on the implementation on a couple of + new features + Enrico Milanese <enricomilanese@gmail.com> for reporting a bugs when using (-a) a single line User-Agent file for providing me with some ideas for the PHP backdoor diff --git a/lib/controller/controller.py b/lib/controller/controller.py index 7da39b948..bc7ad8e54 100644 --- a/lib/controller/controller.py +++ b/lib/controller/controller.py @@ -92,25 +92,40 @@ def start(): """ if conf.url: - kb.targetUrls[conf.url] = None + kb.targetUrls.add(( conf.url, conf.method, conf.data, conf.cookie )) if conf.configFile and not kb.targetUrls: errMsg = "you did not edit the configuration file properly, set " errMsg += "the target url, list of targets or google dork" logger.error(errMsg) + if kb.targetUrls and len(kb.targetUrls) > 1: + infoMsg = "sqlmap got a total of %d targets" % len(kb.targetUrls) + logger.info(infoMsg) + hostCount = 0 - injData = [] receivedCookies = [] cookieStr = "" setCookieAsInjectable = True - for targetUrl, targetData in kb.targetUrls.items(): + for targetUrl, targetMethod, targetData, targetCookie in kb.targetUrls: + conf.url = targetUrl + conf.method = targetMethod + conf.data = targetData + conf.cookie = targetCookie + injData = [] + if conf.multipleTargets: hostCount += 1 + message = "url %d:\n%s %s" % (hostCount, conf.method, targetUrl) - message = "url %d: %s, " % (hostCount, targetUrl) - message += "do you want to test this url? [Y/n/q] " + if conf.cookie: + message += "\nCookie: %s" % conf.cookie + + if conf.data: + message += "\nPOST data: %s" % conf.data + + message += "\ndo you want to test this url? [Y/n/q] " test = readInput(message, default="Y") if not test: @@ -123,10 +138,6 @@ def start(): logMsg = "testing url %s" % targetUrl logger.info(logMsg) - if targetData: - conf.method, conf.data, conf.cookie = targetData - - conf.url = targetUrl initTargetEnv() if not checkConnection() or not checkString(): @@ -206,9 +217,14 @@ def start(): break else: - warnMsg = "%s parameter '%s' is not " % (place, parameter) - warnMsg += "injectable with %d parenthesis" % parenthesis - logger.warn(warnMsg) + infoMsg = "%s parameter '%s' is not " % (place, parameter) + infoMsg += "injectable with %d parenthesis" % parenthesis + logger.info(infoMsg) + + if not injData: + warnMsg = "%s parameter '%s' is not " % (place, parameter) + warnMsg += "injectable" + logger.warn(warnMsg) if not kb.injPlace or not kb.injParameter or not kb.injType: if len(injData) == 1: @@ -230,6 +246,7 @@ def start(): kb.injPlace, kb.injParameter, kb.injType = injDataSelected setInjection() + print kb.injPlace, kb.injParameter, 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: diff --git a/lib/core/common.py b/lib/core/common.py index adbf534d5..e5fdac7f1 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -75,7 +75,7 @@ def paramToDict(place, parameters=None): elem = element.split("=") if len(elem) == 2: - parameter = elem[0] + parameter = elem[0].replace(" ", "") condition = not conf.testParameter condition |= parameter in conf.testParameter diff --git a/lib/core/option.py b/lib/core/option.py index 3e2ca9e4d..b41e9e115 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -81,6 +81,111 @@ def __urllib2Opener(): urllib2.install_opener(opener) +def __feedTargetsDict(reqFile, addedTargetUrls): + fp = open(reqFile, "r") + + fread = fp.read() + fread = fread.replace("\r", "") + + reqResList = fread.split("======================================================") + + for request in reqResList: + if not re.search ("^[\n]*(GET|POST).*?\sHTTP\/", request, re.I): + continue + + getPostReq = False + url = None + host = None + method = None + data = None + cookie = None + params = False + lines = request.split("\n") + + for line in lines: + if len(line) == 0 or line == "\n": + continue + + if line.startswith("GET ") or line.startswith("POST "): + if line.startswith("GET "): + index = 4 + else: + index = 5 + + url = line[index:line.index(" HTTP/")] + method = line[:index-1] + + if "?" in line and "=" in line: + params = True + + getPostReq = True + + elif "?" in line and "=" in line and ": " not in line: + data = line + params = True + + elif ": " in line: + key, value = line.split(": ", 1) + + if key.lower() == "cookie": + cookie = value + elif key.lower() == "host": + host = value + + if getPostReq and params: + if not url.startswith("http"): + url = "http://%s%s" % (host, url) + + if not kb.targetUrls or url not in addedTargetUrls: + kb.targetUrls.add(( url, method, data, cookie )) + addedTargetUrls.add(url) + + +def __setMultipleTargets(): + """ + Define a configuration parameter if we are running in multiple target + mode. + """ + + initialTargetsCount = len(kb.targetUrls) + addedTargetUrls = set() + + if not conf.list: + return + + debugMsg = "parsing targets list from '%s'" % conf.list + logger.debug(debugMsg) + + if not os.path.exists(conf.list): + errMsg = "the specified list of targets does not exist" + raise sqlmapFilePathException, errMsg + + if os.path.isfile(conf.list): + __feedTargetsDict(conf.list, addedTargetUrls) + + 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(os.path.join(conf.list, reqFile), addedTargetUrls) + + else: + errMsg = "the specified list of targets is not a file " + errMsg += "nor a directory" + raise sqlmapFilePathException, errMsg + + updatedTargetsCount = len(kb.targetUrls) + + if updatedTargetsCount > initialTargetsCount: + infoMsg = "sqlmap parsed %d " % (updatedTargetsCount - initialTargetsCount) + infoMsg += "testable requests from the targets list" + logger.info(infoMsg) + + def __setGoogleDorking(): """ This function checks if the way to request testable hosts is through @@ -109,7 +214,7 @@ def __setGoogleDorking(): errMsg += "Google dork expression" raise sqlmapGenericException, errMsg - kb.targetUrls = googleObj.getTargetUrls() + googleObj.getTargetUrls() if kb.targetUrls: logMsg = "sqlmap got %d results for your " % len(matches) @@ -120,7 +225,7 @@ def __setGoogleDorking(): else: logMsg += "%d " % len(kb.targetUrls) - logMsg += "of them are testable hosts" + logMsg += "of them are testable targets" logger.info(logMsg) else: errMsg = "sqlmap got %d results " % len(matches) @@ -129,103 +234,6 @@ def __setGoogleDorking(): raise sqlmapGenericException, errMsg -def __feedTargetsDict(reqFile): - fp = open(reqFile, "r") - - fread = fp.read() - fread = fread.replace("\r", "") - - # TODO: fix for Burp log file - reqResList = fread.split("\n\n======================================================\n\n\n\n") - - for request in reqResList: - url = None - host = None - method = None - data = None - cookie = None - params = False - lines = request.split("\n") - - for line in lines: - if len(line) == 0 or line == "\n": - continue - - if line.startswith("GET ") or line.startswith("POST "): - if line.startswith("GET "): - index = 4 - else: - index = 5 - - url = line[index:line.index(" HTTP/")] - method = line[:index-1] - - if "?" in line and "=" in line: - params = True - - elif "?" in line and "=" in line: - data = line - params = True - - elif ": " in line: - key, value = line.split(": ", 1) - - if key.lower() == "cookie": - cookie = value - elif key.lower() == "host": - host = value - - if params: - if not url.startswith("http"): - url = "http://%s%s" % (host, url) - - # TODO: exclude duplicated urls - kb.targetUrls[url] = ( method, data, cookie ) - - -def __setMultipleTargets(): - """ - Define a configuration parameter if we are running in multiple target - mode. - """ - - initialTargetsCount = len(kb.targetUrls) - - 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(os.path.join(conf.list, reqFile)) - - else: - errMsg = "the specified list of target urls is not a file " - errMsg += "nor a directory" - raise sqlmapFilePathException, errMsg - - updatedTargetsCount = len(kb.targetUrls) - - if updatedTargetsCount > initialTargetsCount: - infoMsg = "sqlmap parsed %d requests from the targets list" % (updatedTargetsCount - initialTargetsCount) - logger.info(infoMsg) - - def __setRemoteDBMS(): """ Checks and set the back-end DBMS option. @@ -359,9 +367,6 @@ def __setHTTPMethod(): """ if conf.method: - debugMsg = "setting the HTTP method to perform HTTP requests through" - logger.debug(debugMsg) - conf.method = conf.method.upper() if conf.method not in ("GET", "POST"): @@ -374,6 +379,9 @@ def __setHTTPMethod(): else: conf.method = "GET" + debugMsg = "setting the HTTP method to %s" % conf.method + logger.debug(debugMsg) + def __setHTTPStandardHeaders(): conf.httpHeaders.append(("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")) @@ -509,6 +517,9 @@ def __cleanupOptions(): if conf.delay: conf.delay = float(conf.delay) + if conf.googleDork or conf.list: + conf.multipleTargets = True + def __setConfAttributes(): """ @@ -560,7 +571,7 @@ def __setKnowledgeBaseAttributes(): kb.injType = None kb.parenthesis = None kb.resumedQueries = {} - kb.targetUrls = {} + kb.targetUrls = set() kb.timeTest = None kb.unionComment = "" kb.unionCount = None @@ -680,8 +691,8 @@ def init(inputOptions=advancedDict()): __setHTTPProxy() __setThreads() __setRemoteDBMS() - __setMultipleTargets() __setGoogleDorking() + __setMultipleTargets() __urllib2Opener() update() diff --git a/lib/core/target.py b/lib/core/target.py index 36364d7e2..05353b873 100644 --- a/lib/core/target.py +++ b/lib/core/target.py @@ -197,6 +197,20 @@ def initTargetEnv(): Initialize target environment. """ + if conf.multipleTargets: + conf.paramDict = {} + conf.parameters = {} + kb.dbms = None + kb.dbmsDetected = False + kb.dbmsVersion = None + kb.injParameter = None + kb.injPlace = None + kb.injType = None + kb.parenthesis = None + kb.unionComment = "" + kb.unionCount = None + kb.unionPosition = None + parseTargetUrl() __setRequestParams() __setOutputResume() diff --git a/lib/parse/cmdline.py b/lib/parse/cmdline.py index 34468218d..a7b28da2a 100644 --- a/lib/parse/cmdline.py +++ b/lib/parse/cmdline.py @@ -37,7 +37,7 @@ def cmdLineParser(): This function parses the command line parameters and arguments """ - usage = "sqlmap.py [options] {-u <URL> | -g <google dork> | -c <config file>}" + usage = "sqlmap.py [options] {-u \"<URL>\" | -g \"<google dork>\" | -c \"<config file>\"}" parser = OptionParser(usage=usage, version=VERSION_STRING) try: @@ -49,7 +49,7 @@ 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("-l", dest="list", help="List of targets") request.add_option("-g", dest="googleDork", help="Process Google dork results as target urls") @@ -118,11 +118,11 @@ def cmdLineParser(): techniques.add_option("--union-test", dest="unionTest", action="store_true", - help="Test for UNION SELECT (inband) SQL injection") + help="Test for UNION query (inband) SQL injection") techniques.add_option("--union-use", dest="unionUse", action="store_true", - help="Use the UNION SELECT (inband) SQL injection " + help="Use the UNION query (inband) SQL injection " "to retrieve the queries output. No " "need to go blind") diff --git a/lib/utils/google.py b/lib/utils/google.py index 3ef479792..0a1b0cb72 100644 --- a/lib/utils/google.py +++ b/lib/utils/google.py @@ -30,6 +30,7 @@ import urllib2 from lib.core.convert import urlencode from lib.core.data import conf +from lib.core.data import kb from lib.core.exception import sqlmapConnectionException from lib.core.exception import sqlmapRegExprException @@ -68,17 +69,9 @@ class Google: your Google dork search results """ - targetUrls = {} - targetUrlsSet = set() - for match in self.__matches: if re.search("(.*?)\?(.+)", match, re.I): - targetUrlsSet.add(match) - - for targetUrl in targetUrlsSet: - targetUrls[targetUrl] = None - - return targetUrls + kb.targetUrls.add(( match, None, None, None )) def getCookie(self): diff --git a/lib/utils/resume.py b/lib/utils/resume.py index 03d0311d2..38880163f 100644 --- a/lib/utils/resume.py +++ b/lib/utils/resume.py @@ -126,7 +126,7 @@ def resume(expression, payload): # If we called this function without providing a payload it means that # we have called it from lib/request/inject __goInband() function - # in UNION SELECT (inband) SQL injection so we return to the calling + # in UNION query (inband) SQL injection so we return to the calling # function so that the query output will be retrieved taking advantage # of the inband SQL injection vulnerability. if not payload: diff --git a/sqlmap.conf b/sqlmap.conf index 85fcc4018..6de0e63b4 100644 --- a/sqlmap.conf +++ b/sqlmap.conf @@ -3,13 +3,13 @@ # 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) #url = http://127.0.0.1/sqlmap/pgsql/get_int.php?id=1 # PHP and Microsoft SQL Server (remote) -url = http://127.0.0.1/sqlmap/mssql/get_int.php?id=1 +#url = http://127.0.0.1/sqlmap/mssql/get_int.php?id=1 # PHP and MySQL (remote on Windows) #url = http://127.0.0.1/sqlmap/mysql/win_get_int.php?id=1 # ASP and Microsoft SQL Server (local) @@ -21,6 +21,9 @@ url = http://127.0.0.1/sqlmap/mssql/get_int.php?id=1 #url = # List of targets +# Valid: Burp proxy (http://portswigger.net/suite/) requests log file path +# or WebScarab proxy (http://www.owasp.org/index.php/Category:OWASP_WebScarab_Project) +# 'conversations/' folder path list = # Rather than providing a target url, let Google return target @@ -107,11 +110,11 @@ dbms = # Valid: True or False timeTest = False -# Test for UNION SELECT (inband) SQL injection. +# Test for UNION query (inband) SQL injection. # Valid: True or False unionTest = False -# Use the UNION SELECT (inband) SQL injection to retrieve the queries +# Use the UNION query (inband) SQL injection to retrieve the queries # output. No need to go blind. # Valid: True or False unionUse = False