Added --code switch to match in boolean-based tests against the HTTP response code

This commit is contained in:
Bernardo Damele 2011-08-12 16:48:11 +00:00
parent e34787db99
commit 702ed73a65
9 changed files with 39 additions and 23 deletions

View File

@ -898,7 +898,7 @@ def checkNullConnection():
logger.info(infoMsg)
try:
page, headers = Request.getPage(method=HTTPMETHOD.HEAD)
page, headers, _ = Request.getPage(method=HTTPMETHOD.HEAD)
if not page and HTTPHEADER.CONTENT_LENGTH in headers:
kb.nullConnection = NULLCONNECTION.HEAD
@ -906,7 +906,7 @@ def checkNullConnection():
infoMsg = "NULL connection is supported with HEAD header"
logger.info(infoMsg)
else:
page, headers = Request.getPage(auxHeaders={HTTPHEADER.RANGE: "bytes=-1"})
page, headers, _ = Request.getPage(auxHeaders={HTTPHEADER.RANGE: "bytes=-1"})
if page and len(page) == 1 and HTTPHEADER.CONTENT_RANGE in headers:
kb.nullConnection = NULLCONNECTION.RANGE

View File

@ -1330,6 +1330,9 @@ def __cleanupOptions():
else:
kb.adjustTimeDelay = False
if conf.code:
conf.code = int(conf.code)
def __setConfAttributes():
"""
This function set some needed attributes into the configuration

View File

@ -68,6 +68,7 @@ optDict = {
"risk": "integer",
"string": "string",
"regexp": "string",
"code": "string",
"textOnly": "boolean",
"titles": "boolean"
},

View File

@ -200,13 +200,16 @@ def cmdLineParser():
"default %d)" % defaults.level)
detection.add_option("--string", dest="string",
help="String to match in page when the "
help="String to match in the response when "
"query is valid")
detection.add_option("--regexp", dest="regexp",
help="Regexp to match in page when the "
help="Regexp to match in the response when "
"query is valid")
detection.add_option("--code", dest="code", type="int",
help="HTTP response code to match when the query is valid")
detection.add_option("--text-only", dest="textOnly",
action="store_true",
help="Compare pages based only on the textual content")

View File

@ -28,7 +28,7 @@ from lib.core.settings import LOWER_RATIO_BOUND
from lib.core.settings import UPPER_RATIO_BOUND
from lib.core.threads import getCurrentThreadData
def comparison(page, headers, getRatioValue=False, pageLength=None):
def comparison(page, headers, code=None, getRatioValue=False, pageLength=None):
if page is None and pageLength is None:
return None
@ -50,6 +50,9 @@ def comparison(page, headers, getRatioValue=False, pageLength=None):
condition = re.search(conf.regexp, rawResponse, re.I | re.M) is not None
return condition if not getRatioValue else (MAX_RATIO if condition else MIN_RATIO)
if isinstance(code, int) and conf.code:
return code == conf.code
if page:
# In case of an DBMS error page return None
if kb.errorIsNone and (wasLastRequestDBMSError() or wasLastRequestHTTPError()):

View File

@ -306,7 +306,7 @@ class Connect:
# Return response object
if response:
return conn, None
return conn, None, None
# Get HTTP response
page = conn.read()
@ -369,7 +369,7 @@ class Connect:
warnMsg = "connection timed out while trying "
warnMsg += "to get error page information (%d)" % e.code
logger.warn(warnMsg)
return None, None
return None, None, None
except:
pass
@ -409,7 +409,7 @@ class Connect:
processResponse(page, responseHeaders)
elif e.code == 504:
if ignoreTimeout:
return None, None
return None, None, None
else:
warnMsg = "unable to connect to the target url (%d - %s)" % (e.code, httplib.responses[e.code])
if threadData.retriesCount < conf.retries and not kb.threadException and not conf.realTest:
@ -418,14 +418,14 @@ class Connect:
return Connect.__retryProxy(**kwargs)
elif kb.testMode:
logger.critical(warnMsg)
return None, None
return None, None, None
else:
raise sqlmapConnectionException, warnMsg
else:
debugMsg = "got HTTP error code: %d (%s)" % (code, status)
logger.debug(debugMsg)
processResponse(page, responseHeaders)
return page, responseHeaders
return page, responseHeaders, code
except (urllib2.URLError, socket.error, socket.timeout, httplib.BadStatusLine, httplib.IncompleteRead), e:
tbMsg = traceback.format_exc()
@ -454,16 +454,16 @@ class Connect:
if "forcibly closed" in tbMsg:
logger.critical(warnMsg)
return None, None
return None, None, None
elif silent or (ignoreTimeout and any(map(lambda x: x in tbMsg, ["timed out", "IncompleteRead"]))):
return None, None
return None, None, None
elif threadData.retriesCount < conf.retries and not kb.threadException and not conf.realTest:
warnMsg += ", sqlmap is going to retry the request"
logger.critical(warnMsg)
return Connect.__retryProxy(**kwargs)
elif kb.testMode:
logger.critical(warnMsg)
return None, None
return None, None, None
else:
raise sqlmapConnectionException, warnMsg
@ -485,7 +485,7 @@ class Connect:
logger.log(7, responseMsg)
return page, responseHeaders
return page, responseHeaders, code
@staticmethod
def queryPage(value=None, place=None, content=False, getRatioValue=False, silent=False, method=None, timeBasedCompare=False, noteResponseTime=True, auxHeaders=None, response=False, raise404=None):
@ -613,7 +613,7 @@ class Connect:
auxHeaders[HTTPHEADER.RANGE] = "bytes=-1"
_, headers = Connect.getPage(url=uri, get=get, post=post, cookie=cookie, ua=ua, referer=referer, silent=silent, method=method, auxHeaders=auxHeaders, raise404=raise404)
_, headers, code = Connect.getPage(url=uri, get=get, post=post, cookie=cookie, ua=ua, referer=referer, silent=silent, method=method, auxHeaders=auxHeaders, raise404=raise404)
if headers:
if kb.nullConnection == NULLCONNECTION.HEAD and HTTPHEADER.CONTENT_LENGTH in headers:
@ -622,7 +622,7 @@ class Connect:
pageLength = int(headers[HTTPHEADER.CONTENT_RANGE][headers[HTTPHEADER.CONTENT_RANGE].find('/') + 1:])
if not pageLength:
page, headers = Connect.getPage(url=uri, get=get, post=post, cookie=cookie, ua=ua, referer=referer, silent=silent, method=method, auxHeaders=auxHeaders, response=response, raise404=raise404, ignoreTimeout=timeBasedCompare)
page, headers, code = Connect.getPage(url=uri, get=get, post=post, cookie=cookie, ua=ua, referer=referer, silent=silent, method=method, auxHeaders=auxHeaders, response=response, raise404=raise404, ignoreTimeout=timeBasedCompare)
threadData.lastQueryDuration = calculateDeltaSeconds(start)
@ -643,8 +643,8 @@ class Connect:
page = removeReflectiveValues(page, payload)
if getRatioValue:
return comparison(page, headers, getRatioValue=False, pageLength=pageLength), comparison(page, headers, getRatioValue=True, pageLength=pageLength)
return comparison(page, headers, code, getRatioValue=False, pageLength=pageLength), comparison(page, headers, code, getRatioValue=True, pageLength=pageLength)
elif pageLength or page:
return comparison(page, headers, getRatioValue, pageLength)
return comparison(page, headers, code, getRatioValue, pageLength)
else:
return False

View File

@ -62,7 +62,7 @@ class Web:
cmd = conf.osCmd
cmdUrl = "%s?cmd=%s" % (self.webBackdoorUrl, cmd)
page, _ = Request.getPage(url=cmdUrl, direct=True, silent=True)
page, _, _ = Request.getPage(url=cmdUrl, direct=True, silent=True)
if page is not None:
output = re.search("<pre>(.+?)</pre>", page, re.I | re.S)
@ -237,7 +237,7 @@ class Web:
self.webBaseUrl = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, uriPath)
self.webStagerUrl = "%s/%s" % (self.webBaseUrl, stagerName)
uplPage, _ = Request.getPage(url=self.webStagerUrl, direct=True, raise404=False)
uplPage, _, _ = Request.getPage(url=self.webStagerUrl, direct=True, raise404=False)
if "sqlmap file uploader" not in uplPage:
if localPath not in warned:

View File

@ -109,7 +109,7 @@ def __findUnionCharCount(comment, place, parameter, value, prefix, suffix, where
query = agent.forgeInbandQuery('', -1, count, comment, prefix, suffix, kb.uChar)
payload = agent.payload(place=place, parameter=parameter, newValue=query, where=where)
page, headers = Request.queryPage(payload, place=place, content=True, raise404=False)
ratio = comparison(page, headers, True) or MIN_RATIO
ratio = comparison(page, headers, getRatioValue=True) or MIN_RATIO
ratios.append(ratio)
min_, max_ = min(min_, ratio), max(max_, ratio)
items.append((count, ratio))

View File

@ -204,12 +204,12 @@ level = 1
# Default: 1
risk = 1
# String to match within the page content when the query is valid, only
# String to match within the raw response when the query is valid, only
# needed if the page content dynamically changes at each refresh.
# Refer to the user's manual for further details.
string =
# Regular expression to match within the page content when the query is
# Regular expression to match within the raw response when the query is
# valid, only needed if the needed if the page content dynamically changes
# at each refresh.
# Refer to the user's manual for further details.
@ -217,6 +217,12 @@ string =
# (http://www.python.org/doc/2.5.2/lib/re-syntax.html)
regexp =
# HTTP response code to match when the query is valid
# Valid: True or False
# Example: 200 (assuming any False statement returns a different response
# code)
code =
# Compare pages based only on the textual content
# Valid: True or False
textOnly = False