mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2024-11-25 19:13:48 +03:00
Added --code switch to match in boolean-based tests against the HTTP response code
This commit is contained in:
parent
e34787db99
commit
702ed73a65
|
@ -898,7 +898,7 @@ def checkNullConnection():
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
page, headers = Request.getPage(method=HTTPMETHOD.HEAD)
|
page, headers, _ = Request.getPage(method=HTTPMETHOD.HEAD)
|
||||||
|
|
||||||
if not page and HTTPHEADER.CONTENT_LENGTH in headers:
|
if not page and HTTPHEADER.CONTENT_LENGTH in headers:
|
||||||
kb.nullConnection = NULLCONNECTION.HEAD
|
kb.nullConnection = NULLCONNECTION.HEAD
|
||||||
|
@ -906,7 +906,7 @@ def checkNullConnection():
|
||||||
infoMsg = "NULL connection is supported with HEAD header"
|
infoMsg = "NULL connection is supported with HEAD header"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
else:
|
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:
|
if page and len(page) == 1 and HTTPHEADER.CONTENT_RANGE in headers:
|
||||||
kb.nullConnection = NULLCONNECTION.RANGE
|
kb.nullConnection = NULLCONNECTION.RANGE
|
||||||
|
|
|
@ -1330,6 +1330,9 @@ def __cleanupOptions():
|
||||||
else:
|
else:
|
||||||
kb.adjustTimeDelay = False
|
kb.adjustTimeDelay = False
|
||||||
|
|
||||||
|
if conf.code:
|
||||||
|
conf.code = int(conf.code)
|
||||||
|
|
||||||
def __setConfAttributes():
|
def __setConfAttributes():
|
||||||
"""
|
"""
|
||||||
This function set some needed attributes into the configuration
|
This function set some needed attributes into the configuration
|
||||||
|
|
|
@ -68,6 +68,7 @@ optDict = {
|
||||||
"risk": "integer",
|
"risk": "integer",
|
||||||
"string": "string",
|
"string": "string",
|
||||||
"regexp": "string",
|
"regexp": "string",
|
||||||
|
"code": "string",
|
||||||
"textOnly": "boolean",
|
"textOnly": "boolean",
|
||||||
"titles": "boolean"
|
"titles": "boolean"
|
||||||
},
|
},
|
||||||
|
|
|
@ -200,13 +200,16 @@ def cmdLineParser():
|
||||||
"default %d)" % defaults.level)
|
"default %d)" % defaults.level)
|
||||||
|
|
||||||
detection.add_option("--string", dest="string",
|
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")
|
"query is valid")
|
||||||
|
|
||||||
detection.add_option("--regexp", dest="regexp",
|
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")
|
"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",
|
detection.add_option("--text-only", dest="textOnly",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="Compare pages based only on the textual content")
|
help="Compare pages based only on the textual content")
|
||||||
|
|
|
@ -28,7 +28,7 @@ from lib.core.settings import LOWER_RATIO_BOUND
|
||||||
from lib.core.settings import UPPER_RATIO_BOUND
|
from lib.core.settings import UPPER_RATIO_BOUND
|
||||||
from lib.core.threads import getCurrentThreadData
|
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:
|
if page is None and pageLength is None:
|
||||||
return 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
|
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)
|
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:
|
if page:
|
||||||
# In case of an DBMS error page return None
|
# In case of an DBMS error page return None
|
||||||
if kb.errorIsNone and (wasLastRequestDBMSError() or wasLastRequestHTTPError()):
|
if kb.errorIsNone and (wasLastRequestDBMSError() or wasLastRequestHTTPError()):
|
||||||
|
|
|
@ -306,7 +306,7 @@ class Connect:
|
||||||
|
|
||||||
# Return response object
|
# Return response object
|
||||||
if response:
|
if response:
|
||||||
return conn, None
|
return conn, None, None
|
||||||
|
|
||||||
# Get HTTP response
|
# Get HTTP response
|
||||||
page = conn.read()
|
page = conn.read()
|
||||||
|
@ -369,7 +369,7 @@ class Connect:
|
||||||
warnMsg = "connection timed out while trying "
|
warnMsg = "connection timed out while trying "
|
||||||
warnMsg += "to get error page information (%d)" % e.code
|
warnMsg += "to get error page information (%d)" % e.code
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
return None, None
|
return None, None, None
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -409,7 +409,7 @@ class Connect:
|
||||||
processResponse(page, responseHeaders)
|
processResponse(page, responseHeaders)
|
||||||
elif e.code == 504:
|
elif e.code == 504:
|
||||||
if ignoreTimeout:
|
if ignoreTimeout:
|
||||||
return None, None
|
return None, None, None
|
||||||
else:
|
else:
|
||||||
warnMsg = "unable to connect to the target url (%d - %s)" % (e.code, httplib.responses[e.code])
|
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:
|
if threadData.retriesCount < conf.retries and not kb.threadException and not conf.realTest:
|
||||||
|
@ -418,14 +418,14 @@ class Connect:
|
||||||
return Connect.__retryProxy(**kwargs)
|
return Connect.__retryProxy(**kwargs)
|
||||||
elif kb.testMode:
|
elif kb.testMode:
|
||||||
logger.critical(warnMsg)
|
logger.critical(warnMsg)
|
||||||
return None, None
|
return None, None, None
|
||||||
else:
|
else:
|
||||||
raise sqlmapConnectionException, warnMsg
|
raise sqlmapConnectionException, warnMsg
|
||||||
else:
|
else:
|
||||||
debugMsg = "got HTTP error code: %d (%s)" % (code, status)
|
debugMsg = "got HTTP error code: %d (%s)" % (code, status)
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
processResponse(page, responseHeaders)
|
processResponse(page, responseHeaders)
|
||||||
return page, responseHeaders
|
return page, responseHeaders, code
|
||||||
|
|
||||||
except (urllib2.URLError, socket.error, socket.timeout, httplib.BadStatusLine, httplib.IncompleteRead), e:
|
except (urllib2.URLError, socket.error, socket.timeout, httplib.BadStatusLine, httplib.IncompleteRead), e:
|
||||||
tbMsg = traceback.format_exc()
|
tbMsg = traceback.format_exc()
|
||||||
|
@ -454,16 +454,16 @@ class Connect:
|
||||||
|
|
||||||
if "forcibly closed" in tbMsg:
|
if "forcibly closed" in tbMsg:
|
||||||
logger.critical(warnMsg)
|
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"]))):
|
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:
|
elif threadData.retriesCount < conf.retries and not kb.threadException and not conf.realTest:
|
||||||
warnMsg += ", sqlmap is going to retry the request"
|
warnMsg += ", sqlmap is going to retry the request"
|
||||||
logger.critical(warnMsg)
|
logger.critical(warnMsg)
|
||||||
return Connect.__retryProxy(**kwargs)
|
return Connect.__retryProxy(**kwargs)
|
||||||
elif kb.testMode:
|
elif kb.testMode:
|
||||||
logger.critical(warnMsg)
|
logger.critical(warnMsg)
|
||||||
return None, None
|
return None, None, None
|
||||||
else:
|
else:
|
||||||
raise sqlmapConnectionException, warnMsg
|
raise sqlmapConnectionException, warnMsg
|
||||||
|
|
||||||
|
@ -485,7 +485,7 @@ class Connect:
|
||||||
|
|
||||||
logger.log(7, responseMsg)
|
logger.log(7, responseMsg)
|
||||||
|
|
||||||
return page, responseHeaders
|
return page, responseHeaders, code
|
||||||
|
|
||||||
@staticmethod
|
@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):
|
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"
|
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 headers:
|
||||||
if kb.nullConnection == NULLCONNECTION.HEAD and HTTPHEADER.CONTENT_LENGTH in 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:])
|
pageLength = int(headers[HTTPHEADER.CONTENT_RANGE][headers[HTTPHEADER.CONTENT_RANGE].find('/') + 1:])
|
||||||
|
|
||||||
if not pageLength:
|
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)
|
threadData.lastQueryDuration = calculateDeltaSeconds(start)
|
||||||
|
|
||||||
|
@ -643,8 +643,8 @@ class Connect:
|
||||||
page = removeReflectiveValues(page, payload)
|
page = removeReflectiveValues(page, payload)
|
||||||
|
|
||||||
if getRatioValue:
|
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:
|
elif pageLength or page:
|
||||||
return comparison(page, headers, getRatioValue, pageLength)
|
return comparison(page, headers, code, getRatioValue, pageLength)
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -62,7 +62,7 @@ class Web:
|
||||||
cmd = conf.osCmd
|
cmd = conf.osCmd
|
||||||
|
|
||||||
cmdUrl = "%s?cmd=%s" % (self.webBackdoorUrl, cmd)
|
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:
|
if page is not None:
|
||||||
output = re.search("<pre>(.+?)</pre>", page, re.I | re.S)
|
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.webBaseUrl = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, uriPath)
|
||||||
self.webStagerUrl = "%s/%s" % (self.webBaseUrl, stagerName)
|
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 "sqlmap file uploader" not in uplPage:
|
||||||
if localPath not in warned:
|
if localPath not in warned:
|
||||||
|
|
|
@ -109,7 +109,7 @@ def __findUnionCharCount(comment, place, parameter, value, prefix, suffix, where
|
||||||
query = agent.forgeInbandQuery('', -1, count, comment, prefix, suffix, kb.uChar)
|
query = agent.forgeInbandQuery('', -1, count, comment, prefix, suffix, kb.uChar)
|
||||||
payload = agent.payload(place=place, parameter=parameter, newValue=query, where=where)
|
payload = agent.payload(place=place, parameter=parameter, newValue=query, where=where)
|
||||||
page, headers = Request.queryPage(payload, place=place, content=True, raise404=False)
|
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)
|
ratios.append(ratio)
|
||||||
min_, max_ = min(min_, ratio), max(max_, ratio)
|
min_, max_ = min(min_, ratio), max(max_, ratio)
|
||||||
items.append((count, ratio))
|
items.append((count, ratio))
|
||||||
|
|
10
sqlmap.conf
10
sqlmap.conf
|
@ -204,12 +204,12 @@ level = 1
|
||||||
# Default: 1
|
# Default: 1
|
||||||
risk = 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.
|
# needed if the page content dynamically changes at each refresh.
|
||||||
# Refer to the user's manual for further details.
|
# Refer to the user's manual for further details.
|
||||||
string =
|
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
|
# valid, only needed if the needed if the page content dynamically changes
|
||||||
# at each refresh.
|
# at each refresh.
|
||||||
# Refer to the user's manual for further details.
|
# 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)
|
# (http://www.python.org/doc/2.5.2/lib/re-syntax.html)
|
||||||
regexp =
|
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
|
# Compare pages based only on the textual content
|
||||||
# Valid: True or False
|
# Valid: True or False
|
||||||
textOnly = False
|
textOnly = False
|
||||||
|
|
Loading…
Reference in New Issue
Block a user