diff --git a/data/xml/errors.xml b/data/xml/errors.xml index f32b82734..ae17201d7 100644 --- a/data/xml/errors.xml +++ b/data/xml/errors.xml @@ -7,7 +7,7 @@ - + @@ -15,6 +15,10 @@ + + + + diff --git a/lib/core/agent.py b/lib/core/agent.py index 98a0abb2e..0b66e728d 100644 --- a/lib/core/agent.py +++ b/lib/core/agent.py @@ -13,6 +13,7 @@ from lib.core.common import filterNone from lib.core.common import getSQLSnippet from lib.core.common import getTechnique from lib.core.common import getTechniqueData +from lib.core.common import hashDBRetrieve from lib.core.common import isDBMSVersionAtLeast from lib.core.common import isNumber from lib.core.common import isTechniqueAvailable @@ -34,6 +35,8 @@ from lib.core.data import queries from lib.core.dicts import DUMP_DATA_PREPROCESS from lib.core.dicts import FROM_DUMMY_TABLE from lib.core.enums import DBMS +from lib.core.enums import FORK +from lib.core.enums import HASHDB_KEYS from lib.core.enums import HTTP_HEADER from lib.core.enums import PAYLOAD from lib.core.enums import PLACE @@ -381,6 +384,11 @@ class Agent(object): for _ in set(re.findall(r"\[RANDSTR(?:\d+)?\]", payload, re.I)): payload = payload.replace(_, randomStr()) + if hashDBRetrieve(HASHDB_KEYS.DBMS_FORK) == FORK.MEMSQL: + payload = re.sub(r"(?i)\bORD\(", "ASCII(", payload) + payload = re.sub(r"(?i)\bMID\(", "SUBSTR(", payload) + payload = re.sub(r"(?i)\bNCHAR\b", "CHAR", payload) + return payload def getComment(self, request): diff --git a/lib/core/enums.py b/lib/core/enums.py index b429cd895..6ed406fb9 100644 --- a/lib/core/enums.py +++ b/lib/core/enums.py @@ -65,6 +65,10 @@ class DBMS_DIRECTORY_NAME(object): MONETDB = "monetdb" DERBY = "derby" +class FORK(object): + MARIADB = "MariaDB" + MEMSQL = "MemSQL" + class CUSTOM_LOGGING(object): PAYLOAD = 9 TRAFFIC_OUT = 8 diff --git a/lib/core/option.py b/lib/core/option.py index 3400e1612..fbc2981a1 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -1919,6 +1919,7 @@ def _setKnowledgeBaseAttributes(flushAll=True): kb.forcePartialUnion = False kb.forceThreads = None kb.forceWhere = None + kb.forkNote = None kb.futileUnion = None kb.heavilyDynamic = False kb.headersFile = None diff --git a/lib/core/settings.py b/lib/core/settings.py index cb6214364..e4d2fe0d8 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -18,7 +18,7 @@ from lib.core.enums import OS from thirdparty.six import unichr as _unichr # sqlmap version (...) -VERSION = "1.4.1.30" +VERSION = "1.4.1.31" 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) @@ -262,7 +262,7 @@ MONETDB_SYSTEM_DBS = ("tmp", "json", "profiler") DERBY_SYSTEM_DBS = ("NULLID", "SQLJ", "SYS", "SYSCAT", "SYSCS_DIAG", "SYSCS_UTIL", "SYSFUN", "SYSIBM", "SYSPROC", "SYSSTAT") MSSQL_ALIASES = ("microsoft sql server", "mssqlserver", "mssql", "ms") -MYSQL_ALIASES = ("mysql", "my", "mariadb", "maria") +MYSQL_ALIASES = ("mysql", "my") + ("mariadb", "maria", "memsql") PGSQL_ALIASES = ("postgresql", "postgres", "pgsql", "psql", "pg") ORACLE_ALIASES = ("oracle", "orcl", "ora", "or") SQLITE_ALIASES = ("sqlite", "sqlite3") diff --git a/lib/parse/html.py b/lib/parse/html.py index 9357ab39f..68fe55621 100644 --- a/lib/parse/html.py +++ b/lib/parse/html.py @@ -52,6 +52,7 @@ class HTMLHandler(ContentHandler): if kb.cache.regex[regexp] in self._lower_page and re.search(regexp, self._urldecoded_page, re.I): self.dbms = self._dbms self._markAsErrorPage() + kb.forkNote = kb.forkNote or attrs.get("fork") def htmlParser(page): """ diff --git a/plugins/dbms/mysql/fingerprint.py b/plugins/dbms/mysql/fingerprint.py index 228ba311a..367b5969e 100644 --- a/plugins/dbms/mysql/fingerprint.py +++ b/plugins/dbms/mysql/fingerprint.py @@ -17,6 +17,7 @@ from lib.core.data import conf from lib.core.data import kb from lib.core.data import logger from lib.core.enums import DBMS +from lib.core.enums import FORK from lib.core.enums import HASHDB_KEYS from lib.core.enums import OS from lib.core.session import setDbms @@ -175,6 +176,13 @@ class Fingerprint(GenericFingerprint): result = inject.checkBooleanExpression("SESSION_USER() LIKE USER()") + if not result: + # Note: MemSQL doesn't support SESSION_USER() + result = inject.checkBooleanExpression("GEOGRAPHY_AREA(NULL) IS NULL") + + if result: + hashDBWrite(HASHDB_KEYS.DBMS_FORK, FORK.MEMSQL) + if not result: warnMsg = "the back-end DBMS is not %s" % DBMS.MYSQL logger.warn(warnMsg) @@ -182,7 +190,7 @@ class Fingerprint(GenericFingerprint): return False if hashDBRetrieve(HASHDB_KEYS.DBMS_FORK) is None: - hashDBWrite(HASHDB_KEYS.DBMS_FORK, inject.checkBooleanExpression("VERSION() LIKE '%MariaDB%'") and "MariaDB" or "") + hashDBWrite(HASHDB_KEYS.DBMS_FORK, inject.checkBooleanExpression("VERSION() LIKE '%MariaDB%'") and FORK.MARIADB or "") # reading information_schema on some platforms is causing annoying timeout exits # Reference: http://bugs.mysql.com/bug.php?id=15855