diff --git a/lib/controller/checks.py b/lib/controller/checks.py index e03b8909d..276a3379e 100644 --- a/lib/controller/checks.py +++ b/lib/controller/checks.py @@ -1034,7 +1034,7 @@ def checkStability(): delay = max(0, min(1, delay)) time.sleep(delay) - secondPage, _ = Request.queryPage(content=True, raise404=False) + secondPage, _ = Request.queryPage(content=True, noteResponseTime=False, raise404=False) if kb.redirectChoice: return None diff --git a/lib/core/common.py b/lib/core/common.py index 1f28b5f25..77fc7bfa4 100755 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -2700,7 +2700,7 @@ def parseSqliteTableSchema(value): table = {} columns = {} - for match in re.finditer(r"(\w+)[\"'`]?\s+(INT|INTEGER|TINYINT|SMALLINT|MEDIUMINT|BIGINT|UNSIGNED BIG INT|INT2|INT8|INTEGER|CHARACTER|VARCHAR|VARYING CHARACTER|NCHAR|NATIVE CHARACTER|NVARCHAR|TEXT|CLOB|TEXT|BLOB|NONE|REAL|DOUBLE|DOUBLE PRECISION|FLOAT|REAL|NUMERIC|DECIMAL|BOOLEAN|DATE|DATETIME|NUMERIC)\b", value, re.I): + for match in re.finditer(r"(\w+)[\"'`]?\s+(INT|INTEGER|TINYINT|SMALLINT|MEDIUMINT|BIGINT|UNSIGNED BIG INT|INT2|INT8|INTEGER|CHARACTER|VARCHAR|VARYING CHARACTER|NCHAR|NATIVE CHARACTER|NVARCHAR|TEXT|CLOB|LONGTEXT|BLOB|NONE|REAL|DOUBLE|DOUBLE PRECISION|FLOAT|REAL|NUMERIC|DECIMAL|BOOLEAN|DATE|DATETIME|NUMERIC)\b", value, re.I): columns[match.group(1)] = match.group(2) table[conf.tbl] = columns @@ -3770,8 +3770,12 @@ def decodeHexValue(value, raw=False): def _(value): retVal = value - if value and isinstance(value, basestring) and len(value) % 2 == 0: - retVal = hexdecode(retVal) + if value and isinstance(value, basestring): + if len(value) % 2 != 0: + retVal = "%s?" % hexdecode(value[:-1]) + singleTimeWarnMessage("there was a problem decoding value '%s' from expected hexadecimal form" % value) + else: + retVal = hexdecode(value) if not kb.binaryField and not raw: if Backend.isDbms(DBMS.MSSQL) and value.startswith("0x"): diff --git a/lib/core/convert.py b/lib/core/convert.py index 8f7123a00..26b3a49af 100644 --- a/lib/core/convert.py +++ b/lib/core/convert.py @@ -8,10 +8,13 @@ See the file 'doc/COPYING' for copying permission import base64 import json import pickle +import StringIO import sys +import types from lib.core.settings import IS_WIN from lib.core.settings import UNICODE_ENCODING +from lib.core.settings import PICKLE_REDUCE_WHITELIST def base64decode(value): """ @@ -67,10 +70,23 @@ def base64unpickle(value): retVal = None + def _(self): + if len(self.stack) > 1: + func = self.stack[-2] + if func not in PICKLE_REDUCE_WHITELIST: + raise Exception, "abusing reduce() is bad, Mkay!" + self.load_reduce() + + def loads(str): + file = StringIO.StringIO(str) + unpickler = pickle.Unpickler(file) + unpickler.dispatch[pickle.REDUCE] = _ + return unpickler.load() + try: - retVal = pickle.loads(base64decode(value)) + retVal = loads(base64decode(value)) except TypeError: - retVal = pickle.loads(base64decode(bytes(value))) + retVal = loads(base64decode(bytes(value))) return retVal diff --git a/lib/core/dump.py b/lib/core/dump.py index 058f5d9e9..15c0c14e9 100644 --- a/lib/core/dump.py +++ b/lib/core/dump.py @@ -578,7 +578,8 @@ class Dump(object): if not os.path.isdir(dumpDbPath): os.makedirs(dumpDbPath, 0755) - filepath = os.path.join(dumpDbPath, "%s-%d.bin" % (unsafeSQLIdentificatorNaming(column), randomInt(8))) + _ = re.sub(r"[^\w]", "_", normalizeUnicode(unsafeSQLIdentificatorNaming(column))) + filepath = os.path.join(dumpDbPath, "%s-%d.bin" % (_, randomInt(8))) warnMsg = "writing binary ('%s') content to file '%s' " % (mimetype, filepath) logger.warn(warnMsg) diff --git a/lib/core/option.py b/lib/core/option.py index 7fe25005d..a2804d1f5 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -1024,6 +1024,9 @@ def _setSocketPreConnect(): Makes a pre-connect version of socket.connect """ + if conf.disablePrecon: + return + def _(): while kb.threadContinue: try: @@ -1373,7 +1376,7 @@ def _setHTTPExtraHeaders(): errMsg = "invalid header value: %s. Valid header format is 'name:value'" % repr(headerValue).lstrip('u') raise SqlmapSyntaxException(errMsg) - elif not conf.httpHeaders or len(conf.httpHeaders) == 1: + elif not conf.requestFile and len(conf.httpHeaders or []) < 2: conf.httpHeaders.append((HTTP_HEADER.ACCEPT_LANGUAGE, "en-us,en;q=0.5")) if not conf.charset: conf.httpHeaders.append((HTTP_HEADER.ACCEPT_CHARSET, "ISO-8859-15,utf-8;q=0.7,*;q=0.7")) @@ -1573,7 +1576,7 @@ def _cleanupOptions(): conf.progressWidth = width - 46 for key, value in conf.items(): - if value and any(key.endswith(_) for _ in ("Path", "File")): + if value and any(key.endswith(_) for _ in ("Path", "File", "Dir")): conf[key] = safeExpandUser(value) if conf.testParameter: @@ -1894,7 +1897,7 @@ def _setKnowledgeBaseAttributes(flushAll=True): kb.safeReq = AttribDict() kb.singleLogFlags = set() kb.reduceTests = None - kb.tlsSNI = None + kb.tlsSNI = {} kb.stickyDBMS = False kb.stickyLevel = None kb.storeCrawlingChoice = None diff --git a/lib/core/optiondict.py b/lib/core/optiondict.py index 9eb0d121a..5f1bd1fea 100644 --- a/lib/core/optiondict.py +++ b/lib/core/optiondict.py @@ -227,6 +227,7 @@ optDict = { }, "Hidden": { "dummy": "boolean", + "disablePrecon": "boolean", "binaryFields": "string", "profile": "boolean", "cpuThrottle": "integer", diff --git a/lib/core/profiling.py b/lib/core/profiling.py index c212a0bb5..e93f6b80b 100644 --- a/lib/core/profiling.py +++ b/lib/core/profiling.py @@ -87,5 +87,4 @@ def profile(profileOutputFile=None, dotOutputFile=None, imageOutputFile=None): win.connect('destroy', gtk.main_quit) win.set_filter("dot") win.open_file(dotOutputFile) - gobject.timeout_add(1000, win.update, dotOutputFile) gtk.main() diff --git a/lib/core/settings.py b/lib/core/settings.py index bf5439130..654049134 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -11,7 +11,9 @@ import subprocess import string import sys import time +import types +from lib.core.datatype import AttribDict from lib.core.enums import DBMS from lib.core.enums import DBMS_DIRECTORY_NAME from lib.core.enums import OS @@ -427,6 +429,8 @@ HTML_TITLE_REGEX = "(?P<result>[^<]+)" # Table used for Base64 conversion in WordPress hash cracking routine ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" +PICKLE_REDUCE_WHITELIST = (types.BooleanType, types.DictType, types.FloatType, types.IntType, types.ListType, types.LongType, types.NoneType, types.StringType, types.TupleType, types.UnicodeType, types.XRangeType, type(AttribDict()), type(set())) + # Chars used to quickly distinguish if the user provided tainted parameter values DUMMY_SQL_INJECTION_CHARS = ";()'" @@ -503,7 +507,7 @@ DEFAULT_COOKIE_DELIMITER = ';' FORCE_COOKIE_EXPIRATION_TIME = "9999999999" # Github OAuth token used for creating an automatic Issue for unhandled exceptions -GITHUB_REPORT_OAUTH_TOKEN = "YzQzM2M2YzgzMDExN2I5ZDMyYjAzNTIzODIwZDA2MDFmMmVjODI1Ng==" +GITHUB_REPORT_OAUTH_TOKEN = "YzNkYTgyMTdjYzdjNjZjMjFjMWE5ODI5OGQyNzk2ODM1M2M0MzUyOA==" # Skip unforced HashDB flush requests below the threshold number of cached items HASHDB_FLUSH_THRESHOLD = 32 @@ -589,6 +593,12 @@ EVENTVALIDATION_REGEX = r'(?i)(?P__EVENTVALIDATION[^"]*)[^>]+value="(?P