diff --git a/lib/controller/checks.py b/lib/controller/checks.py index 9bb3d4277..00a320661 100644 --- a/lib/controller/checks.py +++ b/lib/controller/checks.py @@ -7,10 +7,12 @@ See the file 'doc/COPYING' for copying permission import copy import httplib +import os import random import re import socket import subprocess +import tempfile import time from extra.beep.beep import beep @@ -30,6 +32,7 @@ from lib.core.common import hashDBRetrieve from lib.core.common import hashDBWrite from lib.core.common import intersect from lib.core.common import listToStrValue +from lib.core.common import openFile from lib.core.common import parseFilePaths from lib.core.common import popValue from lib.core.common import pushValue @@ -55,6 +58,7 @@ from lib.core.enums import HASHDB_KEYS from lib.core.enums import HEURISTIC_TEST from lib.core.enums import HTTP_HEADER from lib.core.enums import HTTPMETHOD +from lib.core.enums import MKSTEMP_PREFIX from lib.core.enums import NOTE from lib.core.enums import NULLCONNECTION from lib.core.enums import PAYLOAD @@ -1384,6 +1388,18 @@ def identifyWaf(): retVal.append(product) if retVal: + if kb.wafSpecificResponse and len(retVal) == 1 and "unknown" in retVal[0].lower(): + handle, filename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.SPECIFIC_RESPONSE) + os.close(handle) + with openFile(filename, "w+b") as f: + f.write(kb.wafSpecificResponse) + + message = "WAF/IPS/IDS specific response can be found in '%s'. " % filename + message += "If you know the details on used protection please " + message += "report it along with specific response " + message += "to 'dev@sqlmap.org'" + logger.warn(message) + message = "are you sure that you want to " message += "continue with further target testing? [y/N] " choice = readInput(message, default='N', boolean=True) diff --git a/lib/core/enums.py b/lib/core/enums.py index 9339b8ed4..9596fa00a 100644 --- a/lib/core/enums.py +++ b/lib/core/enums.py @@ -369,6 +369,7 @@ class MKSTEMP_PREFIX: RESULTS = "sqlmapresults-" COOKIE_JAR = "sqlmapcookiejar-" BIG_ARRAY = "sqlmapbigarray-" + SPECIFIC_RESPONSE = "sqlmapresponse-" class TIMEOUT_STATE: NORMAL = 0 diff --git a/lib/core/option.py b/lib/core/option.py index 5243be847..4b6d15629 100755 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -2019,6 +2019,7 @@ def _setKnowledgeBaseAttributes(flushAll=True): kb.tableExistsChoice = None kb.uChar = NULL kb.unionDuplicates = False + kb.wafSpecificResponse = None kb.xpCmdshellAvailable = False if flushAll: diff --git a/lib/core/settings.py b/lib/core/settings.py index 9c10bf414..dac2dead6 100755 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -19,7 +19,7 @@ from lib.core.enums import DBMS_DIRECTORY_NAME from lib.core.enums import OS # sqlmap version (...) -VERSION = "1.1.7.22" +VERSION = "1.1.7.23" TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable" TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34} VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE) @@ -633,7 +633,7 @@ VALID_TIME_CHARS_RUN_THRESHOLD = 100 CHECK_ZERO_COLUMNS_THRESHOLD = 10 # Boldify all logger messages containing these "patterns" -BOLD_PATTERNS = ("' injectable", "provided empty", "leftover chars", "might be injectable", "' is vulnerable", "is not injectable", "does not seem to be", "test failed", "test passed", "live test final result", "test shows that", "the back-end DBMS is", "created Github", "blocked by the target server", "protection is involved", "CAPTCHA") +BOLD_PATTERNS = ("' injectable", "provided empty", "leftover chars", "might be injectable", "' is vulnerable", "is not injectable", "does not seem to be", "test failed", "test passed", "live test final result", "test shows that", "the back-end DBMS is", "created Github", "blocked by the target server", "protection is involved", "CAPTCHA", "specific response") # Generic www root directory names GENERIC_DOC_ROOT_DIRECTORY_NAMES = ("htdocs", "httpdocs", "public", "wwwroot", "www") diff --git a/txt/checksum.md5 b/txt/checksum.md5 index c598aed8a..bbba4e9c5 100644 --- a/txt/checksum.md5 +++ b/txt/checksum.md5 @@ -21,7 +21,7 @@ c55b400b72acc43e0e59c87dd8bb8d75 extra/shellcodeexec/windows/shellcodeexec.x32. 310efc965c862cfbd7b0da5150a5ad36 extra/sqlharvest/__init__.py 7713aa366c983cdf1f3dbaa7383ea9e1 extra/sqlharvest/sqlharvest.py 7afe836fd97271ccba67b4c0da2482ff lib/controller/action.py -e711f036d9c561cdb04aec62f872e170 lib/controller/checks.py +2f410ced3f93932699a046c1b704ef3b lib/controller/checks.py a66093c734c7f94ecdf94d882c2d8b89 lib/controller/controller.py a97df93b552ee4e4ba3692eae870de7c lib/controller/handler.py 310efc965c862cfbd7b0da5150a5ad36 lib/controller/__init__.py @@ -35,18 +35,18 @@ a8143dab9d3a27490f7d49b6b29ea530 lib/core/data.py 94b06df2dfd9f6c7a2ad3f04a846b686 lib/core/defaults.py 7309cf449b009723d1a4655fcf1a96d7 lib/core/dicts.py 65b9187de3d8c9c28ddab53ef2b399bc lib/core/dump.py -b9ff4e622c416116bee6024c0f050349 lib/core/enums.py +c8553b821a2089cb8ddd39ae661f25fc lib/core/enums.py a44d7a4cc6c9a67a72d6af2f25f4ddac lib/core/exception.py 310efc965c862cfbd7b0da5150a5ad36 lib/core/__init__.py 9ba39bf66e9ecd469446bdbbeda906c3 lib/core/log.py 5a34a1be62eab520cacc197b5eacda39 lib/core/optiondict.py -f664e993a4e4d0f8b3153778bec49794 lib/core/option.py +fbf750dc617c3549ee423d6c2334ba4d lib/core/option.py 5f2f56e6c5f274408df61943f1e080c0 lib/core/profiling.py 40be71cd774662a7b420caeb7051e7d5 lib/core/readlineng.py d8e9250f3775119df07e9070eddccd16 lib/core/replication.py 785f86e3f963fa3798f84286a4e83ff2 lib/core/revision.py 40c80b28b3a5819b737a5a17d4565ae9 lib/core/session.py -abde6355f9cd07ba43b7f35b3068eb1f lib/core/settings.py +947bd803e9e364f0511cace7f4fb97dc lib/core/settings.py d91291997d2bd2f6028aaf371bf1d3b6 lib/core/shell.py 2ad85c130cc5f2b3701ea85c2f6bbf20 lib/core/subprocessng.py 080dad10c8350a66fd5321935b53fa70 lib/core/target.py @@ -402,7 +402,7 @@ ab6f6e3169cb43efcf5b6ed84b58252f waf/comodo.py e4b058d759198216d24f8fed6ef97be4 waf/edgecast.py f633953970fb181b9ac5420a47e6a610 waf/expressionengine.py 1df78b6ad49259514cb6e4d68371cbcf waf/fortiweb.py -ef151fbc34f16620958ba61dd415ae59 waf/generic.py +a63bc52b39a7fac38a8a3adee1545851 waf/generic.py d50e17ed49e1a3cb846e652ed98e3b3c waf/hyperguard.py 5b5382ccfb82ee6afdc1b47c8a4bce70 waf/incapsula.py 310efc965c862cfbd7b0da5150a5ad36 waf/__init__.py diff --git a/waf/generic.py b/waf/generic.py index 26c3ec2b3..e8e7c7287 100644 --- a/waf/generic.py +++ b/waf/generic.py @@ -5,6 +5,7 @@ Copyright (c) 2006-2017 sqlmap developers (http://sqlmap.org/) See the file 'doc/COPYING' for copying permission """ +from lib.core.option import kb from lib.core.settings import IDS_WAF_CHECK_PAYLOAD from lib.core.settings import WAF_ATTACK_VECTORS @@ -13,7 +14,7 @@ __product__ = "Generic (Unknown)" def detect(get_page): retval = False - page, _, code = get_page() + page, headers, code = get_page() if page is None or code >= 400: return False @@ -21,6 +22,7 @@ def detect(get_page): page, _, code = get_page(get=vector) if code >= 400 or IDS_WAF_CHECK_PAYLOAD in vector and code is None: + kb.wafSpecificResponse = "HTTP/1.1 %s\n%s\n%s" % (code, "".join(_ for _ in headers.headers or [] if not _.startswith("URI")), page) retval = True break