From 6fc41ca940738634bac477bae58c5b73f6b305a5 Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Tue, 6 Jan 2015 14:01:47 +0100 Subject: [PATCH] Heuristically checking for WAF/IDS/IPS by default --- lib/controller/checks.py | 42 +++++++++--------------------------- lib/controller/controller.py | 3 +-- lib/core/optiondict.py | 1 - lib/core/settings.py | 3 +++ lib/parse/cmdline.py | 4 ---- sqlmap.conf | 4 ---- 6 files changed, 14 insertions(+), 43 deletions(-) diff --git a/lib/controller/checks.py b/lib/controller/checks.py index f2afacd4a..a2984e00d 100644 --- a/lib/controller/checks.py +++ b/lib/controller/checks.py @@ -59,6 +59,7 @@ from lib.core.exception import SqlmapConnectionException from lib.core.exception import SqlmapNoneDataException from lib.core.exception import SqlmapSilentQuitException from lib.core.exception import SqlmapUserQuitException +from lib.core.settings import DEFAULT_GET_POST_DELIMITER from lib.core.settings import DUMMY_XSS_CHECK_APPENDIX from lib.core.settings import FORMAT_EXCEPTION_STRINGS from lib.core.settings import HEURISTIC_CHECK_ALPHABET @@ -68,6 +69,7 @@ from lib.core.settings import URI_HTTP_HEADER from lib.core.settings import LOWER_RATIO_BOUND from lib.core.settings import UPPER_RATIO_BOUND from lib.core.settings import IDS_WAF_CHECK_PAYLOAD +from lib.core.settings import IDS_WAF_CHECK_RATIO from lib.core.threads import getCurrentThreadData from lib.request.connect import Connect as Request from lib.request.inject import checkBooleanExpression @@ -1094,56 +1096,32 @@ def checkWaf(): Reference: http://seclists.org/nmap-dev/2011/q2/att-1005/http-waf-detect.nse """ - if not conf.checkWaf: - return False - infoMsg = "heuristically checking if the target is protected by " infoMsg += "some kind of WAF/IPS/IDS" logger.info(infoMsg) retVal = False - backup = dict(conf.parameters) - payload = "%d %s" % (randomInt(), IDS_WAF_CHECK_PAYLOAD) conf.parameters = dict(backup) - conf.parameters[PLACE.GET] = "" if not conf.parameters.get(PLACE.GET) else conf.parameters[PLACE.GET] + "&" + conf.parameters[PLACE.GET] = "" if not conf.parameters.get(PLACE.GET) else conf.parameters[PLACE.GET] + DEFAULT_GET_POST_DELIMITER conf.parameters[PLACE.GET] += "%s=%s" % (randomStr(), payload) logger.log(CUSTOM_LOGGING.PAYLOAD, payload) - kb.matchRatio = None - Request.queryPage() - - if kb.errorIsNone and kb.matchRatio is None: - kb.matchRatio = LOWER_RATIO_BOUND - - conf.parameters = dict(backup) - conf.parameters[PLACE.GET] = "" if not conf.parameters.get(PLACE.GET) else conf.parameters[PLACE.GET] + "&" - conf.parameters[PLACE.GET] += "%s=%d" % (randomStr(), randomInt()) - - trueResult = Request.queryPage() - - if trueResult: + try: + retVal = Request.queryPage(getRatioValue=True, noteResponseTime=False, silent=True)[1] < IDS_WAF_CHECK_RATIO + except SqlmapConnectionException: + retVal = True + finally: + kb.matchRatio = None conf.parameters = dict(backup) - conf.parameters[PLACE.GET] = "" if not conf.parameters.get(PLACE.GET) else conf.parameters[PLACE.GET] + "&" - conf.parameters[PLACE.GET] += "%s=%d %s" % (randomStr(), randomInt(), IDS_WAF_CHECK_PAYLOAD) - - try: - falseResult = Request.queryPage() - except SqlmapConnectionException: - falseResult = None - - if not falseResult: - retVal = True - - conf.parameters = dict(backup) if retVal: warnMsg = "it appears that the target is protected. Please " warnMsg += "consider usage of tamper scripts (option '--tamper')" - logger.warn(warnMsg) + logger.critical(warnMsg) else: infoMsg = "it appears that the target is not protected" logger.info(infoMsg) diff --git a/lib/controller/controller.py b/lib/controller/controller.py index 6795b76f4..3951ba168 100644 --- a/lib/controller/controller.py +++ b/lib/controller/controller.py @@ -372,8 +372,7 @@ def start(): if not checkConnection(suppressOutput=conf.forms) or not checkString() or not checkRegexp(): continue - if conf.checkWaf: - checkWaf() + checkWaf() if conf.identifyWaf: identifyWaf() diff --git a/lib/core/optiondict.py b/lib/core/optiondict.py index d637aa817..3c09adeda 100644 --- a/lib/core/optiondict.py +++ b/lib/core/optiondict.py @@ -209,7 +209,6 @@ optDict = { "alert": "string", "answers": "string", "beep": "boolean", - "checkWaf": "boolean", "cleanup": "boolean", "dependencies": "boolean", "disableColoring": "boolean", diff --git a/lib/core/settings.py b/lib/core/settings.py index 6cdae1b66..0dbc41c5d 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -40,6 +40,9 @@ BANNER = """\033[01;33m _ DIFF_TOLERANCE = 0.05 CONSTANT_RATIO = 0.9 +# Ratio used in heuristic check for WAF/IDS/IPS protected targets +IDS_WAF_CHECK_RATIO = 0.5 + # Lower and upper values for match ratio in case of stable page LOWER_RATIO_BOUND = 0.02 UPPER_RATIO_BOUND = 0.98 diff --git a/lib/parse/cmdline.py b/lib/parse/cmdline.py index 3b33f8160..ef3112aec 100644 --- a/lib/parse/cmdline.py +++ b/lib/parse/cmdline.py @@ -676,10 +676,6 @@ def cmdLineParser(): miscellaneous.add_option("--beep", dest="beep", action="store_true", help="Make a beep sound when SQL injection is found") - miscellaneous.add_option("--check-waf", dest="checkWaf", - action="store_true", - help="Heuristically check for WAF/IPS/IDS protection") - miscellaneous.add_option("--cleanup", dest="cleanup", action="store_true", help="Clean up the DBMS from sqlmap specific " diff --git a/sqlmap.conf b/sqlmap.conf index 6a2fad0b8..cc506987d 100644 --- a/sqlmap.conf +++ b/sqlmap.conf @@ -718,10 +718,6 @@ beep = False # Valid: True or False checkPayload = False -# Heuristically check for WAF/IPS/IDS protection. -# Valid: True or False -checkWaf = False - # Clean up the DBMS from sqlmap specific UDF and tables. # Valid: True or False cleanup = False