diff --git a/etc/checksum/md5sum.md5 b/etc/checksum/md5sum.md5
index d0ddafc..6c8242b 100644
--- a/etc/checksum/md5sum.md5
+++ b/etc/checksum/md5sum.md5
@@ -11,7 +11,7 @@ d3ad89703575a712a0aeead2b176d8c5 ./etc/html/clickjacking_test_page.html
82cc68f46539d0255f7ce14cd86cd49b ./etc/text_files/link_ext.txt
9659c647c725773e82d130e0f5c73c57 ./etc/text_files/dorks.txt
dc7bfc3d7b9b23340ee37806316bd770 ./etc/text_files/xss_payloads.txt
-b795ccb193f307a8e9a4a888c018241a ./etc/xml/headers.xml
+5250f0aa13b8af4775efa506e77de1ce ./etc/xml/headers.xml
d41d8cd98f00b204e9800998ecf8427e ./bin/__init__.py
ebd255c3ab49efde3155338e5d596b63 ./bin/unzip_gecko.py
dc1eb4ebe0f372af48b5a9c107ebc68d ./bin/drivers/geckodriver-v0.18.0-linux32.tar.gz
@@ -62,22 +62,22 @@ bbd8b4c6100070d420d48dc7dfc297eb ./lib/firewall/webknight.py
81a29a14d72980a306fbaec0dc772048 ./lib/firewall/fortigate.py
6ea65a0160c21e144e92334acc2e3667 ./lib/firewall/anquanbao.py
22a0ad8f2fa1a16b651cb5ae37ca9b0d ./lib/firewall/generic.py
-67ae989c771f1069095aaae7ec3a96d7 ./lib/attacks/gist_lookup/__init__.py
+ddf45537bdcea15d3b428495985bad09 ./lib/attacks/gist_lookup/__init__.py
7183dbd7106ecb436176cebcca4e499f ./lib/attacks/clickjacking_scan/__init__.py
d41d8cd98f00b204e9800998ecf8427e ./lib/attacks/__init__.py
4c644b0e3a62b6c1528d34a04837aa35 ./lib/attacks/sqlmap_scan/__init__.py
5e5bb575014ebe613db6bf671d008cf8 ./lib/attacks/sqlmap_scan/sqlmap_opts.py
7bc7a6f3e85651aab3588f087563eded ./lib/attacks/whois_lookup/__init__.py
8ec72bb33df998e32b925e3060d9d17a ./lib/attacks/whois_lookup/whois.py
-2d7686f1b9b93c3989bc5f279a1a064a ./lib/attacks/admin_panel_finder/__init__.py
-cc5e5838893eba60cf4bd33d38007e32 ./lib/attacks/xss_scan/__init__.py
-lib/attacks/nmap_scan/__init__.py ./lib/attacks/nmap_scan/__init__.py
+67ac65be1b4394ad80ec0fd3472c5309 ./lib/attacks/admin_panel_finder/__init__.py
+75652b6197e9775e58e177f5e2fc680c ./lib/attacks/xss_scan/__init__.py
+75652b6197e9775e58e177f5e2fc680c ./lib/attacks/nmap_scan/__init__.py
216999fa0e84866d5c1d96d5676034e4 ./lib/attacks/nmap_scan/nmap_opts.py
888686098a0850750f2435d0e1645944 ./lib/header_check/__init__.py
-39221756c132732dbdc2b14772dcab11 ./lib/core/common.py
+0721c655d433dbc170756f3e40a786cf ./lib/core/common.py
4433353fb5c55578391d8b4006191ee8 ./lib/core/errors.py
d41d8cd98f00b204e9800998ecf8427e ./lib/core/__init__.py
-ebcd664dbeda6cb93c9e66c71aa45a33 ./lib/core/settings.py
+5f7fd52c614f1a0f280191592d4b08b3 ./lib/core/settings.py
801a4f7ac892b74676c649bd4844ccdb ./lib/core/decorators.py
9a02e5b913d210350545ac26510a63c9 ./var/search/__init__.py
0545ee54ade186681b25d157fb32f350 ./var/search/selenium_search.py
diff --git a/etc/xml/headers.xml b/etc/xml/headers.xml
index ab2aaf3..038552b 100644
--- a/etc/xml/headers.xml
+++ b/etc/xml/headers.xml
@@ -5,4 +5,6 @@
+
+
\ No newline at end of file
diff --git a/lib/attacks/admin_panel_finder/__init__.py b/lib/attacks/admin_panel_finder/__init__.py
index b54770f..63a92d5 100644
--- a/lib/attacks/admin_panel_finder/__init__.py
+++ b/lib/attacks/admin_panel_finder/__init__.py
@@ -136,11 +136,13 @@ def check_for_admin_page(url, exts, protocol="http://", **kwargs):
))
possible_connections.add(true_url)
else:
- lib.core.settings.logger.error(lib.core.settings.set_color(
- "failed to connect got error code {}...".format(
- data[2]
- ), level=40
- ))
+ for error_code in lib.core.common.STATUS_CODES.iterkeys():
+ if int(data[2].split(":")[0]) == error_code:
+ lib.core.settings.logger.error(lib.core.settings.set_color(
+ "failed to connect got error code {} (reason: {})...".format(
+ data[2], lib.core.common.STATUS_CODES[error_code]
+ ), level=40
+ ))
except Exception as e:
if verbose:
if "" or "timeout: timed out" in str(e):
diff --git a/lib/attacks/gist_lookup/__init__.py b/lib/attacks/gist_lookup/__init__.py
index 59b2c13..531ad0a 100644
--- a/lib/attacks/gist_lookup/__init__.py
+++ b/lib/attacks/gist_lookup/__init__.py
@@ -79,12 +79,18 @@ def check_files_for_information(found_url, data_to_search):
# we need to create the query to be just the domain name
data_to_search = data_to_search.split(".")[1]
data_regex_schema = (
- re.compile(r"{}".format(data_to_search), re.I), # a regular match
- re.compile(r"(http(s)?)(.//)?{}".format(data_to_search), re.I), # match a URL containing our string
- re.compile(r"(.)?{}(.)?".format(data_to_search), re.I), # if it has anything around it
- re.compile(r"\b{}".format(data_to_search), re.I), # single boundary match
- re.compile(r"\b{}\b".format(data_to_search), re.I), # double boundary match
- re.compile(r"{}*".format(data_to_search), re.I) # wildcard match
+ # a normal regex with our string
+ re.compile(r"{}".format(data_to_search), re.I),
+ # match a URL with or without www
+ re.compile(r"(http(s)?)?(.//)?(www.)?{}".format(data_to_search), re.I),
+ # match our string and any random character around it (I like to call it the tittyex)
+ re.compile(r"(.)?{}(.)?".format(data_to_search), re.I),
+ # single boundary match, checks if it's inside of something else
+ re.compile(r"\b{}".format(data_to_search), re.I),
+ # double boundary, same as above but with another boundary
+ re.compile(r"\b{}\b".format(data_to_search), re.I),
+ # wildcard match
+ re.compile(r"{}*".format(data_to_search), re.I)
)
total_found = set()
try:
@@ -98,7 +104,9 @@ def check_files_for_information(found_url, data_to_search):
for data_regex in data_regex_schema:
if data_regex.search(data.content) is not None:
lib.core.settings.logger.info(lib.core.settings.set_color(
- "found a match with given specifics, saving full Gist to log file...", level=25
+ "found a match with given specifics ('{}'), saving full Gist to log file...".format(
+ data_regex.pattern
+ ), level=25
))
total_found.add(found_url)
lib.core.common.write_to_log_file(
diff --git a/lib/attacks/nmap_scan/__init__.py b/lib/attacks/nmap_scan/__init__.py
index 4e4a82c..b1036f3 100644
--- a/lib/attacks/nmap_scan/__init__.py
+++ b/lib/attacks/nmap_scan/__init__.py
@@ -41,11 +41,10 @@ class NmapHook(object):
"""
send all the information to a JSON file for further use
"""
- lib.core.settings.create_dir(self.dir)
- full_nmap_path = "{}/{}".format(self.dir, self.file.format(self.ip))
- with open(full_nmap_path, "a+") as log:
- log.write(data)
- return full_nmap_path
+ lib.core.common.write_to_log_file(
+ data, lib.core.settings.NMAP_LOG_FILE_PATH,
+ lib.core.settings.NMAP_FILENAME.format(self.ip)
+ )
def show_open_ports(self, json_data, sep="-" * 30):
"""
@@ -59,7 +58,7 @@ class NmapHook(object):
print(
"{}\nScanned: {} ({})\tStatus: {}\nProtocol: {}\n".format(
sep, self.ip,
- host if host is not "" or None or len(host) == 0 else "unknown",
+ host if host is not "" or None or not len(host) == 0 else "unknown",
json_data[self.ip]["status"]["state"],
"TCP"
)
@@ -107,6 +106,8 @@ def perform_port_scan(url, scanner=NmapHook, **kwargs):
lib.core.settings.logger.info(lib.core.settings.set_color(
"attempting to find IP address for hostname '{}'...".format(url)
))
+ if "www" not in url:
+ url = "www.{}".format(url)
try:
found_ip_address = socket.gethostbyname(url)
except socket.gaierror:
diff --git a/lib/attacks/xss_scan/__init__.py b/lib/attacks/xss_scan/__init__.py
index 24ca387..73aa0ed 100644
--- a/lib/attacks/xss_scan/__init__.py
+++ b/lib/attacks/xss_scan/__init__.py
@@ -136,6 +136,23 @@ def main_xss(start_url, proxy=None, agent=None, **kwargs):
verbose = kwargs.get("verbose", False)
batch = kwargs.get("batch", False)
+ question_msg = (
+ "it appears that heuristic tests have shown this URL may not be a good "
+ "candidate to perform XSS tests on, would you like to continue anyways"
+ )
+ if not batch:
+ if not lib.core.settings.URL_QUERY_REGEX.match(start_url):
+ question = lib.core.common.prompt(
+ question_msg, opts="yN"
+ )
+ else:
+ question = lib.core.common.prompt(
+ question_msg, opts="yN", default="y"
+ )
+
+ if not question.lower().startswith("y"):
+ return
+
try:
if tamper:
lib.core.settings.logger.info(lib.core.settings.set_color(
@@ -171,7 +188,7 @@ def main_xss(start_url, proxy=None, agent=None, **kwargs):
payload = find_xss_script(url)
try:
result = scan_xss(url, proxy=proxy, agent=agent)
- except requests.exceptions.ConnectionError:
+ except (requests.exceptions.ConnectionError, requests.exceptions.TooManyRedirects):
lib.core.settings.logger.error(lib.core.settings.set_color(
"payload '{}' caused a connection error, assuming no good and continuing...".format(payload), level=40
))
@@ -214,7 +231,7 @@ def main_xss(start_url, proxy=None, agent=None, **kwargs):
lib.core.settings.logger.error(lib.core.settings.set_color(
"host '{}' does not appear to be vulnerable to XSS attacks...".format(start_url)
))
- question_msg = "would you like to keep the URL's saved for further testing"
+ question_msg = "would you like to keep the created URLs saved for further testing"
if not batch:
save = lib.core.common.prompt(
question_msg, opts="yN"
diff --git a/lib/core/common.py b/lib/core/common.py
index 95dccc4..0a9ac40 100644
--- a/lib/core/common.py
+++ b/lib/core/common.py
@@ -19,11 +19,27 @@ import lib.core.settings
# reference https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
STATUS_CODES = {
- 200: "OK", 300: "multiple choices", 302: "not found",
- 400: "bad request", 401: "unauthorized", 403: "forbidden",
- 404: "not found", 405: "method not allowed", 500: "internal server error",
- 501: "not implemented", 502: "bad gateway", 503: "service unavailable",
- "other": "unexpected error code"
+ 100: "continue", 101: "switching protocols", 102: "processing",
+ 200: "OK", 201: "created", 202: "accepted", 203: "non-authoritative information",
+ 204: "no content", 205: "reset content", 206: "partial content",
+ 207: "multi-status", 208: "already reported", 226: "IM used",
+ 300: "multiple choices", 301: "moved permanently", 302: "not found",
+ 303: "see other", 304: "not modified", 305: "use proxy",
+ 306: "switch proxy", 308: "permanent redirect",
+ 400: "bad request", 401: "unauthorized", 402: "payment required",
+ 403: "forbidden", 404: "not found", 405: "method not allowed",
+ 406: "not acceptable", 407: "proxy authentication required", 408: "request timed out",
+ 409: "conflict", 410: "gone", 411: "length required", 412: "precondition failed",
+ 413: "payload to large", 414: "URI too long", 415: "unsupported media type",
+ 416: "range not satisfiable", 417: "expectation failed", 418: "im a teapot {EASTER EGG!}",
+ 421: "misdirected request", 422: "unprocesseable entity", 423: "locked",
+ 424: "failed dependency", 426: "upgrade requried", 428: "precondition required",
+ 429: "to many requests", 431: "request headers field too large",
+ 451: "unavailable for legal reasons",
+ 500: "internal server error", 501: "not implemented", 502: "bad gateway",
+ 503: "service unavailable", 504: "gateway timeout", 505: "HTTP version not supported",
+ 506: "variant also negotiable", 507: "insufficient storage", 508: "loop detected",
+ 510: "not extended", 511: "network authentication required", "other": "unexpected error code"
}
@@ -125,8 +141,7 @@ def write_to_log_file(data_to_write, path, filename, blacklist=False):
)
skip_log_schema = (
"url-log", "blackwidow-log", "zeus-log",
- "extracted", ".blacklist", "gist-match",
- "sqli-sites"
+ "extracted", ".blacklist", "sqli-sites"
)
to_search = filename.split("-")[0]
amount = len([f for f in os.listdir(path) if to_search in f])
diff --git a/lib/core/settings.py b/lib/core/settings.py
index 2908c0b..81f8dc1 100644
--- a/lib/core/settings.py
+++ b/lib/core/settings.py
@@ -46,7 +46,7 @@ CLONE = "https://github.com/ekultek/zeus-scanner.git"
ISSUE_LINK = "https://github.com/ekultek/zeus-scanner/issues"
# current version
-VERSION = "1.3.11.{}".format(PATCH_ID)
+VERSION = "1.3.12.{}".format(PATCH_ID)
# colors to output depending on the version
VERSION_TYPE_COLORS = {"dev": 33, "stable": 92, "other": 30}
@@ -182,6 +182,9 @@ SQLI_SITES_FILEPATH = "{}/log/sqli-sites".format(os.getcwd())
# the current log file being used
CURRENT_LOG_FILE_PATH = "{}/log".format(os.getcwd())
+# nmap scan log path
+NMAP_LOG_FILE_PATH = "{}/log/nmap-scan-log".format(os.getcwd())
+
# filename for sitemap log file
SITEMAP_FILENAME = "{}-sitemap.xml"
@@ -228,7 +231,7 @@ BLACKLIST_FILENAME = ".blacklist"
BLACKWIDOW_FILENAME = "blackwidow-log-{}.log"
# filename for nmap scans
-NMAP_FILENAME = "nmap-scan-results-{}.json"
+NMAP_FILENAME = "{}-nmap-scan-results.json"
# github autohorization token path
GITHUB_AUTH_PATH = "{}/etc/auths/git_auth".format(os.getcwd())