def discover(self, fuzzable_request): """ Checks if JBoss Interesting Directories exist in the target server. Also verifies some vulnerabilities. """ base_url = fuzzable_request.get_url().base_url() args_iter = izip(repeat(base_url), self.JBOSS_VULNS) otm_send_request = one_to_many(self.send_request) response_pool = self.worker_pool.imap_unordered(otm_send_request, args_iter) for vuln_db_instance, response in response_pool: if is_404(response): continue vuln_url = base_url.url_join(vuln_db_instance['url']) name = vuln_db_instance['name'] desc = vuln_db_instance['desc'] if vuln_db_instance['type'] == 'info': o = Info(name, desc, response.id, self.get_name()) else: o = Vuln(name, desc, severity.LOW, response.id, self.get_name()) o.set_url(vuln_url) kb.kb.append(self, 'find_jboss', o) for fr in self._create_fuzzable_requests(response): self.output_queue.put(fr)
def discover(self, fuzzable_request): """ Checks if JBoss Interesting Directories exist in the target server. Also verifies some vulnerabilities. """ base_url = fuzzable_request.get_url().base_url() args_iter = izip(repeat(base_url), self.JBOSS_VULNS) otm_send_request = one_to_many(self.send_request) response_pool = self.worker_pool.imap_unordered( otm_send_request, args_iter) for vuln_db_instance, response in response_pool: if is_404(response): continue vuln_url = base_url.url_join(vuln_db_instance['url']) name = vuln_db_instance['name'] desc = vuln_db_instance['desc'] if vuln_db_instance['type'] == 'info': o = Info(name, desc, response.id, self.get_name()) else: o = Vuln(name, desc, severity.LOW, response.id, self.get_name()) o.set_url(vuln_url) kb.kb.append(self, 'find_jboss', o) self.output_queue.put(FuzzableRequest(response.get_uri()))
def _send_in_threads(self, base_url, vhosts): base_url_repeater = repeat(base_url) args_iterator = izip(base_url_repeater, vhosts) http_get = return_args(one_to_many(self._http_get_vhost)) pool_results = self.worker_pool.imap_unordered(http_get, args_iterator) for ((base_url, vhost),), vhost_response in pool_results: yield vhost, vhost_response
def _send_in_threads(self, base_url, vhosts): base_url_repeater = repeat(base_url) args_iterator = izip(base_url_repeater, vhosts) http_get = return_args(one_to_many(self._http_get_vhost)) pool_results = self.worker_pool.imap_unordered(http_get, args_iterator) for ((base_url, vhost), ), vhost_response in pool_results: yield vhost, vhost_response
def audit(self, freq, original_response): """ Find all kind of "generic" bugs without using a fixed error database :param freq: A FuzzableRequest """ # Prevent some false positives for cases where the original response # is already triggering an error if original_response.get_code() == 500: return # Get the original response and create the mutants mutants = create_mutants(freq, ['', ], orig_resp=original_response) original_response_repeat = repeat(original_response) args_iterator = izip(original_response_repeat, mutants) check_mutant = one_to_many(self._check_mutant) self.worker_pool.imap_unordered(check_mutant, args_iterator)
def audit(self, freq, original_response): """ Find all kind of "generic" bugs without using a fixed error database :param freq: A FuzzableRequest """ # Prevent some false positives for cases where the original response # is already triggering an error if original_response.get_code() == 500: return # Get the original response and create the mutants mutants = create_mutants(freq, [ '', ], orig_resp=original_response) original_response_repeat = repeat(original_response) args_iterator = izip(original_response_repeat, mutants) check_mutant = one_to_many(self._check_mutant) self.worker_pool.imap_unordered(check_mutant, args_iterator)
class php_eggs(InfrastructurePlugin): """ Fingerprint the PHP version using documented easter eggs that exist in PHP. :author: Andres Riancho ([email protected]) """ PHP_EGGS = [('?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000', 'PHP Credits'), ('?=PHPE9568F34-D428-11d2-A769-00AA001ACF42', 'PHP Logo'), ('?=PHPE9568F35-D428-11d2-A769-00AA001ACF42', 'Zend Logo'), ('?=PHPE9568F36-D428-11d2-A769-00AA001ACF42', 'PHP Logo 2')] # Empty EGG_DB array, will be filled with external data EGG_DB = {} def __init__(self): InfrastructurePlugin.__init__(self) # Already analyzed extensions self._already_analyzed_ext = ScalableBloomFilter() # Internal DB self._db_file = os.path.join(ROOT_PATH, 'plugins', 'infrastructure', 'php_eggs', 'eggs.json') # Get data from external JSON file and fill EGG_DB array data = self.read_jsondata(self._db_file) self.EGG_DB = self.fill_egg_array(data) def read_jsondata(self, jsonfile): """ Read a JSON file. File handling for reading a JSON file :return: Raw JSON data. """ json_data = open(jsonfile) file_data = json.load(json_data) json_data.close() return file_data def fill_egg_array(self, json_egg_data): """ Fill an array with data from a JSON input file. :return: An array with PHP-versions with corresponding MD5 hashes. """ egg_db = {} for egg in json_egg_data['db']: version = egg['version'] egg_db[version] = {} for key in ('credits', 'php_1', 'php_2', 'zend'): if key in egg: egg_db[version][key] = egg[key] return egg_db def discover(self, fuzzable_request): """ Nothing strange, just do some GET requests to the eggs and analyze the response. :param fuzzable_request: A fuzzable_request instance that contains (among other things) the URL to test. """ # Get the extension of the URL (.html, .php, .. etc) ext = fuzzable_request.get_url().get_extension() # Only perform this analysis if we haven't already analyzed this type # of extension OR if we get an URL like http://f00b5r/4/ (Note that # it has no extension) This logic will perform some extra tests... but # we won't miss some special cases. Also, we aren't doing something like # "if 'php' in ext:" because we never depend on something so easy to # modify as extensions to make decisions. if ext not in self._already_analyzed_ext: # Now we save the extension as one of the already analyzed self._already_analyzed_ext.add(ext) # Init some internal variables query_results = self._get_php_eggs(fuzzable_request, ext) if self._are_php_eggs(query_results): # analyze the info to see if we can identify the version self._extract_version_from_egg(query_results) raise NoMoreCalls def _get_php_eggs(self, fuzzable_request, ext): """ HTTP GET the URLs for PHP Eggs :return: A list with the HTTP response objects """ def http_get(fuzzable_request, (egg_url, egg_desc)): egg_url = fuzzable_request.get_url().uri2url().url_join(egg_url) response = self._uri_opener.GET(egg_url, cache=True, grep=False) return response, egg_url, egg_desc # Send the requests using threads: query_results = [] http_get = one_to_many(http_get) fr_repeater = repeat(fuzzable_request) args_iterator = izip(fr_repeater, self.PHP_EGGS) pool_results = self.worker_pool.imap_unordered(http_get, args_iterator) for response, egg_URL, egg_desc in pool_results: eqr = EggQueryResult(response, egg_desc, egg_URL) query_results.append(eqr) return query_results
def http_get(fuzzable_request, (egg_url, egg_desc)): egg_URL = fuzzable_request.get_url().uri2url().url_join(egg_url) try: response = self._uri_opener.GET(egg_URL, cache=True) except BaseFrameworkException, w3: raise w3 else: return response, egg_URL, egg_desc # Send the requests using threads: query_results = [] EggQueryResult = namedtuple('EggQueryResult', ['http_response', 'egg_desc', 'egg_URL']) http_get = one_to_many(http_get) fr_repeater = repeat(fuzzable_request) args_iterator = izip(fr_repeater, self.PHP_EGGS) pool_results = self.worker_pool.imap_unordered(http_get, args_iterator) for response, egg_URL, egg_desc in pool_results: eqr = EggQueryResult(response, egg_desc, egg_URL) query_results.append(eqr) return query_results def _are_php_eggs(self, query_results): """ Now I analyze if this is really a PHP eggs thing, or simply a response that changes a lot on each request. Before, I had something like this: