Implementation for an Issue #70

This commit is contained in:
Miroslav Stampar 2012-07-26 12:06:02 +02:00
parent 57f2fccc24
commit 30f8d09651
8 changed files with 31 additions and 8 deletions

View File

@ -359,7 +359,7 @@ def checkSqlInjection(place, parameter, value):
injectable = True injectable = True
if not injectable and not conf.string and kb.pageStable: if not injectable and not any((conf.string, conf.notString, conf.regexp)) and kb.pageStable:
trueSet = set(extractTextTagContent(truePage)) trueSet = set(extractTextTagContent(truePage))
falseSet = set(extractTextTagContent(falsePage)) falseSet = set(extractTextTagContent(falsePage))
candidates = filter(None, (_.strip() if _.strip() in (kb.pageTemplate or "") and _.strip() not in falsePage else None for _ in (trueSet - falseSet))) candidates = filter(None, (_.strip() if _.strip() in (kb.pageTemplate or "") and _.strip() not in falsePage else None for _ in (trueSet - falseSet)))
@ -499,6 +499,7 @@ def checkSqlInjection(place, parameter, value):
injection.conf.textOnly = conf.textOnly injection.conf.textOnly = conf.textOnly
injection.conf.titles = conf.titles injection.conf.titles = conf.titles
injection.conf.string = conf.string injection.conf.string = conf.string
injection.conf.notString = conf.notString
injection.conf.regexp = conf.regexp injection.conf.regexp = conf.regexp
injection.conf.optimize = conf.optimize injection.conf.optimize = conf.optimize

View File

@ -357,7 +357,7 @@ def start():
if (len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None)) \ if (len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None)) \
and (kb.injection.place is None or kb.injection.parameter is None): and (kb.injection.place is None or kb.injection.parameter is None):
if not conf.string and not conf.regexp and PAYLOAD.TECHNIQUE.BOOLEAN in conf.tech: if not any((conf.string, conf.notString, conf.regexp)) and PAYLOAD.TECHNIQUE.BOOLEAN in conf.tech:
# NOTE: this is not needed anymore, leaving only to display # NOTE: this is not needed anymore, leaving only to display
# a warning message to the user in case the page is not stable # a warning message to the user in case the page is not stable
checkStability() checkStability()
@ -527,7 +527,7 @@ def start():
errMsg += "Please, consider usage of tampering scripts as " errMsg += "Please, consider usage of tampering scripts as "
errMsg += "your target might filter the queries." errMsg += "your target might filter the queries."
if not conf.string and not conf.regexp: if not conf.string and not conf.notString and not conf.regexp:
errMsg += " Also, you can try to rerun by providing " errMsg += " Also, you can try to rerun by providing "
errMsg += "either a valid value for option '--string' " errMsg += "either a valid value for option '--string' "
errMsg += "(or '--regexp')" errMsg += "(or '--regexp')"

View File

@ -2362,7 +2362,7 @@ def setOptimize():
#conf.predictOutput = True #conf.predictOutput = True
conf.keepAlive = True conf.keepAlive = True
conf.threads = 3 if conf.threads < 3 else conf.threads conf.threads = 3 if conf.threads < 3 else conf.threads
conf.nullConnection = not any([conf.data, conf.textOnly, conf.titles, conf.string, conf.regexp, conf.tor]) conf.nullConnection = not any([conf.data, conf.textOnly, conf.titles, conf.string, conf.notString, conf.regexp, conf.tor])
if not conf.nullConnection: if not conf.nullConnection:
debugMsg = "turning off --null-connection switch used indirectly by switch -o" debugMsg = "turning off --null-connection switch used indirectly by switch -o"

View File

@ -1865,6 +1865,14 @@ def __basicOptionValidation():
errMsg = "option '--string' is incompatible with switch '--null-connection'" errMsg = "option '--string' is incompatible with switch '--null-connection'"
raise sqlmapSyntaxException, errMsg raise sqlmapSyntaxException, errMsg
if conf.notString and conf.nullConnection:
errMsg = "option '--not-string' is incompatible with switch '--null-connection'"
raise sqlmapSyntaxException, errMsg
if conf.string and conf.notString:
errMsg = "option '--string' is incompatible with switch '--not-string'"
raise sqlmapSyntaxException, errMsg
if conf.regexp and conf.nullConnection: if conf.regexp and conf.nullConnection:
errMsg = "option '--regexp' is incompatible with switch '--null-connection'" errMsg = "option '--regexp' is incompatible with switch '--null-connection'"
raise sqlmapSyntaxException, errMsg raise sqlmapSyntaxException, errMsg

View File

@ -76,6 +76,7 @@ optDict = {
"level": "integer", "level": "integer",
"risk": "integer", "risk": "integer",
"string": "string", "string": "string",
"notString": "notString",
"regexp": "string", "regexp": "string",
"code": "integer", "code": "integer",
"textOnly": "boolean", "textOnly": "boolean",

View File

@ -245,6 +245,10 @@ def cmdLineParser():
help="String to match when " help="String to match when "
"query is evaluated to True") "query is evaluated to True")
detection.add_option("--not-string", dest="notString",
help="String to match when "
"query is evaluated to False")
detection.add_option("--regexp", dest="regexp", detection.add_option("--regexp", dest="regexp",
help="Regexp to match when " help="Regexp to match when "
"query is evaluated to True") "query is evaluated to True")

View File

@ -31,7 +31,7 @@ def comparison(page, headers, code=None, getRatioValue=False, pageLength=None):
return _ return _
def _adjust(condition, getRatioValue): def _adjust(condition, getRatioValue):
if not any([conf.string, conf.regexp, conf.code]): if not any([conf.string, conf.notString, conf.regexp, conf.code]):
# Negative logic approach is used in raw page comparison scheme as that what is "different" than original # Negative logic approach is used in raw page comparison scheme as that what is "different" than original
# PAYLOAD.WHERE.NEGATIVE response is considered as True; in switch based approach negative logic is not # PAYLOAD.WHERE.NEGATIVE response is considered as True; in switch based approach negative logic is not
# applied as that what is by user considered as True is that what is returned by the comparison mechanism # applied as that what is by user considered as True is that what is returned by the comparison mechanism
@ -54,14 +54,18 @@ def _comparison(page, headers, code, getRatioValue, pageLength):
seqMatcher = threadData.seqMatcher seqMatcher = threadData.seqMatcher
seqMatcher.set_seq1(kb.pageTemplate) seqMatcher.set_seq1(kb.pageTemplate)
if any([conf.string, conf.regexp]): if any([conf.string, conf.notString, conf.regexp]):
rawResponse = "%s%s" % (listToStrValue(headers.headers if headers else ""), page) rawResponse = "%s%s" % (listToStrValue(headers.headers if headers else ""), page)
# String to match in page when the query is valid # String to match in page when the query is True and/or valid
if conf.string: if conf.string:
return conf.string in rawResponse return conf.string in rawResponse
# Regular expression to match in page when the query is valid # String to match in page when the query is False and/or invalid
if conf.notString:
return conf.notString not in rawResponse
# Regular expression to match in page when the query is True and/or valid
if conf.regexp: if conf.regexp:
return re.search(conf.regexp, rawResponse, re.I | re.M) is not None return re.search(conf.regexp, rawResponse, re.I | re.M) is not None

View File

@ -247,6 +247,11 @@ risk = 1
# Refer to the user's manual for further details. # Refer to the user's manual for further details.
string = string =
# String to match within the raw response when the query is evaluated to
# False, only needed if the page content dynamically changes at each refresh.
# Refer to the user's manual for further details.
notString =
# Regular expression to match within the raw response when the query is # Regular expression to match within the raw response when the query is
# evaluated to True, only needed if the needed if the page content # evaluated to True, only needed if the needed if the page content
# dynamically changes at each refresh. # dynamically changes at each refresh.