From 30f8d09651274905b5868d038a5575640c590716 Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Thu, 26 Jul 2012 12:06:02 +0200 Subject: [PATCH] Implementation for an Issue #70 --- lib/controller/checks.py | 3 ++- lib/controller/controller.py | 4 ++-- lib/core/common.py | 2 +- lib/core/option.py | 8 ++++++++ lib/core/optiondict.py | 1 + lib/parse/cmdline.py | 4 ++++ lib/request/comparison.py | 12 ++++++++---- sqlmap.conf | 5 +++++ 8 files changed, 31 insertions(+), 8 deletions(-) diff --git a/lib/controller/checks.py b/lib/controller/checks.py index 96fdaa6f2..112b9e0c6 100644 --- a/lib/controller/checks.py +++ b/lib/controller/checks.py @@ -359,7 +359,7 @@ def checkSqlInjection(place, parameter, value): 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)) 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))) @@ -499,6 +499,7 @@ def checkSqlInjection(place, parameter, value): injection.conf.textOnly = conf.textOnly injection.conf.titles = conf.titles injection.conf.string = conf.string + injection.conf.notString = conf.notString injection.conf.regexp = conf.regexp injection.conf.optimize = conf.optimize diff --git a/lib/controller/controller.py b/lib/controller/controller.py index 139c5847e..984392177 100644 --- a/lib/controller/controller.py +++ b/lib/controller/controller.py @@ -357,7 +357,7 @@ def start(): 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): - 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 # a warning message to the user in case the page is not stable checkStability() @@ -527,7 +527,7 @@ def start(): errMsg += "Please, consider usage of tampering scripts as " 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 += "either a valid value for option '--string' " errMsg += "(or '--regexp')" diff --git a/lib/core/common.py b/lib/core/common.py index 17a53a4ae..344bb1669 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -2362,7 +2362,7 @@ def setOptimize(): #conf.predictOutput = True conf.keepAlive = True 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: debugMsg = "turning off --null-connection switch used indirectly by switch -o" diff --git a/lib/core/option.py b/lib/core/option.py index 39069fbeb..6a67a6ded 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -1865,6 +1865,14 @@ def __basicOptionValidation(): errMsg = "option '--string' is incompatible with switch '--null-connection'" 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: errMsg = "option '--regexp' is incompatible with switch '--null-connection'" raise sqlmapSyntaxException, errMsg diff --git a/lib/core/optiondict.py b/lib/core/optiondict.py index ee0cbb0c9..fa22c522b 100644 --- a/lib/core/optiondict.py +++ b/lib/core/optiondict.py @@ -76,6 +76,7 @@ optDict = { "level": "integer", "risk": "integer", "string": "string", + "notString": "notString", "regexp": "string", "code": "integer", "textOnly": "boolean", diff --git a/lib/parse/cmdline.py b/lib/parse/cmdline.py index 6be188db2..b9c06df89 100644 --- a/lib/parse/cmdline.py +++ b/lib/parse/cmdline.py @@ -245,6 +245,10 @@ def cmdLineParser(): help="String to match when " "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", help="Regexp to match when " "query is evaluated to True") diff --git a/lib/request/comparison.py b/lib/request/comparison.py index 3848e42eb..60efa0078 100644 --- a/lib/request/comparison.py +++ b/lib/request/comparison.py @@ -31,7 +31,7 @@ def comparison(page, headers, code=None, getRatioValue=False, pageLength=None): return _ 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 # 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 @@ -54,14 +54,18 @@ def _comparison(page, headers, code, getRatioValue, pageLength): seqMatcher = threadData.seqMatcher 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) - # 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: 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: return re.search(conf.regexp, rawResponse, re.I | re.M) is not None diff --git a/sqlmap.conf b/sqlmap.conf index 85ea6e9ed..5d8728d51 100644 --- a/sqlmap.conf +++ b/sqlmap.conf @@ -247,6 +247,11 @@ risk = 1 # Refer to the user's manual for further details. 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 # evaluated to True, only needed if the needed if the page content # dynamically changes at each refresh.