From 6030774303e70a5a27105e6be37de4a54db040ba Mon Sep 17 00:00:00 2001 From: ekultek Date: Sun, 29 Oct 2017 11:00:28 -0500 Subject: [PATCH] a patch for a reported issue (private) where if the found sitemap already exists, it would error out. will not just write as plain text and warn you that it probably already exists, also fixes an issue where found admin pages where not saved to a log file, and finally moved the sitemap.xml and robots.txt searches to a single function --- etc/checksum/md5sum.md5 | 6 +- lib/attacks/admin_panel_finder/__init__.py | 88 ++++++++++++---------- lib/core/settings.py | 13 +++- zeus.py | 8 +- 4 files changed, 64 insertions(+), 51 deletions(-) mode change 100644 => 100755 zeus.py diff --git a/etc/checksum/md5sum.md5 b/etc/checksum/md5sum.md5 index 58ff900..60753a2 100644 --- a/etc/checksum/md5sum.md5 +++ b/etc/checksum/md5sum.md5 @@ -1,4 +1,4 @@ -4910b563b0f2403dbe4a89f10001de0b ./zeus.py +1627b4ccf4cbc52b7408d7cde3c2a5e1 ./zeus.py 6ad5f22ec4a6f8324bfb1b01ab6d51ec ./etc/scripts/cleanup.sh 155c9482f690f1482f324a7ffd8b8098 ./etc/scripts/fix_pie.sh 0e435c641bc636ac0b3d54e032d9cf6a ./etc/scripts/install_nmap.sh @@ -36,14 +36,14 @@ d93cf7cdeabe951251f2f4d56687b5f4 ./lib/attacks/sqlmap_scan/__init__.py 5e5bb575014ebe613db6bf671d008cf8 ./lib/attacks/sqlmap_scan/sqlmap_opts.py d41d8cd98f00b204e9800998ecf8427e ./lib/attacks/whois_lookup/__init__.py f27322b9716e1a2b0b0b0487f3149474 ./lib/attacks/whois_lookup/whois.py -08fea2a989329d26774e60b7de3cf07e ./lib/attacks/admin_panel_finder/__init__.py +96fc5b718e60e5e9c82b1a0e38170d29 ./lib/attacks/admin_panel_finder/__init__.py 23c1e5e934029f9acc89d2c95e7748e7 ./lib/attacks/xss_scan/__init__.py 27358f26bda30d7356143c3ea1fa99c5 ./lib/attacks/nmap_scan/__init__.py 216999fa0e84866d5c1d96d5676034e4 ./lib/attacks/nmap_scan/nmap_opts.py f746d2867f493104a78d0540cf50c03f ./lib/attacks/intel_me/__init__.py 1faa2b5dfad6eb538bbfe42942d2a9da ./lib/core/errors.py d41d8cd98f00b204e9800998ecf8427e ./lib/core/__init__.py -819b60912d654bdd81b9d96bd757989f ./lib/core/settings.py +9dd8b8617f2b465f29d3e82c040eeb9e ./lib/core/settings.py d41d8cd98f00b204e9800998ecf8427e ./var/google_search/__init__.py b92ee17da90b17a0abb4e07e24fca3e1 ./var/google_search/search.py d41d8cd98f00b204e9800998ecf8427e ./var/__init__.py diff --git a/lib/attacks/admin_panel_finder/__init__.py b/lib/attacks/admin_panel_finder/__init__.py index 4ee17b5..22a3f65 100644 --- a/lib/attacks/admin_panel_finder/__init__.py +++ b/lib/attacks/admin_panel_finder/__init__.py @@ -18,59 +18,59 @@ from lib.core.settings import ( prompt, write_to_log_file, ROBOTS_PAGE_PATH, - SITEMAP_FILE_LOG_PATH + SITEMAP_FILE_LOG_PATH, + ADMIN_PAGE_FILE_PATH ) -def check_for_robots(url, ext="/robots.txt", data_sep="-" * 30): +def check_for_externals(url, robots=False, sitemap=False, data_sep="-" * 30, verbose=False): """ check if the URL has a robots.txt in it and collect `interesting` information out of the page """ + ext = { + robots: "/robots.txt", + sitemap: "/sitemap.xml" + } + currently_searching = ext[robots if robots else sitemap] + if verbose: + logger.debug(set_color( + "currently searching for a '{}'...".format(currently_searching), level=10 + )) url = replace_http(url) - interesting = set() - full_url = "{}{}{}".format("http://", url, ext) - conn = requests.get(full_url) - data = conn.content - code = conn.status_code - if code == 404: - return False - for line in data.split("\n"): - if "Allow" in line: - interesting.add(line.strip()) - if len(interesting) > 0: - create_tree(full_url, list(interesting)) - else: - to_display = prompt( - "nothing interesting found in robots.txt would you like to display the entire page", opts="yN" - ) - if to_display.lower().startswith("y"): - print( - "{}\n{}\n{}".format( - data_sep, data, data_sep - ) - ) - logger.info(set_color( - "robots.txt page will be saved into a file..." - )) - return write_to_log_file(data, ROBOTS_PAGE_PATH, "robots-{}.log".format(url)) - - -def check_for_sitemap(url, ext="/sitemap.xml"): - """ - check the URL for a sitemap.xml file - """ - url = replace_http(url) - full_url = "http://{}{}".format(url, ext) + full_url = "{}{}{}".format("http://", url, currently_searching) conn = requests.get(full_url) data = conn.content code = conn.status_code if code == 404: logger.error(set_color( - "no sitemap found, continuing...", level=40 + "unable to connect to '{}', assuming does not exist and continuing...".format( + full_url + ), level=40 )) return False - else: + if robots: + interesting = set() + for line in data.split("\n"): + if "Allow" in line: + interesting.add(line.strip()) + if len(interesting) > 0: + create_tree(full_url, list(interesting)) + else: + to_display = prompt( + "nothing interesting found in robots.txt would you like to display the entire page", opts="yN" + ) + if to_display.lower().startswith("y"): + print( + "{}\n{}\n{}".format( + data_sep, data, data_sep + ) + ) + logger.info(set_color( + "robots.txt page will be saved into a file..." + )) + return write_to_log_file(data, ROBOTS_PAGE_PATH, "robots-{}.log".format(url)) + elif sitemap: logger.info(set_color( "found a sitemap, saving to file..." )) @@ -152,6 +152,12 @@ def check_for_admin_page(url, exts, protocol="http://", **kwargs): "did not find any possible connections to {}'s " "admin page".format(url), level=50 )) + logger.warning(set_color( + "only writing successful connections to log file..." + )) + write_to_log_file(list(connections), ADMIN_PAGE_FILE_PATH, "{}-admin-page.log".format( + replace_http(url) + )) def __load_extensions(filename="{}/etc/link_ext.txt"): @@ -171,15 +177,15 @@ def main(url, show=False, verbose=False, **kwargs): logger.info(set_color( "parsing robots.txt..." )) - results = check_for_robots(url) + results = check_for_externals(url, robots=True) if not results: logger.warning(set_color( - "seems like this page is blocking access to robots.txt...", level=30 + "seems like this page is either blocking access to robots.txt or it does not exist...", level=30 )) logger.info(set_color( "checking for a sitemap..." )) - check_for_sitemap(url) + check_for_externals(url, sitemap=True) logger.info(set_color( "loading extensions..." )) diff --git a/lib/core/settings.py b/lib/core/settings.py index b09efbb..f9c1234 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -38,7 +38,7 @@ PATCH_ID = str(subprocess.check_output(["git", "rev-parse", "origin/master"]))[: # clone link CLONE = "https://github.com/ekultek/zeus-scanner.git" # current version -VERSION = "1.1.6.{}".format(PATCH_ID) +VERSION = "1.1.7.{}".format(PATCH_ID) # colors to output depending on the version VERSION_TYPE_COLORS = {"dev": 33, "stable": 92, "other": 30} # version string formatting @@ -82,6 +82,8 @@ LAUNCH_SQLMAP_API_TOOL = "{}/etc/scripts/launch_sqlmap_api.sh".format(os.getcwd( NMAP_INSTALLER_TOOL = "{}/etc/scripts/install_nmap.sh".format(os.getcwd()) # paths to sqlmap and nmap TOOL_PATHS = "{}/bin/paths/path_config.ini".format(os.getcwd()) +# the log for found admin pages on a site +ADMIN_PAGE_FILE_PATH = "{}/log/admin-page-log".format(os.getcwd()) # path to the sitemap log file SITEMAP_FILE_LOG_PATH = "{}/log/sitemap-log".format(os.getcwd()) # log path to the whois results @@ -454,7 +456,14 @@ def write_to_log_file(data_to_write, path, filename): with open(full_file_path, "a+") as log: data = re.sub(r'\s+', '', log.read()) if re.match(r'^<.+>$', data): - log.write(etree.tostring(data_to_write, pretty_print=True)) + try: + log.write(etree.tostring(data_to_write, pretty_print=True)) + except TypeError: + logger.warning(set_color( + "unable to serialize XML, writing as plain text (usually means the file already exists)...", + level=30 + )) + log.write(data_to_write) else: if isinstance(data_to_write, list): for item in data_to_write: diff --git a/zeus.py b/zeus.py old mode 100644 new mode 100755 index a88302f..6957330 --- a/zeus.py +++ b/zeus.py @@ -6,7 +6,6 @@ import io import shlex import subprocess import time - try: import http.client as http_client # Python 3 except ImportError: @@ -25,8 +24,6 @@ from lib.core.errors import ( InvalidInputProvided, InvalidProxyType ) - - from lib.attacks import ( nmap_scan, sqlmap_scan, @@ -59,6 +56,7 @@ from lib.core.settings import ( create_arguments ) + if __name__ == "__main__": parser = optparse.OptionParser(usage="{} -d|l|s|b DORK|FILE|URL [ATTACKS] [S-E] [--OPTS]".format( @@ -567,8 +565,8 @@ if __name__ == "__main__": shutdown() elif "Service geckodriver unexpectedly exited" in str(e): logger.fatal(set_color( - "it seems that your firefox version is not compatible with the geckodriver " - "version. please update firefox and try again...", level=50 + "it seems your firefox version is not compatible with the geckodriver version, " + "please re-install Zeus and try again...", level=50 )) shutdown() elif "Max retries exceeded with url" in str(e):