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:
Bernardo Damele 2008-12-05 15:34:13 +00:00
parent 78e8a83c11
commit 38c9627700
9 changed files with 145 additions and 36 deletions

View File

@ -1,26 +1,34 @@
sqlmap (0.6.3-1) stable; urgency=low 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 * Major enhancement to get list of targets to test from Burp proxy
(http://portswigger.net/suite/) requests log file path or WebScarab (http://portswigger.net/suite/) requests log file path or WebScarab
proxy (http://www.owasp.org/index.php/Category:OWASP_WebScarab_Project) 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 * 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 * Minor enhancement to fingerprint the web server operating system and
the web application technology by parsing some HTTP response headers; the web application technology by parsing some HTTP response headers;
* Minor enhancement to fingerprint the back-end DBMS operating system by * Minor enhancement to fingerprint the back-end DBMS operating system by
parsing the DBMS banner value when -b option is provided; parsing the DBMS banner value when -b option is provided;
* Minor enhancement to be able to specify the number of seconds before * 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 * 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 * Minor enhancement to be able to enumerate table columns and dump table
entries, also when the database name is not provided, by using the entries, also when the database name is not provided, by using the
current database on MySQL and Microsoft SQL Server, the 'public' current database on MySQL and Microsoft SQL Server, the 'public'
scheme on PostgreSQL and the 'USERS' TABLESPACE_NAME on Oracle; 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 * Minor improvement to set by default in all HTTP requests the standard
client HTTP headers (Accept, Accept-Encoding, etc); client HTTP headers (Accept, Accept-Encoding, etc);
* Minor improvements to sqlmap Debian package files: sqlmap uploaded * Minor improvements to sqlmap Debian package files: sqlmap uploaded

View File

@ -5,6 +5,9 @@ Chip Andrews <chip@sqlsecurity.com>
at SQLSecurity.com and permission to implement the update feature at SQLSecurity.com and permission to implement the update feature
taking data from his site taking data from his site
Jack Butler <fattredd@hotmail.com>
for providing me with the sqlmap site favicon
Karl Chen <quarl@cs.berkeley.edu> Karl Chen <quarl@cs.berkeley.edu>
for providing with the multithreading patch for the inference for providing with the multithreading patch for the inference
algorithm algorithm

View File

@ -49,8 +49,11 @@ optDict = {
"Injection": { "Injection": {
"testParameter": "string", "testParameter": "string",
"string": "string",
"dbms": "string", "dbms": "string",
"string": "string",
"regexp": "string",
"eString": "string",
"eRegexp": "string",
}, },
"Techniques": { "Techniques": {

View File

@ -53,7 +53,7 @@ def __updateMSSQLXML():
logger.info(infoMsg) logger.info(infoMsg)
try: try:
mssqlVersionsHtmlString = Request.getPage(url=MSSQL_VERSIONS_URL, direct=True) mssqlVersionsHtmlString, _ = Request.getPage(url=MSSQL_VERSIONS_URL, direct=True)
except sqlmapConnectionException, _: except sqlmapConnectionException, _:
__mssqlPath = urlparse.urlsplit(MSSQL_VERSIONS_URL) __mssqlPath = urlparse.urlsplit(MSSQL_VERSIONS_URL)
__mssqlHostname = __mssqlPath[1] __mssqlHostname = __mssqlPath[1]
@ -231,7 +231,7 @@ def __updateSqlmap():
logger.debug(debugMsg) logger.debug(debugMsg)
try: try:
sqlmapNewestVersion = Request.getPage(url=SQLMAP_VERSION_URL, direct=True) sqlmapNewestVersion, _ = Request.getPage(url=SQLMAP_VERSION_URL, direct=True)
except sqlmapConnectionException, _: except sqlmapConnectionException, _:
__sqlmapPath = urlparse.urlsplit(SQLMAP_VERSION_URL) __sqlmapPath = urlparse.urlsplit(SQLMAP_VERSION_URL)
__sqlmapHostname = __sqlmapPath[1] __sqlmapHostname = __sqlmapPath[1]
@ -271,7 +271,7 @@ def __updateSqlmap():
sqlmapBinaryStringUrl = SQLMAP_SOURCE_URL % sqlmapNewestVersion sqlmapBinaryStringUrl = SQLMAP_SOURCE_URL % sqlmapNewestVersion
try: try:
sqlmapBinaryString = Request.getPage(url=sqlmapBinaryStringUrl, direct=True) sqlmapBinaryString, _ = Request.getPage(url=sqlmapBinaryStringUrl, direct=True)
except sqlmapConnectionException, _: except sqlmapConnectionException, _:
__sqlmapPath = urlparse.urlsplit(sqlmapBinaryStringUrl) __sqlmapPath = urlparse.urlsplit(sqlmapBinaryStringUrl)
__sqlmapHostname = __sqlmapPath[1] __sqlmapHostname = __sqlmapPath[1]

View File

@ -109,12 +109,24 @@ def cmdLineParser():
injection.add_option("-p", dest="testParameter", injection.add_option("-p", dest="testParameter",
help="Testable parameter(s)") help="Testable parameter(s)")
injection.add_option("--dbms", dest="dbms",
help="Force back-end DBMS to this value")
injection.add_option("--string", dest="string", injection.add_option("--string", dest="string",
help="String to match in page when the " help="String to match in page when the "
"query is valid") "query is valid")
injection.add_option("--dbms", dest="dbms", injection.add_option("--regexp", dest="regexp",
help="Force back-end DBMS to this value") 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 options
techniques = OptionGroup(parser, "Techniques", "These options can " techniques = OptionGroup(parser, "Techniques", "These options can "

69
lib/request/comparison.py Normal file
View 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()

View File

@ -42,7 +42,7 @@ from lib.core.exception import sqlmapConnectionException
from lib.core.settings import RETRIES from lib.core.settings import RETRIES
from lib.request.basic import forgeHeaders from lib.request.basic import forgeHeaders
from lib.request.basic import parseResponse from lib.request.basic import parseResponse
from lib.request.comparison import comparison
class Connect: class Connect:
@ -190,15 +190,15 @@ class Connect:
warnMsg += "status code, try to force the HTTP User-Agent " warnMsg += "status code, try to force the HTTP User-Agent "
warnMsg += "header with option --user-agent or -a" warnMsg += "header with option --user-agent or -a"
if "BadStatusLine" not in tbMsg:
warnMsg += " or proxy"
if conf.multipleTargets: if conf.multipleTargets:
warnMsg += ", skipping to next url" warnMsg += ", skipping to next url"
logger.warn(warnMsg) logger.warn(warnMsg)
return None return None
if "BadStatusLine" not in tbMsg:
warnMsg += " or proxy"
if conf.retries < RETRIES: if conf.retries < RETRIES:
conf.retries += 1 conf.retries += 1
@ -207,6 +207,7 @@ class Connect:
time.sleep(1) time.sleep(1)
return Connect.__getPageProxy(get=get, post=post, cookie=cookie, ua=ua, direct=direct, multipart=multipart) return Connect.__getPageProxy(get=get, post=post, cookie=cookie, ua=ua, direct=direct, multipart=multipart)
else: else:
raise sqlmapConnectionException, warnMsg raise sqlmapConnectionException, warnMsg
@ -220,7 +221,7 @@ class Connect:
logger.log(8, responseMsg) logger.log(8, responseMsg)
return page return page, responseHeaders
@staticmethod @staticmethod
@ -263,15 +264,9 @@ class Connect:
else: else:
ua = conf.parameters["User-Agent"] 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: if content:
return page return page
elif conf.string:
if conf.string in page:
return True
else:
return False
else: else:
return md5.new(page).hexdigest() return comparison(page, headers, content)

View File

@ -450,7 +450,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Takeover):
baseUrl = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, requestDir) baseUrl = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, requestDir)
uploaderUrl = "%s/%s" % (baseUrl, uploaderName) 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: if "sqlmap backdoor uploader" not in page:
warnMsg = "unable to upload the uploader " warnMsg = "unable to upload the uploader "
@ -470,7 +470,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Takeover):
"uploadDir": directory, "uploadDir": directory,
} }
uploaderUrl = "%s/%s" % (baseUrl, uploaderName) 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: if "Backdoor uploaded" not in page:
warnMsg = "unable to upload the backdoor through " warnMsg = "unable to upload the backdoor through "
@ -522,7 +522,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Takeover):
break break
cmdUrl = "%s?cmd=%s" % (backdoorUrl, command) 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) output = re.search("<pre>(.+?)</pre>", page, re.I | re.S)
if output: if output:

View File

@ -99,19 +99,38 @@ timeout = 10
# parameters and HTTP User-Agent are tested by sqlmap. # parameters and HTTP User-Agent are tested by sqlmap.
testParameter = 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 # Force back-end DBMS to this value. If this option is set, the back-end
# DBMS identification process will be minimized as needed. # DBMS identification process will be minimized as needed.
# If not set, sqlmap will detect back-end DBMS automatically by default. # If not set, sqlmap will detect back-end DBMS automatically by default.
# Valid: mssql, mysql, mysql 4, mysql 5, oracle, pgsql # Valid: mssql, mysql, mysql 4, mysql 5, oracle, pgsql
dbms = 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] [Techniques]