minor refactoring, added possibility to compare the remote file and downloaded file (--file-read), prepping for #223

This commit is contained in:
Bernardo Damele 2012-12-18 17:49:18 +00:00
parent 9a1eca20b5
commit 8d9aa2c384
4 changed files with 54 additions and 36 deletions

View File

@ -343,7 +343,7 @@ class Filesystem(GenericFilesystem):
self._stackedWriteFileVbs(tmpPath, wFileContent, dFile, fileType) self._stackedWriteFileVbs(tmpPath, wFileContent, dFile, fileType)
sameFile = self.askCheckWrittenFile(wFile, dFile, fileType) sameFile = self.askCheckWrittenFile(wFile, dFile)
if sameFile is False: if sameFile is False:
message = "do you want to try to upload the file with " message = "do you want to try to upload the file with "
@ -353,3 +353,4 @@ class Filesystem(GenericFilesystem):
if not choice or choice.lower() == "y": if not choice or choice.lower() == "y":
self._stackedWriteFileDebugExe(tmpPath, wFile, wFileContent, dFile, fileType) self._stackedWriteFileDebugExe(tmpPath, wFile, wFileContent, dFile, fileType)
#self._stackedWriteFilePS(tmpPath, wFileContent, dFile, fileType) #self._stackedWriteFilePS(tmpPath, wFileContent, dFile, fileType)
self.askCheckWrittenFile(wFile, dFile)

View File

@ -100,7 +100,7 @@ class Filesystem(GenericFilesystem):
sqlQuery = "%s INTO DUMPFILE '%s'" % (fcEncodedStr, dFile) sqlQuery = "%s INTO DUMPFILE '%s'" % (fcEncodedStr, dFile)
unionUse(sqlQuery, unpack=False) unionUse(sqlQuery, unpack=False)
self.askCheckWrittenFile(wFile, dFile, fileType) self.askCheckWrittenFile(wFile, dFile)
warnMsg = "expect junk characters inside the " warnMsg = "expect junk characters inside the "
warnMsg += "file as a leftover from UNION query" warnMsg += "file as a leftover from UNION query"
@ -133,4 +133,4 @@ class Filesystem(GenericFilesystem):
# Reference: http://dev.mysql.com/doc/refman/5.1/en/select.html # Reference: http://dev.mysql.com/doc/refman/5.1/en/select.html
inject.goStacked("SELECT %s FROM %s INTO DUMPFILE '%s'" % (self.tblField, self.fileTblName, dFile), silent=True) inject.goStacked("SELECT %s FROM %s INTO DUMPFILE '%s'" % (self.tblField, self.fileTblName, dFile), silent=True)
self.askCheckWrittenFile(wFile, dFile, fileType) self.askCheckWrittenFile(wFile, dFile)

View File

@ -110,6 +110,6 @@ class Filesystem(GenericFilesystem):
# (pg_largeobject 'data' field) # (pg_largeobject 'data' field)
inject.goStacked("SELECT lo_export(%d, '%s')" % (self.oid, dFile), silent=True) inject.goStacked("SELECT lo_export(%d, '%s')" % (self.oid, dFile), silent=True)
self.askCheckWrittenFile(wFile, dFile, fileType) self.askCheckWrittenFile(wFile, dFile)
inject.goStacked("SELECT lo_unlink(%d)" % self.oid) inject.goStacked("SELECT lo_unlink(%d)" % self.oid)

View File

@ -36,40 +36,44 @@ class Filesystem:
self.fileTblName = "sqlmapfile" self.fileTblName = "sqlmapfile"
self.tblField = "data" self.tblField = "data"
def _checkWrittenFile(self, wFile, dFile, fileType): def _checkFileLength(self, localFile, remoteFile, fileRead=False):
if Backend.isDbms(DBMS.MYSQL): if Backend.isDbms(DBMS.MYSQL):
lengthQuery = "SELECT LENGTH(LOAD_FILE('%s'))" % dFile lengthQuery = "SELECT LENGTH(LOAD_FILE('%s'))" % remoteFile
elif Backend.isDbms(DBMS.PGSQL): elif Backend.isDbms(DBMS.PGSQL):
if fileRead:
lengthQuery = True
else:
lengthQuery = "SELECT LENGTH(data) FROM pg_largeobject WHERE loid=%d" % self.oid lengthQuery = "SELECT LENGTH(data) FROM pg_largeobject WHERE loid=%d" % self.oid
elif Backend.isDbms(DBMS.MSSQL): elif Backend.isDbms(DBMS.MSSQL):
self.createSupportTbl(self.fileTblName, self.tblField, "text") self.createSupportTbl(self.fileTblName, self.tblField, "text")
# Reference: http://msdn.microsoft.com/en-us/library/ms188365.aspx # Reference: http://msdn.microsoft.com/en-us/library/ms188365.aspx
inject.goStacked("BULK INSERT %s FROM '%s' WITH (CODEPAGE='RAW', FIELDTERMINATOR='%s', ROWTERMINATOR='%s')" % (self.fileTblName, dFile, randomStr(10), randomStr(10))) inject.goStacked("BULK INSERT %s FROM '%s' WITH (CODEPAGE='RAW', FIELDTERMINATOR='%s', ROWTERMINATOR='%s')" % (self.fileTblName, remoteFile, randomStr(10), randomStr(10)))
lengthQuery = "SELECT DATALENGTH(%s) FROM %s" % (self.tblField, self.fileTblName) lengthQuery = "SELECT DATALENGTH(%s) FROM %s" % (self.tblField, self.fileTblName)
wFileSize = os.path.getsize(wFile) localFileSize = os.path.getsize(localFile)
logger.debug("checking if the %s file has been written" % fileType) logger.debug("checking the length of the remote file %s" % remoteFile)
dFileSize = inject.getValue(lengthQuery, resumeValue=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) remoteFileSize = inject.getValue(lengthQuery, resumeValue=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
sameFile = None sameFile = None
if isNumPosStrValue(dFileSize): if isNumPosStrValue(remoteFileSize):
infoMsg = "the file has been successfully written and " remoteFileSize = long(remoteFileSize)
infoMsg += "its size is %s bytes" % dFileSize
dFileSize = long(dFileSize)
if wFileSize == dFileSize:
sameFile = True
infoMsg += ", same size as the local file '%s'" % wFile
else:
sameFile = False sameFile = False
if localFileSize == remoteFileSize:
sameFile = True
infoMsg = "the local file %s and the remote file " % localFile
infoMsg += "%s have the same size" % remoteFile
elif remoteFileSize > localFileSize:
infoMsg = "the remote file %s is larger than " % remoteFile
infoMsg += "the local file %s" % localFile
else:
infoMsg += ", but the size differs from the local " infoMsg += ", but the size differs from the local "
infoMsg += "file '%s' (%d bytes)" % (wFile, wFileSize) infoMsg += "file '%s' (%d bytes)" % (localFile, localFileSize)
logger.info(infoMsg) logger.info(infoMsg)
else: else:
@ -133,38 +137,49 @@ class Filesystem:
return retVal return retVal
def askCheckWrittenFile(self, wFile, dFile, fileType): def askCheckWrittenFile(self, localFile, remoteFile):
message = "do you want confirmation that the file '%s' " % dFile message = "do you want confirmation that the local file '%s' " % localFile
message += "has been successfully written on the back-end DBMS " message += "has been successfully written on the back-end DBMS "
message += "file system? [Y/n] " message += "file system (%s)? [Y/n] " % remoteFile
output = readInput(message, default="Y") output = readInput(message, default="Y")
if not output or output in ("y", "Y"): if not output or output in ("y", "Y"):
return self._checkWrittenFile(wFile, dFile, fileType) return self._checkFileLength(localFile, remoteFile)
return True return True
def nonStackedReadFile(self, rFile): def askCheckReadFile(self, localFile, remoteFile):
message = "do you want confirmation that the remote file '%s' " % remoteFile
message += "has been successfully downloaded from the back-end "
message += "DBMS file system? [Y/n] "
output = readInput(message, default="Y")
if not output or output in ("y", "Y"):
return self._checkFileLength(localFile, remoteFile, True)
return True
def nonStackedReadFile(self, remoteFile):
errMsg = "'nonStackedReadFile' method must be defined " errMsg = "'nonStackedReadFile' method must be defined "
errMsg += "into the specific DBMS plugin" errMsg += "into the specific DBMS plugin"
raise SqlmapUndefinedMethod, errMsg raise SqlmapUndefinedMethod, errMsg
def stackedReadFile(self, rFile): def stackedReadFile(self, remoteFile):
errMsg = "'stackedReadFile' method must be defined " errMsg = "'stackedReadFile' method must be defined "
errMsg += "into the specific DBMS plugin" errMsg += "into the specific DBMS plugin"
raise SqlmapUndefinedMethod, errMsg raise SqlmapUndefinedMethod, errMsg
def unionWriteFile(self, wFile, dFile, fileType): def unionWriteFile(self, localFile, remoteFile, fileType):
errMsg = "'unionWriteFile' method must be defined " errMsg = "'unionWriteFile' method must be defined "
errMsg += "into the specific DBMS plugin" errMsg += "into the specific DBMS plugin"
raise SqlmapUndefinedMethod, errMsg raise SqlmapUndefinedMethod, errMsg
def stackedWriteFile(self, wFile, dFile, fileType): def stackedWriteFile(self, localFile, remoteFile, fileType):
errMsg = "'stackedWriteFile' method must be defined " errMsg = "'stackedWriteFile' method must be defined "
errMsg += "into the specific DBMS plugin" errMsg += "into the specific DBMS plugin"
raise SqlmapUndefinedMethod, errMsg raise SqlmapUndefinedMethod, errMsg
def readFile(self, rFile): def readFile(self, remoteFile):
fileContent = None fileContent = None
self.checkDbmsOs() self.checkDbmsOs()
@ -177,13 +192,13 @@ class Filesystem:
debugMsg += "injection technique" debugMsg += "injection technique"
logger.debug(debugMsg) logger.debug(debugMsg)
fileContent = self.stackedReadFile(rFile) fileContent = self.stackedReadFile(remoteFile)
elif Backend.isDbms(DBMS.MYSQL): elif Backend.isDbms(DBMS.MYSQL):
debugMsg = "going to read the file with a non-stacked query " debugMsg = "going to read the file with a non-stacked query "
debugMsg += "SQL injection technique" debugMsg += "SQL injection technique"
logger.debug(debugMsg) logger.debug(debugMsg)
fileContent = self.nonStackedReadFile(rFile) fileContent = self.nonStackedReadFile(remoteFile)
else: else:
errMsg = "none of the SQL injection techniques detected can " errMsg = "none of the SQL injection techniques detected can "
errMsg += "be used to read files from the underlying file " errMsg += "be used to read files from the underlying file "
@ -214,14 +229,16 @@ class Filesystem:
fileContent = newFileContent fileContent = newFileContent
fileContent = decodeHexValue(fileContent) fileContent = decodeHexValue(fileContent)
rFilePath = dataToOutFile(fileContent) remoteFilePath = dataToOutFile(fileContent)
if not Backend.isDbms(DBMS.PGSQL): if not Backend.isDbms(DBMS.PGSQL):
self.cleanup(onlyFileTbl=True) self.cleanup(onlyFileTbl=True)
return rFilePath self.askCheckReadFile(remoteFilePath, remoteFile)
def writeFile(self, wFile, dFile, fileType=None): return remoteFilePath
def writeFile(self, localFile, remoteFile, fileType=None):
self.checkDbmsOs() self.checkDbmsOs()
if conf.direct or isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED): if conf.direct or isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED):
@ -230,14 +247,14 @@ class Filesystem:
debugMsg += "stacked query SQL injection technique" debugMsg += "stacked query SQL injection technique"
logger.debug(debugMsg) logger.debug(debugMsg)
self.stackedWriteFile(wFile, dFile, fileType) self.stackedWriteFile(localFile, remoteFile, fileType)
self.cleanup(onlyFileTbl=True) self.cleanup(onlyFileTbl=True)
elif isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) and Backend.isDbms(DBMS.MYSQL): elif isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) and Backend.isDbms(DBMS.MYSQL):
debugMsg = "going to upload the %s file with " % fileType debugMsg = "going to upload the %s file with " % fileType
debugMsg += "UNION query SQL injection technique" debugMsg += "UNION query SQL injection technique"
logger.debug(debugMsg) logger.debug(debugMsg)
self.unionWriteFile(wFile, dFile, fileType) self.unionWriteFile(localFile, remoteFile, fileType)
else: else:
errMsg = "none of the SQL injection techniques detected can " errMsg = "none of the SQL injection techniques detected can "
errMsg += "be used to write files to the underlying file " errMsg += "be used to write files to the underlying file "