2009-04-22 15:48:07 +04:00
|
|
|
#!/usr/bin/env python
|
|
|
|
|
|
|
|
"""
|
2013-01-18 18:07:51 +04:00
|
|
|
Copyright (c) 2006-2013 sqlmap developers (http://sqlmap.org/)
|
2010-10-15 03:18:29 +04:00
|
|
|
See the file 'doc/COPYING' for copying permission
|
2009-04-22 15:48:07 +04:00
|
|
|
"""
|
|
|
|
|
2012-02-22 14:40:11 +04:00
|
|
|
from extra.safe2bin.safe2bin import safechardecode
|
2010-10-21 02:09:03 +04:00
|
|
|
from lib.core.common import dataToStdout
|
2011-01-28 19:36:09 +03:00
|
|
|
from lib.core.common import Backend
|
2012-07-10 03:19:32 +04:00
|
|
|
from lib.core.common import getSQLSnippet
|
2010-12-18 18:57:47 +03:00
|
|
|
from lib.core.common import isTechniqueAvailable
|
2009-04-22 15:48:07 +04:00
|
|
|
from lib.core.common import readInput
|
|
|
|
from lib.core.data import conf
|
|
|
|
from lib.core.data import logger
|
2010-11-08 12:20:02 +03:00
|
|
|
from lib.core.enums import DBMS
|
2010-12-18 18:57:47 +03:00
|
|
|
from lib.core.enums import PAYLOAD
|
2013-01-23 05:27:01 +04:00
|
|
|
from lib.core.exception import SqlmapFilePathException
|
2012-12-06 17:14:19 +04:00
|
|
|
from lib.core.exception import SqlmapUnsupportedFeatureException
|
2009-04-22 15:48:07 +04:00
|
|
|
from lib.core.shell import autoCompletion
|
2012-07-02 05:04:19 +04:00
|
|
|
from lib.request import inject
|
2009-04-22 15:48:07 +04:00
|
|
|
from lib.takeover.udf import UDF
|
2010-01-14 17:03:16 +03:00
|
|
|
from lib.takeover.web import Web
|
2012-12-06 16:46:24 +04:00
|
|
|
from lib.takeover.xp_cmdshell import Xp_cmdshell
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2010-11-02 14:59:24 +03:00
|
|
|
|
2012-12-06 16:46:24 +04:00
|
|
|
class Abstraction(Web, UDF, Xp_cmdshell):
|
2009-04-22 15:48:07 +04:00
|
|
|
"""
|
|
|
|
This class defines an abstraction layer for OS takeover functionalities
|
2012-12-06 16:46:24 +04:00
|
|
|
to UDF / Xp_cmdshell objects
|
2009-04-22 15:48:07 +04:00
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
self.envInitialized = False
|
2010-02-25 14:40:49 +03:00
|
|
|
self.alwaysRetrieveCmdOutput = False
|
2009-04-22 15:48:07 +04:00
|
|
|
|
|
|
|
UDF.__init__(self)
|
2010-01-14 17:03:16 +03:00
|
|
|
Web.__init__(self)
|
2012-12-06 16:46:24 +04:00
|
|
|
Xp_cmdshell.__init__(self)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2010-10-28 04:19:40 +04:00
|
|
|
def execCmd(self, cmd, silent=False):
|
2010-12-18 18:57:47 +03:00
|
|
|
if self.webBackdoorUrl and not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED):
|
2010-01-14 17:33:08 +03:00
|
|
|
self.webBackdoorRunCmd(cmd)
|
2010-01-14 17:03:16 +03:00
|
|
|
|
2013-01-09 18:38:41 +04:00
|
|
|
elif Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
|
2009-09-26 03:03:45 +04:00
|
|
|
self.udfExecCmd(cmd, silent=silent)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2011-04-30 18:54:29 +04:00
|
|
|
elif Backend.isDbms(DBMS.MSSQL):
|
2010-10-29 17:09:53 +04:00
|
|
|
self.xpCmdshellExecCmd(cmd, silent=silent)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
|
|
|
else:
|
|
|
|
errMsg = "Feature not yet implemented for the back-end DBMS"
|
2013-01-04 02:20:55 +04:00
|
|
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2009-09-26 03:03:45 +04:00
|
|
|
def evalCmd(self, cmd, first=None, last=None):
|
2011-05-03 19:31:12 +04:00
|
|
|
retVal = None
|
|
|
|
|
2010-12-18 18:57:47 +03:00
|
|
|
if self.webBackdoorUrl and not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED):
|
2011-05-03 19:31:12 +04:00
|
|
|
retVal = self.webBackdoorRunCmd(cmd)
|
2010-01-14 17:33:08 +03:00
|
|
|
|
2013-01-09 18:38:41 +04:00
|
|
|
elif Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
|
2011-05-03 19:31:12 +04:00
|
|
|
retVal = self.udfEvalCmd(cmd, first, last)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2011-04-30 18:54:29 +04:00
|
|
|
elif Backend.isDbms(DBMS.MSSQL):
|
2011-05-03 19:31:12 +04:00
|
|
|
retVal = self.xpCmdshellEvalCmd(cmd, first, last)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
|
|
|
else:
|
|
|
|
errMsg = "Feature not yet implemented for the back-end DBMS"
|
2013-01-04 02:20:55 +04:00
|
|
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2011-05-03 19:31:12 +04:00
|
|
|
return safechardecode(retVal)
|
|
|
|
|
2009-04-22 15:48:07 +04:00
|
|
|
def runCmd(self, cmd):
|
|
|
|
getOutput = None
|
|
|
|
|
2010-02-25 14:40:49 +03:00
|
|
|
if not self.alwaysRetrieveCmdOutput:
|
2011-04-30 17:20:05 +04:00
|
|
|
message = "do you want to retrieve the command standard "
|
|
|
|
message += "output? [Y/n/a] "
|
2010-02-25 14:40:49 +03:00
|
|
|
getOutput = readInput(message, default="Y")
|
2010-11-03 13:08:27 +03:00
|
|
|
|
2010-02-25 14:40:49 +03:00
|
|
|
if getOutput in ("a", "A"):
|
|
|
|
self.alwaysRetrieveCmdOutput = True
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2010-02-25 14:40:49 +03:00
|
|
|
if not getOutput or getOutput in ("y", "Y") or self.alwaysRetrieveCmdOutput:
|
2009-04-22 15:48:07 +04:00
|
|
|
output = self.evalCmd(cmd)
|
|
|
|
|
|
|
|
if output:
|
2010-05-28 20:43:04 +04:00
|
|
|
conf.dumper.string("command standard output", output)
|
2009-04-22 15:48:07 +04:00
|
|
|
else:
|
2010-10-21 02:09:03 +04:00
|
|
|
dataToStdout("No output\n")
|
2009-04-22 15:48:07 +04:00
|
|
|
else:
|
2010-10-28 04:19:40 +04:00
|
|
|
self.execCmd(cmd)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2010-01-14 17:33:08 +03:00
|
|
|
def shell(self):
|
2010-12-18 18:57:47 +03:00
|
|
|
if self.webBackdoorUrl and not isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED):
|
2011-04-30 17:20:05 +04:00
|
|
|
infoMsg = "calling OS shell. To quit type "
|
2010-01-14 17:33:08 +03:00
|
|
|
infoMsg += "'x' or 'q' and press ENTER"
|
2009-04-22 15:48:07 +04:00
|
|
|
logger.info(infoMsg)
|
|
|
|
|
|
|
|
else:
|
2013-01-09 18:38:41 +04:00
|
|
|
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
|
2011-04-30 17:20:05 +04:00
|
|
|
infoMsg = "going to use injected sys_eval and sys_exec "
|
2010-01-14 17:33:08 +03:00
|
|
|
infoMsg += "user-defined functions for operating system "
|
|
|
|
infoMsg += "command execution"
|
|
|
|
logger.info(infoMsg)
|
|
|
|
|
2011-04-30 18:54:29 +04:00
|
|
|
elif Backend.isDbms(DBMS.MSSQL):
|
2011-04-30 17:20:05 +04:00
|
|
|
infoMsg = "going to use xp_cmdshell extended procedure for "
|
2010-01-14 17:33:08 +03:00
|
|
|
infoMsg += "operating system command execution"
|
|
|
|
logger.info(infoMsg)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2010-01-14 17:33:08 +03:00
|
|
|
else:
|
|
|
|
errMsg = "feature not yet implemented for the back-end DBMS"
|
2013-01-04 02:20:55 +04:00
|
|
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
2010-01-14 17:33:08 +03:00
|
|
|
|
2011-04-30 17:20:05 +04:00
|
|
|
infoMsg = "calling %s OS shell. To quit type " % (Backend.getOs() or "Windows")
|
2010-01-14 17:33:08 +03:00
|
|
|
infoMsg += "'x' or 'q' and press ENTER"
|
|
|
|
logger.info(infoMsg)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
|
|
|
autoCompletion(osShell=True)
|
|
|
|
|
|
|
|
while True:
|
|
|
|
command = None
|
|
|
|
|
|
|
|
try:
|
|
|
|
command = raw_input("os-shell> ")
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
print
|
|
|
|
errMsg = "user aborted"
|
|
|
|
logger.error(errMsg)
|
|
|
|
except EOFError:
|
|
|
|
print
|
|
|
|
errMsg = "exit"
|
|
|
|
logger.error(errMsg)
|
|
|
|
break
|
|
|
|
|
|
|
|
if not command:
|
|
|
|
continue
|
|
|
|
|
2013-01-09 18:38:41 +04:00
|
|
|
if command.lower() in ("x", "q", "exit", "quit"):
|
2009-04-22 15:48:07 +04:00
|
|
|
break
|
|
|
|
|
|
|
|
self.runCmd(command)
|
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _initRunAs(self):
|
2012-07-24 17:34:50 +04:00
|
|
|
if not conf.dbmsCred:
|
2012-07-02 05:04:19 +04:00
|
|
|
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"):
|
2012-07-10 03:19:32 +04:00
|
|
|
expression = getSQLSnippet(DBMS.MSSQL, "configure_openrowset", ENABLE="1")
|
2012-07-02 05:04:19 +04:00
|
|
|
inject.goStacked(expression)
|
|
|
|
|
|
|
|
# TODO: add support for PostgreSQL
|
|
|
|
#elif Backend.isDbms(DBMS.PGSQL):
|
2012-07-10 03:19:32 +04:00
|
|
|
# expression = getSQLSnippet(DBMS.PGSQL, "configure_dblink", ENABLE="1")
|
2012-07-02 05:04:19 +04:00
|
|
|
# inject.goStacked(expression)
|
|
|
|
|
2010-01-14 18:11:32 +03:00
|
|
|
def initEnv(self, mandatory=True, detailed=False, web=False):
|
2012-12-06 17:14:19 +04:00
|
|
|
self._initRunAs()
|
2012-07-02 05:04:19 +04:00
|
|
|
|
2010-01-02 05:02:12 +03:00
|
|
|
if self.envInitialized:
|
2009-04-22 15:48:07 +04:00
|
|
|
return
|
|
|
|
|
2010-01-14 18:11:32 +03:00
|
|
|
if web:
|
|
|
|
self.webInit()
|
|
|
|
else:
|
|
|
|
self.checkDbmsOs(detailed)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2010-01-14 18:11:32 +03:00
|
|
|
if mandatory and not self.isDba():
|
2012-07-13 16:33:16 +04:00
|
|
|
warnMsg = "functionality requested probably does not work because "
|
|
|
|
warnMsg += "the curent session user is not a database administrator"
|
2012-07-02 18:02:00 +04:00
|
|
|
|
2013-01-09 18:38:41 +04:00
|
|
|
if not conf.dbmsCred and Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.PGSQL):
|
2012-07-17 03:25:02 +04:00
|
|
|
warnMsg += ". You can try to use option '--dbms-cred' "
|
2012-07-02 18:02:00 +04:00
|
|
|
warnMsg += "to execute statements as a DBA user if you "
|
|
|
|
warnMsg += "were able to extract and crack a DBA "
|
|
|
|
warnMsg += "password by any mean"
|
|
|
|
|
2010-01-14 18:11:32 +03:00
|
|
|
logger.warn(warnMsg)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2013-01-09 18:38:41 +04:00
|
|
|
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
|
2013-01-23 05:27:01 +04:00
|
|
|
success = self.udfInjectSys()
|
|
|
|
|
|
|
|
if success is not True:
|
|
|
|
msg = "unable to mount the operating system takeover"
|
|
|
|
raise SqlmapFilePathException(msg)
|
2011-04-30 18:54:29 +04:00
|
|
|
elif Backend.isDbms(DBMS.MSSQL):
|
2010-01-14 18:11:32 +03:00
|
|
|
if mandatory:
|
|
|
|
self.xpCmdshellInit()
|
|
|
|
else:
|
|
|
|
errMsg = "feature not yet implemented for the back-end DBMS"
|
2012-12-06 17:14:19 +04:00
|
|
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
2010-01-04 18:02:56 +03:00
|
|
|
|
|
|
|
self.envInitialized = True
|