mirror of
				https://github.com/sqlmapproject/sqlmap.git
				synced 2025-11-04 09:57:38 +03:00 
			
		
		
		
	Minor enhancemet to support also --regexp, --excl-str and --excl-reg
options rather than only --string when comparing HTTP responses page content
This commit is contained in:
		
							parent
							
								
									78e8a83c11
								
							
						
					
					
						commit
						38c9627700
					
				| 
						 | 
				
			
			@ -1,26 +1,34 @@
 | 
			
		|||
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;
 | 
			
		||||
    'conversations/' folder path by providing option -l <filepath>;
 | 
			
		||||
  * Major enhancement to support stacked queries (multiple staatements)
 | 
			
		||||
    when the web application supports them which is useful for time based
 | 
			
		||||
    blind sql injection test and will be used someday also by takeover
 | 
			
		||||
    functionality;
 | 
			
		||||
  * Minor enhancement to test if the injectable parameter is affected by
 | 
			
		||||
    a time based blind SQL injection technique;
 | 
			
		||||
    a time based blind SQL injection technique by providing option
 | 
			
		||||
    --time-test;
 | 
			
		||||
  * Minor enhancement to fingerprint the web server operating system and
 | 
			
		||||
    the web application technology by parsing some HTTP response headers;
 | 
			
		||||
  * Minor enhancement to fingerprint the back-end DBMS operating system by
 | 
			
		||||
    parsing the DBMS banner value when -b option is provided;
 | 
			
		||||
  * Minor enhancement to be able to specify the number of seconds before
 | 
			
		||||
    timeout the connection, default is set to 10 seconds;
 | 
			
		||||
    timeout the connection by providing option --timeout #, default is set
 | 
			
		||||
    to 10 seconds and must be 3 or higher;
 | 
			
		||||
  * Minor enhancement to be able to specify the number of seconds to wait
 | 
			
		||||
    between each HTTP request providing option --delay #;
 | 
			
		||||
    between each HTTP request by providing option --delay #;
 | 
			
		||||
  * Minor enhancement to be able to enumerate table columns and dump table
 | 
			
		||||
    entries, also when the database name is not provided, by using the
 | 
			
		||||
    current database on MySQL and Microsoft SQL Server, the 'public'
 | 
			
		||||
    scheme on PostgreSQL and the 'USERS' TABLESPACE_NAME on Oracle;
 | 
			
		||||
  * Minor enhancemet to support also --regexp, --excl-str and --excl-reg
 | 
			
		||||
    options rather than only --string when comparing HTTP responses page
 | 
			
		||||
    content;
 | 
			
		||||
  * Minor improvement to be able to provide CU as user value (-U) when
 | 
			
		||||
    enumerating users privileges or users passwords;
 | 
			
		||||
  * Minor improvement to set by default in all HTTP requests the standard
 | 
			
		||||
    client HTTP headers (Accept, Accept-Encoding, etc);
 | 
			
		||||
  * Minor improvements to sqlmap Debian package files: sqlmap uploaded
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,9 @@ Chip Andrews <chip@sqlsecurity.com>
 | 
			
		|||
    at SQLSecurity.com and permission to implement the update feature
 | 
			
		||||
    taking data from his site
 | 
			
		||||
 | 
			
		||||
Jack Butler <fattredd@hotmail.com>
 | 
			
		||||
    for providing me with the sqlmap site favicon
 | 
			
		||||
 | 
			
		||||
Karl Chen <quarl@cs.berkeley.edu>
 | 
			
		||||
    for providing with the multithreading patch for the inference
 | 
			
		||||
    algorithm
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,8 +49,11 @@ optDict = {
 | 
			
		|||
 | 
			
		||||
            "Injection":     {
 | 
			
		||||
                               "testParameter":     "string",
 | 
			
		||||
                               "string":            "string",
 | 
			
		||||
                               "dbms":              "string",
 | 
			
		||||
                               "string":            "string",
 | 
			
		||||
                               "regexp":            "string",
 | 
			
		||||
                               "eString":           "string",
 | 
			
		||||
                               "eRegexp":           "string",
 | 
			
		||||
                             },
 | 
			
		||||
 | 
			
		||||
            "Techniques":    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -53,7 +53,7 @@ def __updateMSSQLXML():
 | 
			
		|||
    logger.info(infoMsg)
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        mssqlVersionsHtmlString = Request.getPage(url=MSSQL_VERSIONS_URL, direct=True)
 | 
			
		||||
        mssqlVersionsHtmlString, _ = Request.getPage(url=MSSQL_VERSIONS_URL, direct=True)
 | 
			
		||||
    except sqlmapConnectionException, _:
 | 
			
		||||
        __mssqlPath     = urlparse.urlsplit(MSSQL_VERSIONS_URL)
 | 
			
		||||
        __mssqlHostname = __mssqlPath[1]
 | 
			
		||||
| 
						 | 
				
			
			@ -231,7 +231,7 @@ def __updateSqlmap():
 | 
			
		|||
    logger.debug(debugMsg)
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        sqlmapNewestVersion = Request.getPage(url=SQLMAP_VERSION_URL, direct=True)
 | 
			
		||||
        sqlmapNewestVersion, _ = Request.getPage(url=SQLMAP_VERSION_URL, direct=True)
 | 
			
		||||
    except sqlmapConnectionException, _:
 | 
			
		||||
        __sqlmapPath     = urlparse.urlsplit(SQLMAP_VERSION_URL)
 | 
			
		||||
        __sqlmapHostname = __sqlmapPath[1]
 | 
			
		||||
| 
						 | 
				
			
			@ -271,7 +271,7 @@ def __updateSqlmap():
 | 
			
		|||
    sqlmapBinaryStringUrl = SQLMAP_SOURCE_URL % sqlmapNewestVersion
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        sqlmapBinaryString = Request.getPage(url=sqlmapBinaryStringUrl, direct=True)
 | 
			
		||||
        sqlmapBinaryString, _ = Request.getPage(url=sqlmapBinaryStringUrl, direct=True)
 | 
			
		||||
    except sqlmapConnectionException, _:
 | 
			
		||||
        __sqlmapPath     = urlparse.urlsplit(sqlmapBinaryStringUrl)
 | 
			
		||||
        __sqlmapHostname = __sqlmapPath[1]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -109,12 +109,24 @@ def cmdLineParser():
 | 
			
		|||
        injection.add_option("-p", dest="testParameter",
 | 
			
		||||
                             help="Testable parameter(s)")
 | 
			
		||||
 | 
			
		||||
        injection.add_option("--dbms", dest="dbms",
 | 
			
		||||
                             help="Force back-end DBMS to this value")
 | 
			
		||||
 | 
			
		||||
        injection.add_option("--string", dest="string",
 | 
			
		||||
                             help="String to match in page when the "
 | 
			
		||||
                                  "query is valid")
 | 
			
		||||
 | 
			
		||||
        injection.add_option("--dbms", dest="dbms",
 | 
			
		||||
                             help="Force back-end DBMS to this value")
 | 
			
		||||
        injection.add_option("--regexp", dest="regexp",
 | 
			
		||||
                             help="Regexp to match in page when the "
 | 
			
		||||
                                  "query is valid")
 | 
			
		||||
 | 
			
		||||
        injection.add_option("--excl-str", dest="eString",
 | 
			
		||||
                             help="String to be excluded before calculating "
 | 
			
		||||
                                  "page hash")
 | 
			
		||||
 | 
			
		||||
        injection.add_option("--excl-reg", dest="eRegexp",
 | 
			
		||||
                             help="Regexp matches to be excluded before "
 | 
			
		||||
                                  "calculating page hash")
 | 
			
		||||
 | 
			
		||||
        # Techniques options
 | 
			
		||||
        techniques = OptionGroup(parser, "Techniques", "These options can "
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										69
									
								
								lib/request/comparison.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								lib/request/comparison.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,69 @@
 | 
			
		|||
#!/usr/bin/env python
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
$Id$
 | 
			
		||||
 | 
			
		||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com>
 | 
			
		||||
                        and Daniele Bellucci <daniele.bellucci@gmail.com>
 | 
			
		||||
 | 
			
		||||
sqlmap is free software; you can redistribute it and/or modify it under
 | 
			
		||||
the terms of the GNU General Public License as published by the Free
 | 
			
		||||
Software Foundation version 2 of the License.
 | 
			
		||||
 | 
			
		||||
sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY
 | 
			
		||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 | 
			
		||||
FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 | 
			
		||||
details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License along
 | 
			
		||||
with sqlmap; if not, write to the Free Software Foundation, Inc., 51
 | 
			
		||||
Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import md5
 | 
			
		||||
import re
 | 
			
		||||
 | 
			
		||||
from lib.core.data import conf
 | 
			
		||||
from lib.core.data import kb
 | 
			
		||||
from lib.core.data import logger
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def comparison(page, headers=None, content=False):
 | 
			
		||||
    regExpResults = None
 | 
			
		||||
 | 
			
		||||
    if conf.eString and conf.eString in page:
 | 
			
		||||
        index              = page.index(conf.eString)
 | 
			
		||||
        length             = len(conf.eString)
 | 
			
		||||
        pageWithoutString  = page[:index]
 | 
			
		||||
        pageWithoutString += page[index+length:]
 | 
			
		||||
        page               = pageWithoutString
 | 
			
		||||
 | 
			
		||||
    if conf.eRegexp:
 | 
			
		||||
        regExpResults = re.findall(conf.eRegexp, page, re.I | re.M)
 | 
			
		||||
 | 
			
		||||
    if conf.eRegexp and regExpResults:
 | 
			
		||||
        for regExpResult in regExpResults:
 | 
			
		||||
            index              = page.index(regExpResult)
 | 
			
		||||
            length             = len(regExpResult)
 | 
			
		||||
            pageWithoutRegExp  = page[:index]
 | 
			
		||||
            pageWithoutRegExp += page[index+length:]
 | 
			
		||||
            page               = pageWithoutRegExp
 | 
			
		||||
 | 
			
		||||
    if conf.string:
 | 
			
		||||
        if conf.string in page:
 | 
			
		||||
            return True
 | 
			
		||||
        else:
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
    elif conf.regexp:
 | 
			
		||||
        if re.search(conf.regexp, page, re.I | re.M):
 | 
			
		||||
            return True
 | 
			
		||||
        else:
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
    else:
 | 
			
		||||
        return md5.new(page).hexdigest()
 | 
			
		||||
| 
						 | 
				
			
			@ -42,7 +42,7 @@ from lib.core.exception import sqlmapConnectionException
 | 
			
		|||
from lib.core.settings import RETRIES
 | 
			
		||||
from lib.request.basic import forgeHeaders
 | 
			
		||||
from lib.request.basic import parseResponse
 | 
			
		||||
 | 
			
		||||
from lib.request.comparison import comparison
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Connect:
 | 
			
		||||
| 
						 | 
				
			
			@ -190,15 +190,15 @@ class Connect:
 | 
			
		|||
                warnMsg += "status code, try to force the HTTP User-Agent "
 | 
			
		||||
                warnMsg += "header with option --user-agent or -a"
 | 
			
		||||
 | 
			
		||||
            if "BadStatusLine" not in tbMsg:
 | 
			
		||||
                warnMsg += " or proxy"
 | 
			
		||||
 | 
			
		||||
            if conf.multipleTargets:
 | 
			
		||||
                warnMsg += ", skipping to next url"
 | 
			
		||||
                logger.warn(warnMsg)
 | 
			
		||||
 | 
			
		||||
                return None
 | 
			
		||||
 | 
			
		||||
            if "BadStatusLine" not in tbMsg:
 | 
			
		||||
                warnMsg += " or proxy"
 | 
			
		||||
 | 
			
		||||
            if conf.retries < RETRIES:
 | 
			
		||||
                conf.retries += 1
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -207,6 +207,7 @@ class Connect:
 | 
			
		|||
 | 
			
		||||
                time.sleep(1)
 | 
			
		||||
                return Connect.__getPageProxy(get=get, post=post, cookie=cookie, ua=ua, direct=direct, multipart=multipart)
 | 
			
		||||
 | 
			
		||||
            else:
 | 
			
		||||
                raise sqlmapConnectionException, warnMsg
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -220,7 +221,7 @@ class Connect:
 | 
			
		|||
 | 
			
		||||
        logger.log(8, responseMsg)
 | 
			
		||||
 | 
			
		||||
        return page
 | 
			
		||||
        return page, responseHeaders
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
| 
						 | 
				
			
			@ -263,15 +264,9 @@ class Connect:
 | 
			
		|||
            else:
 | 
			
		||||
                ua = conf.parameters["User-Agent"]
 | 
			
		||||
 | 
			
		||||
        page = Connect.getPage(get=get, post=post, cookie=cookie, ua=ua)
 | 
			
		||||
        page, headers = Connect.getPage(get=get, post=post, cookie=cookie, ua=ua)
 | 
			
		||||
 | 
			
		||||
        # TODO: create a comparison library and move these checks there
 | 
			
		||||
        if content:
 | 
			
		||||
            return page
 | 
			
		||||
        elif conf.string:
 | 
			
		||||
            if conf.string in page:
 | 
			
		||||
                return True
 | 
			
		||||
            else:
 | 
			
		||||
                return False
 | 
			
		||||
        else:
 | 
			
		||||
            return md5.new(page).hexdigest()
 | 
			
		||||
            return comparison(page, headers, content)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -450,7 +450,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Takeover):
 | 
			
		|||
 | 
			
		||||
            baseUrl = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, requestDir)
 | 
			
		||||
            uploaderUrl = "%s/%s" % (baseUrl, uploaderName)
 | 
			
		||||
            page = Request.getPage(url=uploaderUrl, direct=True)
 | 
			
		||||
            page, _ = Request.getPage(url=uploaderUrl, direct=True)
 | 
			
		||||
 | 
			
		||||
            if "sqlmap backdoor uploader" not in page:
 | 
			
		||||
                warnMsg  = "unable to upload the uploader "
 | 
			
		||||
| 
						 | 
				
			
			@ -470,7 +470,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Takeover):
 | 
			
		|||
                                "uploadDir": directory,
 | 
			
		||||
                              }
 | 
			
		||||
            uploaderUrl = "%s/%s" % (baseUrl, uploaderName)
 | 
			
		||||
            page = Request.getPage(url=uploaderUrl, multipart=multipartParams)
 | 
			
		||||
            page, _ = Request.getPage(url=uploaderUrl, multipart=multipartParams)
 | 
			
		||||
 | 
			
		||||
            if "Backdoor uploaded" not in page:
 | 
			
		||||
                warnMsg  = "unable to upload the backdoor through "
 | 
			
		||||
| 
						 | 
				
			
			@ -522,7 +522,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Takeover):
 | 
			
		|||
                    break
 | 
			
		||||
 | 
			
		||||
                cmdUrl = "%s?cmd=%s" % (backdoorUrl, command)
 | 
			
		||||
                page = Request.getPage(url=cmdUrl, direct=True)
 | 
			
		||||
                page, _ = Request.getPage(url=cmdUrl, direct=True)
 | 
			
		||||
                output = re.search("<pre>(.+?)</pre>", page, re.I | re.S)
 | 
			
		||||
 | 
			
		||||
                if output:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										33
									
								
								sqlmap.conf
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								sqlmap.conf
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -99,19 +99,38 @@ timeout = 10
 | 
			
		|||
# parameters and HTTP User-Agent are tested by sqlmap.
 | 
			
		||||
testParameter = 
 | 
			
		||||
 | 
			
		||||
# String to match in page when the query is valid, only needed if the
 | 
			
		||||
# page content dynamically changes at each refresh, consequently changing
 | 
			
		||||
# the MD5 of the page which is the method used by default to determine
 | 
			
		||||
# if a query was valid or not. Read the documentation for further
 | 
			
		||||
# details.
 | 
			
		||||
string = 
 | 
			
		||||
 | 
			
		||||
# Force back-end DBMS to this value. If this option is set, the back-end
 | 
			
		||||
# DBMS identification process will be minimized as needed.
 | 
			
		||||
# If not set, sqlmap will detect back-end DBMS automatically by default.
 | 
			
		||||
# Valid: mssql, mysql, mysql 4, mysql 5, oracle, pgsql
 | 
			
		||||
dbms = 
 | 
			
		||||
 | 
			
		||||
# String to match within the page content when the query is valid, only
 | 
			
		||||
# needed if the page content dynamically changes at each refresh,
 | 
			
		||||
# consequently changing the MD5 hash of the page which is the method used
 | 
			
		||||
# by default to determine if a query was valid or not. Refer to the user's
 | 
			
		||||
# manual for further details.
 | 
			
		||||
string = 
 | 
			
		||||
 | 
			
		||||
# Regular expression to match within the page content when the query is
 | 
			
		||||
# valid, only needed if the needed if the page content dynamically changes
 | 
			
		||||
# at each refresh, consequently changing the MD5 hash of the page which is
 | 
			
		||||
# the method used by default to determine if a query was valid or not.
 | 
			
		||||
# Refer to the user's manual for further details.
 | 
			
		||||
# Valid: regular expression with Python syntax
 | 
			
		||||
# (http://www.python.org/doc/2.5.2/lib/re-syntax.html)
 | 
			
		||||
regexp = 
 | 
			
		||||
 | 
			
		||||
# String to be excluded by the page content before calculating the page
 | 
			
		||||
# MD5 hash
 | 
			
		||||
eString = 
 | 
			
		||||
 | 
			
		||||
# Regular expression matches to be excluded by the page content before
 | 
			
		||||
# calculating the page MD5 hash
 | 
			
		||||
# Valid: regular expression with Python syntax
 | 
			
		||||
# (http://www.python.org/doc/2.5.2/lib/re-syntax.html)
 | 
			
		||||
eRegexp = 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[Techniques]
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user