diff --git a/lib/controller/handler.py b/lib/controller/handler.py index a02b65a1f..81a80c835 100644 --- a/lib/controller/handler.py +++ b/lib/controller/handler.py @@ -32,6 +32,7 @@ from lib.core.settings import PGSQL_ALIASES from lib.core.settings import SQLITE_ALIASES from lib.core.settings import ACCESS_ALIASES from lib.core.settings import FIREBIRD_ALIASES +from lib.core.settings import MAXDB_ALIASES from plugins.dbms.mssqlserver import MSSQLServerMap from plugins.dbms.mssqlserver.connector import Connector as MSSQLServerConn @@ -47,6 +48,8 @@ from plugins.dbms.access import AccessMap from plugins.dbms.access.connector import Connector as AccessConn from plugins.dbms.firebird import FirebirdMap from plugins.dbms.firebird.connector import Connector as FirebirdConn +from plugins.dbms.maxdb import MaxDBMap +from plugins.dbms.maxdb.connector import Connector as MaxDBConn def setHandler(): """ @@ -55,7 +58,7 @@ def setHandler(): """ count = 0 - dbmsNames = ( "MySQL", "Oracle", "PostgreSQL", "Microsoft SQL Server", "SQLite", "Microsoft Access", "Firebird" ) + dbmsNames = ( "MySQL", "Oracle", "PostgreSQL", "Microsoft SQL Server", "SQLite", "Microsoft Access", "Firebird", "SAP MaxDB" ) dbmsMap = ( ( MYSQL_ALIASES, MySQLMap, MySQLConn ), ( ORACLE_ALIASES, OracleMap, OracleConn ), @@ -64,6 +67,7 @@ def setHandler(): ( SQLITE_ALIASES, SQLiteMap, SQLiteConn ), ( ACCESS_ALIASES, AccessMap, AccessConn ), ( FIREBIRD_ALIASES, FirebirdMap, FirebirdConn ), + ( MAXDB_ALIASES, MaxDBMap, MaxDBConn ), ) for dbmsAliases, dbmsMap, dbmsConn in dbmsMap: diff --git a/lib/core/common.py b/lib/core/common.py index e0836d530..62ee83510 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -164,7 +164,7 @@ def formatDBMSfp(versions=None): while versions and None in versions: versions.remove(None) - if not versions and kb.dbmsVersion and kb.dbmsVersion[0] != "Unknown": + if not versions and kb.dbmsVersion and kb.dbmsVersion[0] != "Unknown" and kb.dbmsVersion[0] != None: versions = kb.dbmsVersion if isinstance(versions, basestring): diff --git a/lib/core/settings.py b/lib/core/settings.py index 07d454ed1..802c80f80 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -57,10 +57,10 @@ PYVERSION = sys.version.split()[0] MSSQL_VERSIONS_URL = "http://www.sqlsecurity.com/FAQs/SQLServerVersionDatabase/tabid/63/Default.aspx" # Database management system specific variables -MSSQL_SYSTEM_DBS = ( "Northwind", "model", "msdb", "pubs", "tempdb" ) -MYSQL_SYSTEM_DBS = ( "information_schema", "mysql" ) # Before MySQL 5.0 only "mysql" -PGSQL_SYSTEM_DBS = ( "information_schema", "pg_catalog", "pg_toast" ) -ORACLE_SYSTEM_DBS = ( "SYSTEM", "SYSAUX" ) # These are TABLESPACE_NAME +MSSQL_SYSTEM_DBS = ( "Northwind", "model", "msdb", "pubs", "tempdb" ) +MYSQL_SYSTEM_DBS = ( "information_schema", "mysql" ) # Before MySQL 5.0 only "mysql" +PGSQL_SYSTEM_DBS = ( "information_schema", "pg_catalog", "pg_toast" ) +ORACLE_SYSTEM_DBS = ( "SYSTEM", "SYSAUX" ) # These are TABLESPACE_NAME SQLITE_SYSTEM_DBS = ( "sqlite_master", "sqlite_temp_master" ) ACCESS_SYSTEM_DBS = ( "MSysAccessObjects", "MSysACEs", "MSysObjects", "MSysQueries", "MSysRelationships", "MSysAccessStorage",\ "MSysAccessXML", "MSysModules", "MSysModules2" ) @@ -70,19 +70,21 @@ FIREBIRD_SYSTEM_DBS = ( "RDB$BACKUP_HISTORY", "RDB$CHARACTER_SETS", "RDB$CHECK_C "RDB$LOG_FILES", "RDB$PAGES", "RDB$PROCEDURES", "RDB$PROCEDURE_PARAMETERS", "RDB$REF_CONSTRAINTS", "RDB$RELATIONS",\ "RDB$RELATION_CONSTRAINTS", "RDB$RELATION_FIELDS", "RDB$ROLES", "RDB$SECURITY_CLASSES", "RDB$TRANSACTIONS", "RDB$TRIGGERS",\ "RDB$TRIGGER_MESSAGES", "RDB$TYPES", "RDB$USER_PRIVILEGES", "RDB$VIEW_RELATIONS" ) +MAXDB_SYSTEM_DBS = ( "SYSINFO", "DOMAIN" ) -MSSQL_ALIASES = [ "microsoft sql server", "mssqlserver", "mssql", "ms" ] -MYSQL_ALIASES = [ "mysql", "my" ] -PGSQL_ALIASES = [ "postgresql", "postgres", "pgsql", "psql", "pg" ] -ORACLE_ALIASES = [ "oracle", "orcl", "ora", "or" ] -SQLITE_ALIASES = [ "sqlite", "sqlite3" ] -ACCESS_ALIASES = [ "access", "jet", "microsoft access", "msaccess" ] -FIREBIRD_ALIASES = [ "firebird", "mozilla firebird", "interbase", "ibase", "fb" ] +MSSQL_ALIASES = [ "microsoft sql server", "mssqlserver", "mssql", "ms" ] +MYSQL_ALIASES = [ "mysql", "my" ] +PGSQL_ALIASES = [ "postgresql", "postgres", "pgsql", "psql", "pg" ] +ORACLE_ALIASES = [ "oracle", "orcl", "ora", "or" ] +SQLITE_ALIASES = [ "sqlite", "sqlite3" ] +ACCESS_ALIASES = [ "access", "jet", "microsoft access", "msaccess" ] +FIREBIRD_ALIASES = [ "firebird", "mozilla firebird", "interbase", "ibase", "fb" ] +MAXDB_ALIASES = [ "maxdb", "sap maxdb", "sap db" ] -SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES + SQLITE_ALIASES + ACCESS_ALIASES + FIREBIRD_ALIASES -SUPPORTED_OS = ( "linux", "windows" ) +SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES + SQLITE_ALIASES + ACCESS_ALIASES + FIREBIRD_ALIASES + MAXDB_ALIASES +SUPPORTED_OS = ( "linux", "windows" ) -SQL_STATEMENTS = { +SQL_STATEMENTS = { "SQL SELECT statement": ( "select ", "show ", diff --git a/plugins/dbms/firebird/fingerprint.py b/plugins/dbms/firebird/fingerprint.py index e27fd0319..2b83460ed 100644 --- a/plugins/dbms/firebird/fingerprint.py +++ b/plugins/dbms/firebird/fingerprint.py @@ -91,7 +91,7 @@ class Fingerprint(GenericFingerprint): ("2.0", [" AND EXISTS(SELECT CURRENT_TIME(0) FROM RDB$DATABASE)", " AND BIT_LENGTH(%d)>0", " AND CHAR_LENGTH(%d)>0"]), ("2.1", [" AND BIN_XOR(%d,%d)=0", " AND PI()>0.%d", " AND RAND()<1.%d", " AND FLOOR(1.%d)>=0"]) ) - + for i in xrange(len(table)): version, checks = table[i] failed = False @@ -105,7 +105,7 @@ class Fingerprint(GenericFingerprint): break if failed: break - + return retVal def __dialectCheck(self): @@ -115,7 +115,7 @@ class Fingerprint(GenericFingerprint): result = Request.queryPage(payload) retVal = "dialect 3" if result else "dialect 1" return retVal - + def checkDbms(self): if conf.dbms in FIREBIRD_ALIASES: setDbms("Firebird") @@ -127,7 +127,7 @@ class Fingerprint(GenericFingerprint): logMsg = "testing Firebird" logger.info(logMsg) - + randInt = randomInt() payload = agent.fullPayload(" AND EXISTS(SELECT * FROM RDB$DATABASE WHERE %d=%d)" % (randInt, randInt)) diff --git a/plugins/dbms/maxdb/__init__.py b/plugins/dbms/maxdb/__init__.py new file mode 100644 index 000000000..45a9c2aa5 --- /dev/null +++ b/plugins/dbms/maxdb/__init__.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python + +""" +$Id$ + +This file is part of the sqlmap project, http://sqlmap.sourceforge.net. + +Copyright (c) 2007-2009 Bernardo Damele A. G. +Copyright (c) 2006 Daniele Bellucci + +sqlmap is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation version 2 of the License. + +sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +You should have received a copy of the GNU General Public License along +with sqlmap; if not, write to the Free Software Foundation, Inc., 51 +Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" + +from lib.core.settings import MAXDB_SYSTEM_DBS +from lib.core.unescaper import unescaper + +from plugins.dbms.maxdb.enumeration import Enumeration +from plugins.dbms.maxdb.filesystem import Filesystem +from plugins.dbms.maxdb.fingerprint import Fingerprint +from plugins.dbms.maxdb.syntax import Syntax +from plugins.dbms.maxdb.takeover import Takeover +from plugins.generic.misc import Miscellaneous + +class MaxDBMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover): + """ + This class defines SAP MaxDB methods + """ + + def __init__(self): + self.excludeDbsList = MAXDB_SYSTEM_DBS + + Syntax.__init__(self) + Fingerprint.__init__(self) + Enumeration.__init__(self) + Filesystem.__init__(self) + Miscellaneous.__init__(self) + Takeover.__init__(self) + + unescaper.setUnescape(MaxDBMap.unescape) diff --git a/plugins/dbms/maxdb/connector.py b/plugins/dbms/maxdb/connector.py new file mode 100644 index 000000000..5172945f0 --- /dev/null +++ b/plugins/dbms/maxdb/connector.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python + +""" +$Id$ + +This file is part of the sqlmap project, http://sqlmap.sourceforge.net. + +Copyright (c) 2007-2010 Bernardo Damele A. G. +Copyright (c) 2006 Daniele Bellucci + +sqlmap is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation version 2 of the License. + +sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +You should have received a copy of the GNU General Public License along +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 sqlmapUnsupportedFeatureException + +from plugins.generic.connector import Connector as GenericConnector + +class Connector(GenericConnector): + def __init__(self): + GenericConnector.__init__(self) + + def connect(self): + errMsg = "on SAP MaxDB it is not possible to establish an " + errMsg += "direct connection" + raise sqlmapUnsupportedFeatureException, errMsg diff --git a/plugins/dbms/maxdb/enumeration.py b/plugins/dbms/maxdb/enumeration.py new file mode 100644 index 000000000..ae449fd86 --- /dev/null +++ b/plugins/dbms/maxdb/enumeration.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python + +""" +$Id$ + +This file is part of the sqlmap project, http://sqlmap.sourceforge.net. + +Copyright (c) 2007-2010 Bernardo Damele A. G. +Copyright (c) 2006 Daniele Bellucci + +sqlmap is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation version 2 of the License. + +sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +You should have received a copy of the GNU General Public License along +with sqlmap; if not, write to the Free Software Foundation, Inc., 51 +Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" + +from plugins.generic.enumeration import Enumeration as GenericEnumeration + +class Enumeration(GenericEnumeration): + def __init__(self): + GenericEnumeration.__init__(self, "SAP MaxDB") + + def getDbs(self): + warnMsg = "on SAP MaxDB it is not possible to enumerate databases" + logger.warn(warnMsg) + + return [] + + def getBanner(self): + warnMsg = "on SAP MaxDB it is not possible to get a banner" + logger.warn(warnMsg) + + return None + + def getPasswordHashes(self): + warnMsg = "on SAP MaxDB it is not possible to enumerate the user password hashes" + logger.warn(warnMsg) + + return {} + + def searchDb(self): + warnMsg = "on SAP MaxDB it is not possible to search databases" + logger.warn(warnMsg) + + return [] diff --git a/plugins/dbms/maxdb/filesystem.py b/plugins/dbms/maxdb/filesystem.py new file mode 100644 index 000000000..435de8094 --- /dev/null +++ b/plugins/dbms/maxdb/filesystem.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python + +""" +$Id$ + +This file is part of the sqlmap project, http://sqlmap.sourceforge.net. + +Copyright (c) 2007-2010 Bernardo Damele A. G. +Copyright (c) 2006 Daniele Bellucci + +sqlmap is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation version 2 of the License. + +sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +You should have received a copy of the GNU General Public License along +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 sqlmapUnsupportedFeatureException + +from plugins.generic.filesystem import Filesystem as GenericFilesystem + +class Filesystem(GenericFilesystem): + def __init__(self): + GenericFilesystem.__init__(self) + + def readFile(self, rFile): + errMsg = "on SAP MaxDB reading of files is not supported" + raise sqlmapUnsupportedFeatureException, errMsg + + def writeFile(self, wFile, dFile, fileType=None, confirm=True): + errMsg = "on SAP MaxDB writing of files is not supported" + raise sqlmapUnsupportedFeatureException, errMsg diff --git a/plugins/dbms/maxdb/fingerprint.py b/plugins/dbms/maxdb/fingerprint.py new file mode 100644 index 000000000..5e9dbbd48 --- /dev/null +++ b/plugins/dbms/maxdb/fingerprint.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python + +""" +$Id$ + +This file is part of the sqlmap project, http://sqlmap.sourceforge.net. + +Copyright (c) 2007-2010 Bernardo Damele A. G. +Copyright (c) 2006 Daniele Bellucci + +sqlmap is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation version 2 of the License. + +sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +You should have received a copy of the GNU General Public License along +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 +from lib.core.common import formatDBMSfp +from lib.core.common import formatFingerprint +from lib.core.common import getHtmlErrorFp +from lib.core.common import getUnicode +from lib.core.common import randomInt +from lib.core.common import randomRange +from lib.core.data import conf +from lib.core.data import kb +from lib.core.data import logger +from lib.core.session import setDbms +from lib.core.settings import MAXDB_ALIASES +from lib.request.connect import Connect as Request + +from plugins.generic.fingerprint import Fingerprint as GenericFingerprint + +class Fingerprint(GenericFingerprint): + def __init__(self): + GenericFingerprint.__init__(self) + + def getFingerprint(self): + value = "" + wsOsFp = formatFingerprint("web server", kb.headersFp) + + if wsOsFp: + value += "%s\n" % wsOsFp + + if kb.data.banner: + dbmsOsFp = formatFingerprint("back-end DBMS", kb.bannerFp) + + if dbmsOsFp: + value += "%s\n" % dbmsOsFp + + blank = " " * 15 + value += "back-end DBMS: " + + if not conf.extensiveFp: + value += "SAP MaxDB" + return value + + actVer = formatDBMSfp() + " (%s)" % None + blank = " " * 15 + value += "active fingerprint: %s" % actVer + + if kb.bannerFp: + value += "\n%sbanner parsing fingerprint: -" % blank + + htmlErrorFp = getHtmlErrorFp() + + if htmlErrorFp: + value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp) + + return value + + def checkDbms(self): + if conf.dbms in MAXDB_ALIASES: + setDbms("SAP MaxDB") + + self.getBanner() + + if not conf.extensiveFp: + return True + + logMsg = "testing SAP MaxDB" + logger.info(logMsg) + + randInt = randomInt() + + payload = agent.fullPayload(" AND NOROUND(%d)=%d" % (randInt, randInt)) + result = Request.queryPage(payload) + + if result: + logMsg = "confirming SAP MaxDB" + logger.info(logMsg) + + payload = agent.fullPayload(" AND MAPCHAR(NULL,1,DEFAULTMAP) IS NULL") + result = Request.queryPage(payload) + + if not result: + warnMsg = "the back-end DMBS is not SAP MaxDB" + logger.warn(warnMsg) + + return False + + setDbms("SAP MaxDB") + + self.getBanner() + + if not conf.extensiveFp: + return True + + kb.dbmsVersion = None + + return True + else: + warnMsg = "the back-end DMBS is not SAP MaxDB" + logger.warn(warnMsg) + + return False + + def forceDbmsEnum(self): + conf.db = "SAP MaxDB" diff --git a/plugins/dbms/maxdb/syntax.py b/plugins/dbms/maxdb/syntax.py new file mode 100644 index 000000000..ad2304552 --- /dev/null +++ b/plugins/dbms/maxdb/syntax.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python + +""" +$Id$ + +This file is part of the sqlmap project, http://sqlmap.sourceforge.net. + +Copyright (c) 2007-2010 Bernardo Damele A. G. +Copyright (c) 2006 Daniele Bellucci + +sqlmap is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation version 2 of the License. + +sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +You should have received a copy of the GNU General Public License along +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 sqlmapSyntaxException +from plugins.generic.syntax import Syntax as GenericSyntax + +class Syntax(GenericSyntax): + def __init__(self): + GenericSyntax.__init__(self) + + @staticmethod + def unescape(expression, quote=True): + if quote: + while True: + index = expression.find("'") + if index == -1: + break + + firstIndex = index + 1 + index = expression[firstIndex:].find("'") + + if index == -1: + raise sqlmapSyntaxException, "Unenclosed ' in '%s'" % expression + + lastIndex = firstIndex + index + old = "'%s'" % expression[firstIndex:lastIndex] + #unescaped = "(" + unescaped = "" + + for i in range(firstIndex, lastIndex): + unescaped += "CHR(%d)" % (ord(expression[i])) + if i < lastIndex - 1: + unescaped += "||" + + #unescaped += ")" + expression = expression.replace(old, unescaped) + else: + expression = "||".join("CHR(%d)" % ord(c) for c in expression) + + return expression + + @staticmethod + def escape(expression): + while True: + index = expression.find("CHR(") + if index == -1: + break + + firstIndex = index + index = expression[firstIndex:].find("))") + + if index == -1: + raise sqlmapSyntaxException, "Unenclosed ) in '%s'" % expression + + lastIndex = firstIndex + index + 1 + old = expression[firstIndex:lastIndex] + oldUpper = old.upper() + oldUpper = oldUpper.replace("CHR(", "").replace(")", "") + oldUpper = oldUpper.split("||") + + escaped = "'%s'" % "".join([chr(int(char)) for char in oldUpper]) + expression = expression.replace(old, escaped) + + return expression diff --git a/plugins/dbms/maxdb/takeover.py b/plugins/dbms/maxdb/takeover.py new file mode 100644 index 000000000..be34e6a75 --- /dev/null +++ b/plugins/dbms/maxdb/takeover.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +""" +$Id$ + +This file is part of the sqlmap project, http://sqlmap.sourceforge.net. + +Copyright (c) 2007-2010 Bernardo Damele A. G. +Copyright (c) 2006 Daniele Bellucci + +sqlmap is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation version 2 of the License. + +sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +You should have received a copy of the GNU General Public License along +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 sqlmapUnsupportedFeatureException + +from plugins.generic.takeover import Takeover as GenericTakeover + +class Takeover(GenericTakeover): + def __init__(self): + GenericTakeover.__init__(self) + + def osCmd(self): + errMsg = "on SAP MaxDB it is not possible to execute commands" + raise sqlmapUnsupportedFeatureException, errMsg + + def osShell(self): + errMsg = "on SAP MaxDB it is not possible to execute commands" + raise sqlmapUnsupportedFeatureException, errMsg + + def osPwn(self): + errMsg = "on SAP MaxDB it is not possible to establish an " + errMsg += "out-of-band connection" + raise sqlmapUnsupportedFeatureException, errMsg + + def osSmb(self): + errMsg = "on SAP MaxDB it is not possible to establish an " + errMsg += "out-of-band connection" + raise sqlmapUnsupportedFeatureException, errMsg diff --git a/xml/errors.xml b/xml/errors.xml index 82cdbc2fb..8061810a2 100644 --- a/xml/errors.xml +++ b/xml/errors.xml @@ -62,7 +62,7 @@ - + @@ -71,4 +71,10 @@ + + + + + + diff --git a/xml/queries.xml b/xml/queries.xml index e38418fcf..1f53a882e 100644 --- a/xml/queries.xml +++ b/xml/queries.xml @@ -355,7 +355,7 @@ - + @@ -404,4 +404,11 @@ + + + + + + +