mirror of
https://github.com/Ekultek/Zeus-Scanner.git
synced 2026-03-11 08:55:51 +00:00
Compare commits
47 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21b8756306 | ||
|
|
d75169e401 | ||
|
|
f6a3ada2f0 | ||
|
|
ac83743b4d | ||
|
|
910c3e434a | ||
|
|
f512423c4e | ||
|
|
2ca5c5ac3f | ||
|
|
55ba7ca7fe | ||
|
|
caa7a4a564 | ||
|
|
3d8cf0e9f8 | ||
|
|
9dae61919d | ||
|
|
fe9c0abb76 | ||
|
|
443c0d94d1 | ||
|
|
cfc348f03f | ||
|
|
6cecf4f6d1 | ||
|
|
69a9305e11 | ||
|
|
f14bbe5645 | ||
|
|
51905bbc82 | ||
|
|
b857e6b120 | ||
|
|
ae134c3989 | ||
|
|
e5ac6316d3 | ||
|
|
cadc40b81a | ||
|
|
b0ea074e4e | ||
|
|
14f2506ef5 | ||
|
|
1bfac89266 | ||
|
|
f0056a0133 | ||
|
|
31c530cc9f | ||
|
|
1423e420d5 | ||
|
|
f7a7b436f8 | ||
|
|
05d88eaec8 | ||
|
|
73a6458fb8 | ||
|
|
aab81e892e | ||
|
|
6e2e13a2c7 | ||
|
|
a302562893 | ||
|
|
c83f745f84 | ||
|
|
301461bf71 | ||
|
|
14a7204e88 | ||
|
|
e5b52d7b45 | ||
|
|
362753d57c | ||
|
|
27701e6660 | ||
|
|
82f0c1f1ec | ||
|
|
b16a9c184a | ||
|
|
43199d690d | ||
|
|
0349835951 | ||
|
|
6e3d4b98f8 | ||
|
|
4e0945b842 | ||
|
|
b86db8008f |
34 changed files with 5169 additions and 5768 deletions
34
Dockerfile
Normal file
34
Dockerfile
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
FROM ubuntu:18.10
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN apt update && \
|
||||||
|
apt install -y \
|
||||||
|
libxml2-dev \
|
||||||
|
libxslt1-dev \
|
||||||
|
libgtk-3-dev \
|
||||||
|
libdbus-glib-1-2 \
|
||||||
|
python-dev \
|
||||||
|
python-pip \
|
||||||
|
git \
|
||||||
|
curl \
|
||||||
|
nmap \
|
||||||
|
sqlmap \
|
||||||
|
xvfb \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
ARG GECKO_DRIVER_VERSION=0.23.0
|
||||||
|
ARG FIREFOX_VERSION=58.0.2
|
||||||
|
|
||||||
|
RUN git clone https://github.com/ekultek/zeus-scanner.git . && \
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
|
RUN curl -L https://github.com/mozilla/geckodriver/releases/download/v${GECKO_DRIVER_VERSION}/geckodriver-v${GECKO_DRIVER_VERSION}-linux64.tar.gz | tar xz -C /usr/bin
|
||||||
|
|
||||||
|
RUN curl -L https://ftp.mozilla.org/pub/firefox/releases/${FIREFOX_VERSION}/linux-$(uname -m)/en-US/firefox-${FIREFOX_VERSION}.tar.bz2 -o firefox.tar.bz2 && \
|
||||||
|
tar xjf firefox.tar.bz2 -C /opt && \
|
||||||
|
rm firefox.tar.bz2 && \
|
||||||
|
ln -s /opt/firefox/firefox /usr/bin/firefox
|
||||||
|
|
||||||
|
CMD ["python", "zeus.py"]
|
||||||
|
|
||||||
41
README.md
41
README.md
|
|
@ -1,8 +1,12 @@
|
||||||
|
**_NOTE: due to dumbass people, automatic issue creation has been turned off until further notice_**
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
[](https://github.com/ekultek/zeus-scanner/stargazers)
|
[](https://github.com/ekultek/zeus-scanner/stargazers)
|
||||||
[](https://github.com/ekultek/zeus-scanner/network)
|
[](https://github.com/ekultek/zeus-scanner/network)
|
||||||
[](https://github.com/ekultek/zeus-scanner/issues)
|
[](https://github.com/ekultek/zeus-scanner/issues)
|
||||||
[](https://raw.githubusercontent.com/Ekultek/Zeus-Scanner/master/.github/LICENSE.md)
|
[](https://raw.githubusercontent.com/Ekultek/Zeus-Scanner/master/.github/LICENSE.md)
|
||||||
[](https://twitter.com/Zeus_Scanner)
|
[](https://twitter.com/stay__salty)
|
||||||
[](https://github.com/Ekultek/Zeus-Scanner#donations)
|
[](https://github.com/Ekultek/Zeus-Scanner#donations)
|
||||||
|
|
||||||
# Helpful links directory
|
# Helpful links directory
|
||||||
|
|
@ -13,6 +17,7 @@
|
||||||
- [Requirements and installation](https://github.com/Ekultek/Zeus-Scanner#requirements)
|
- [Requirements and installation](https://github.com/Ekultek/Zeus-Scanner#requirements)
|
||||||
- [Ubuntu/Debian](https://github.com/Ekultek/Zeus-Scanner#ubuntudebian)
|
- [Ubuntu/Debian](https://github.com/Ekultek/Zeus-Scanner#ubuntudebian)
|
||||||
- [centOS](https://github.com/Ekultek/Zeus-Scanner#centos)
|
- [centOS](https://github.com/Ekultek/Zeus-Scanner#centos)
|
||||||
|
- [Backbox](https://github.com/Ekultek/Zeus-Scanner#backbox)
|
||||||
- [other](https://github.com/Ekultek/Zeus-Scanner#others)
|
- [other](https://github.com/Ekultek/Zeus-Scanner#others)
|
||||||
- [Screenshots](https://github.com/Ekultek/Zeus-Scanner#screenshots)
|
- [Screenshots](https://github.com/Ekultek/Zeus-Scanner#screenshots)
|
||||||
- [Demo video](https://vimeo.com/239885768)
|
- [Demo video](https://vimeo.com/239885768)
|
||||||
|
|
@ -79,7 +84,7 @@ There are some requirements for this to be run successfully.
|
||||||
##### Basic requirements
|
##### Basic requirements
|
||||||
|
|
||||||
- `libxml2-dev`, `libxslt1-dev`, `python-dev` are required for the installation process
|
- `libxml2-dev`, `libxslt1-dev`, `python-dev` are required for the installation process
|
||||||
- Firefox web browser is required as of now, you will need Firefox version `<=57 >=51` (between 51 and 57). Full functionality for other browsers will eventually be added.
|
- Firefox web browser is required as of now, you will need Firefox version `<=58 >=52` (between 52 and 58). Full functionality for other browsers will eventually be added.
|
||||||
- If you want to run sqlmap through the URL's you will need sqlmap somewhere on your system.
|
- If you want to run sqlmap through the URL's you will need sqlmap somewhere on your system.
|
||||||
- If you want to run a port scan using nmap on the URL's IP addresses. You will need nmap on your system.
|
- If you want to run a port scan using nmap on the URL's IP addresses. You will need nmap on your system.
|
||||||
- [Geckodriver](https://github.com/mozilla/geckodriver) is required to run the firefox web browser and will be installed the first time you run. It will be added to your `/usr/bin` so that it can be run in your ENV PATH.
|
- [Geckodriver](https://github.com/mozilla/geckodriver) is required to run the firefox web browser and will be installed the first time you run. It will be added to your `/usr/bin` so that it can be run in your ENV PATH.
|
||||||
|
|
@ -99,7 +104,7 @@ There are some requirements for this to be run successfully.
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
You can download the latest [tar.gz](https://github.com/ekultek/zeus-scanner/tarball/master), the latest [zip](https://github.com/ekultek/zeus-scanner/zipball/master), or you can find the current stable release [here](https://github.com/Ekultek/Zeus-Scanner/releases/tag/v1.4). Alternatively you can install the latest development version by following the instructions that best match your operating system:
|
You can download the latest [tar.gz](https://github.com/ekultek/zeus-scanner/tarball/master), the latest [zip](https://github.com/ekultek/zeus-scanner/zipball/master), or you can find the current stable release [here](https://github.com/Ekultek/Zeus-Scanner/releases/tag/v1.5). Alternatively you can install the latest development version by following the instructions that best match your operating system:
|
||||||
|
|
||||||
**_NOTE: (optional but highly advised)_** add sqlmap and nmap to your environment PATH by moving them to `/usr/bin` or by adding them to the PATH via terminal
|
**_NOTE: (optional but highly advised)_** add sqlmap and nmap to your environment PATH by moving them to `/usr/bin` or by adding them to the PATH via terminal
|
||||||
|
|
||||||
|
|
@ -115,6 +120,36 @@ sudo apt-get install libxml2-dev libxslt1-dev python-dev && git clone https://g
|
||||||
sudo apt-get install gcc python-devel libxml2-dev libxslt1-dev python-dev && git clone https://github.com/ekultek/zeus-scanner.git && cd zeus-scanner && sudo pip2 install -r requirements.txt && sudo python zeus.py
|
sudo apt-get install gcc python-devel libxml2-dev libxslt1-dev python-dev && git clone https://github.com/ekultek/zeus-scanner.git && cd zeus-scanner && sudo pip2 install -r requirements.txt && sudo python zeus.py
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Backbox
|
||||||
|
|
||||||
|
64 bit installation:
|
||||||
|
```
|
||||||
|
sudo -s << EOF
|
||||||
|
aptitude purge firefox
|
||||||
|
wget https://ftp.mozilla.org/pub/firefox/releases/57.0/linux-x86_64/en-US/firefox-57.0.tar.bz2
|
||||||
|
tar -xjf firefox-57.0.tar.bz2
|
||||||
|
rm -rf /opt/firefox*
|
||||||
|
mv firefox /opt/firefox57
|
||||||
|
mv /usr/bin/firefox /usr/bin/firefoxold
|
||||||
|
ln -s /opt/firefox57/firefox-bin /usr/bin/firefox
|
||||||
|
apt-get install libxml2-dev libxslt1-dev python-dev && git clone https://github.com/ekultek/zeus-scanner.git && cd zeus-scanner && pip2 install -r requirements.txt && python zeus.py
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
32 bit installation:
|
||||||
|
```
|
||||||
|
sudo -s << EOF
|
||||||
|
aptitude purge firefox
|
||||||
|
wget https://ftp.mozilla.org/pub/firefox/releases/57.0/linux-i686/en-US/firefox-57.0.tar.bz2
|
||||||
|
tar -xjf firefox-57.0.tar.bz2
|
||||||
|
rm -rf /opt/firefox*
|
||||||
|
mv firefox /opt/firefox57
|
||||||
|
mv /usr/bin/firefox /usr/bin/firefoxold
|
||||||
|
ln -s /opt/firefox57/firefox-bin /usr/bin/firefox
|
||||||
|
apt-get install libxml2-dev libxslt1-dev python-dev && git clone https://github.com/ekultek/zeus-scanner.git && cd zeus-scanner && pip2 install -r requirements.txt && python zeus.py
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
##### Others
|
##### Others
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import shlex
|
||||||
import platform
|
import platform
|
||||||
|
import threading
|
||||||
import subprocess
|
import subprocess
|
||||||
import tarfile
|
import tarfile
|
||||||
try:
|
try:
|
||||||
|
|
@ -13,6 +17,27 @@ import lib.core.common
|
||||||
import lib.core.settings
|
import lib.core.settings
|
||||||
|
|
||||||
|
|
||||||
|
stop_animation = False
|
||||||
|
xvfb_path = "{}/etc/scripts/install_xvfb.sh".format(os.getcwd())
|
||||||
|
|
||||||
|
|
||||||
|
def animation(text):
|
||||||
|
global stop_animation
|
||||||
|
i = 0
|
||||||
|
while not stop_animation:
|
||||||
|
temp_text = list(text)
|
||||||
|
if i >= len(temp_text):
|
||||||
|
i = 0
|
||||||
|
temp_text[i] = temp_text[i].upper()
|
||||||
|
temp_text = ''.join(temp_text)
|
||||||
|
sys.stdout.write("\033[92m{}\r\033[0m".format(temp_text))
|
||||||
|
sys.stdout.flush()
|
||||||
|
i += 1
|
||||||
|
time.sleep(0.1)
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def disclaimer():
|
def disclaimer():
|
||||||
question = raw_input(
|
question = raw_input(
|
||||||
"\033[91mAttacking targets without consent is not only illegal, but it "
|
"\033[91mAttacking targets without consent is not only illegal, but it "
|
||||||
|
|
@ -28,7 +53,7 @@ def disclaimer():
|
||||||
else:
|
else:
|
||||||
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
||||||
"you have not agreed with the terms of service, so "
|
"you have not agreed with the terms of service, so "
|
||||||
"Zeus will shut down now...", level=50
|
"Zeus will shut down now", level=50
|
||||||
))
|
))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
@ -46,6 +71,8 @@ def parse_hosts(filepath="/etc/hosts"):
|
||||||
|
|
||||||
|
|
||||||
def find_tools(to_search=("sqlmap", "nmap"), directory="{}/bin/paths", filename="path_config.ini"):
|
def find_tools(to_search=("sqlmap", "nmap"), directory="{}/bin/paths", filename="path_config.ini"):
|
||||||
|
global stop_animation
|
||||||
|
|
||||||
lib.core.settings.create_dir(directory.format(os.getcwd()))
|
lib.core.settings.create_dir(directory.format(os.getcwd()))
|
||||||
full_path = "{}/{}".format(
|
full_path = "{}/{}".format(
|
||||||
directory.format(os.getcwd()),
|
directory.format(os.getcwd()),
|
||||||
|
|
@ -62,6 +89,8 @@ def find_tools(to_search=("sqlmap", "nmap"), directory="{}/bin/paths", filename=
|
||||||
path_schema[item] = None
|
path_schema[item] = None
|
||||||
for key, value in path_schema.iteritems():
|
for key, value in path_schema.iteritems():
|
||||||
if value is None:
|
if value is None:
|
||||||
|
stop_animation = True
|
||||||
|
print("\n")
|
||||||
provided_path = lib.core.common.prompt(
|
provided_path = lib.core.common.prompt(
|
||||||
"what is the full path to {} on your system".format(key)
|
"what is the full path to {} on your system".format(key)
|
||||||
)
|
)
|
||||||
|
|
@ -78,9 +107,9 @@ def config_gecko_version(browser_version):
|
||||||
figure out which gecko version you need
|
figure out which gecko version you need
|
||||||
"""
|
"""
|
||||||
version_specs = {
|
version_specs = {
|
||||||
(56, 57): 19,
|
(57, 58): 19,
|
||||||
(55, 54): 18,
|
(56, 55, 54): 18,
|
||||||
(53, 52, 51): 17
|
(53, 52): 17
|
||||||
}
|
}
|
||||||
if isinstance(browser_version, (tuple, list, set)):
|
if isinstance(browser_version, (tuple, list, set)):
|
||||||
major = browser_version[0]
|
major = browser_version[0]
|
||||||
|
|
@ -112,11 +141,13 @@ def check_xvfb(exc="Xvfb"):
|
||||||
"""
|
"""
|
||||||
test for xvfb on the users system
|
test for xvfb on the users system
|
||||||
"""
|
"""
|
||||||
|
global xvfb_path
|
||||||
|
global stop_animation
|
||||||
if whichcraft.which(exc) is None:
|
if whichcraft.which(exc) is None:
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
cmd = shlex.split("sudo sh {}".format(xvfb_path))
|
||||||
"installing Xvfb, required by pyvirutaldisplay..."
|
subprocess.call(cmd)
|
||||||
))
|
stop_animation = True
|
||||||
subprocess.call(["sudo", "apt-get", "install", "xvfb"])
|
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
@ -136,53 +167,45 @@ def check_if_run(file_check="{}/bin/executed.txt"):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def untar_gecko(filename="{}/bin/drivers/geckodriver-v0.{}.0-linux{}.tar.gz", verbose=False):
|
def untar_gecko(filename="{}/bin/drivers/geckodriver-v0.{}.0-linux{}.tar.gz"):
|
||||||
"""
|
"""
|
||||||
untar the correct gecko driver for your computer architecture
|
untar the correct gecko driver for your computer architecture
|
||||||
"""
|
"""
|
||||||
|
global stop_animation
|
||||||
|
|
||||||
arch_info = {"64bit": "64", "32bit": "32"}
|
arch_info = {"64bit": "64", "32bit": "32"}
|
||||||
file_arch = arch_info[platform.architecture()[0]]
|
file_arch = arch_info[platform.architecture()[0]]
|
||||||
ff_version = lib.core.settings.get_browser_version()
|
ff_version = lib.core.settings.get_browser_version(output=False)
|
||||||
if isinstance(ff_version, str) or ff_version is None:
|
if isinstance(ff_version, str) or ff_version is None:
|
||||||
|
stop_animation = True
|
||||||
ff_version = lib.core.common.prompt(
|
ff_version = lib.core.common.prompt(
|
||||||
"enter your firefox browser version (if you don't know it run firefox --version"
|
"enter your firefox browser version (if you don't know it run firefox --version)"
|
||||||
)
|
)
|
||||||
gecko_version = config_gecko_version(ff_version)
|
gecko_version = config_gecko_version(ff_version)
|
||||||
if gecko_version is None:
|
if gecko_version is None:
|
||||||
|
stop_animation = True
|
||||||
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
||||||
"your current firefox version is not supported by Zeus...", level=50
|
"your current firefox version is not supported by Zeus", level=50
|
||||||
))
|
))
|
||||||
lib.core.common.shutdown()
|
lib.core.common.shutdown()
|
||||||
gecko_full_filename = filename.format(os.getcwd(), gecko_version, file_arch)
|
gecko_full_filename = filename.format(os.getcwd(), gecko_version, file_arch)
|
||||||
with open(lib.core.settings.GECKO_VERSION_INFO_PATH, "a+") as log:
|
with open(lib.core.settings.GECKO_VERSION_INFO_PATH, "a+") as log:
|
||||||
log.write(gecko_full_filename.split("/")[-1])
|
log.write(gecko_full_filename.split("/")[-1])
|
||||||
tar = tarfile.open(filename.format(os.getcwd(), gecko_version, file_arch), "r:gz")
|
tar = tarfile.open(filename.format(os.getcwd(), gecko_version, file_arch), "r:gz")
|
||||||
if verbose:
|
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
|
||||||
"extracting the correct driver for your architecture...", level=10
|
|
||||||
))
|
|
||||||
try:
|
try:
|
||||||
tar.extractall("/usr/bin")
|
tar.extractall("/usr/bin")
|
||||||
if verbose:
|
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
|
||||||
"driver extracted into /usr/bin (you may change this, but ensure that it "
|
|
||||||
"is in your PATH)...", level=10
|
|
||||||
))
|
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
if "Text file busy" in str(e):
|
if "Text file busy" in str(e):
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
|
||||||
"the driver is already installed..."
|
|
||||||
))
|
|
||||||
tar.close()
|
tar.close()
|
||||||
pass
|
pass
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if "[Errno 13] Permission denied: '/usr/bin/geckodriver'" in str(e):
|
if "[Errno 13] Permission denied: '/usr/bin/geckodriver'" in str(e):
|
||||||
lib.core.settings.logger.exception(lib.core.settings.set_color(
|
lib.core.settings.logger.exception(lib.core.settings.set_color(
|
||||||
"first run must be ran as root (sudo python zeus.py)...", level=50
|
"first run must be ran as root (sudo python zeus.py)", level=50
|
||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
lib.core.settings.logger.exception(lib.core.settings.set_color(
|
lib.core.settings.logger.exception(lib.core.settings.set_color(
|
||||||
"ran into exception '{}', logged to current log file...".format(e), level=50
|
"ran into exception '{}', logged to current log file".format(e), level=50
|
||||||
))
|
))
|
||||||
exit(-1)
|
exit(-1)
|
||||||
tar.close()
|
tar.close()
|
||||||
|
|
@ -192,10 +215,6 @@ def ensure_placed(item="geckodriver", verbose=False):
|
||||||
"""
|
"""
|
||||||
use whichcraft to ensure that the driver has been placed in your PATH variable
|
use whichcraft to ensure that the driver has been placed in your PATH variable
|
||||||
"""
|
"""
|
||||||
if verbose:
|
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
|
||||||
"ensuring that the driver exists in your system path...", level=10
|
|
||||||
))
|
|
||||||
if not whichcraft.which(item):
|
if not whichcraft.which(item):
|
||||||
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
||||||
"the executable '{}' does not appear to be in your /usr/bin PATH. "
|
"the executable '{}' does not appear to be in your /usr/bin PATH. "
|
||||||
|
|
@ -204,10 +223,6 @@ def ensure_placed(item="geckodriver", verbose=False):
|
||||||
))
|
))
|
||||||
exit(-1)
|
exit(-1)
|
||||||
else:
|
else:
|
||||||
if verbose:
|
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
|
||||||
"driver exists, continuing...", level=10
|
|
||||||
))
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -215,39 +230,28 @@ def main(rewrite="{}/bin/executed.txt", verbose=False):
|
||||||
"""
|
"""
|
||||||
main method
|
main method
|
||||||
"""
|
"""
|
||||||
if verbose:
|
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
|
||||||
"verifying operating system...", level=10
|
|
||||||
))
|
|
||||||
if not check_os():
|
if not check_os():
|
||||||
raise NotImplementedError(lib.core.settings.set_color(
|
raise NotImplementedError(lib.core.settings.set_color(
|
||||||
"as of now, Zeus requires Linux to run successfully "
|
"as of now, Zeus requires Linux to run successfully "
|
||||||
"your current operating system '{}' is not implemented "
|
"your current operating system '{}' is not implemented "
|
||||||
"yet...".format(platform.platform()), level=50
|
"yet".format(platform.platform()), level=50
|
||||||
))
|
))
|
||||||
if check_if_run():
|
if check_if_run():
|
||||||
if not disclaimer():
|
if not disclaimer():
|
||||||
exit(1)
|
exit(1)
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
t = threading.Thread(target=animation, args=(
|
||||||
"seems this is your first time running the application, "
|
"seems this is your first time running the application, doing setup please wait..",))
|
||||||
"doing setup please wait..."
|
t.daemon = True
|
||||||
))
|
t.start()
|
||||||
if verbose:
|
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
|
||||||
"checking if xvfb is on your system...", level=10
|
|
||||||
))
|
|
||||||
find_tools()
|
find_tools()
|
||||||
check_xvfb()
|
check_xvfb()
|
||||||
untar_gecko(verbose=verbose)
|
untar_gecko()
|
||||||
parse_hosts()
|
parse_hosts()
|
||||||
if ensure_placed(verbose=verbose):
|
if ensure_placed(verbose=verbose):
|
||||||
with open(rewrite.format(os.getcwd()), "w") as rw:
|
with open(rewrite.format(os.getcwd()), "w") as rw:
|
||||||
rw.write("TRUE")
|
rw.write("TRUE")
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"done, continuing process..."
|
"done, continuing process"
|
||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
if verbose:
|
pass
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
|
||||||
"already ran, skipping...", level=10
|
|
||||||
))
|
|
||||||
|
|
|
||||||
|
|
@ -1,111 +1,119 @@
|
||||||
1caf80ae9a944960ef67773c2bbdd6b2 ./zeus.py
|
685a20fa3fc7652b5c3e39821cdc6f25 ./zeus.py
|
||||||
4b32db388e8acda35570c734d27c950c ./etc/scripts/launch_sqlmap.sh
|
4b32db388e8acda35570c734d27c950c ./etc/scripts/launch_sqlmap.sh
|
||||||
6ad5f22ec4a6f8324bfb1b01ab6d51ec ./etc/scripts/cleanup.sh
|
6ad5f22ec4a6f8324bfb1b01ab6d51ec ./etc/scripts/cleanup.sh
|
||||||
74d7bee13890a9dd279bb857591647ce ./etc/scripts/reinstall.sh
|
869025acb457dc881e53e440aa11dd7b ./etc/scripts/reinstall.sh
|
||||||
155c9482f690f1482f324a7ffd8b8098 ./etc/scripts/fix_pie.sh
|
155c9482f690f1482f324a7ffd8b8098 ./etc/scripts/fix_pie.sh
|
||||||
0e435c641bc636ac0b3d54e032d9cf6a ./etc/scripts/install_nmap.sh
|
0e435c641bc636ac0b3d54e032d9cf6a ./etc/scripts/install_nmap.sh
|
||||||
|
440431165b2db8a537c1a93cb2232f16 ./etc/scripts/install_xvfb.sh
|
||||||
66b11aa388ea909de7b212341259a318 ./etc/auths/git_auth
|
66b11aa388ea909de7b212341259a318 ./etc/auths/git_auth
|
||||||
8f686b05c5c5dfc02f0fcaa7ebc8677c ./etc/auths/whois_auth
|
8f686b05c5c5dfc02f0fcaa7ebc8677c ./etc/auths/whois_auth
|
||||||
d3ad89703575a712a0aeead2b176d8c5 ./etc/html/clickjacking_test_page.html
|
d3ad89703575a712a0aeead2b176d8c5 ./etc/html/clickjacking_test_page.html
|
||||||
642a77905d8bb4e5533e0e9c2137c0fa ./etc/text_files/agents.txt
|
642a77905d8bb4e5533e0e9c2137c0fa ./etc/text_files/agents.txt
|
||||||
82cc68f46539d0255f7ce14cd86cd49b ./etc/text_files/link_ext.txt
|
82cc68f46539d0255f7ce14cd86cd49b ./etc/text_files/link_ext.txt
|
||||||
9659c647c725773e82d130e0f5c73c57 ./etc/text_files/dorks.txt
|
c57ac34fe965961917ac8a207df256d5 ./etc/text_files/dorks.txt
|
||||||
dc7bfc3d7b9b23340ee37806316bd770 ./etc/text_files/xss_payloads.txt
|
cf85d83da34d70720193d83950c31fdc ./etc/text_files/xss_payloads.txt
|
||||||
|
6cabeb9919d2301efc4ba3d8869282d6 ./etc/checksum/md5sum.md5
|
||||||
5250f0aa13b8af4775efa506e77de1ce ./etc/xml/headers.xml
|
5250f0aa13b8af4775efa506e77de1ce ./etc/xml/headers.xml
|
||||||
d41d8cd98f00b204e9800998ecf8427e ./bin/__init__.py
|
d41d8cd98f00b204e9800998ecf8427e ./bin/__init__.py
|
||||||
ebd255c3ab49efde3155338e5d596b63 ./bin/unzip_gecko.py
|
3be7ee6f4267e0d0cf2143b58792527b ./bin/paths/path_config.ini
|
||||||
|
fa5084cc7ee56ff2df8631b76be5be4d ./bin/unzip_gecko.py
|
||||||
|
c0d83f0b82a6b30de8811e69e6d95c61 ./bin/executed.txt
|
||||||
dc1eb4ebe0f372af48b5a9c107ebc68d ./bin/drivers/geckodriver-v0.18.0-linux32.tar.gz
|
dc1eb4ebe0f372af48b5a9c107ebc68d ./bin/drivers/geckodriver-v0.18.0-linux32.tar.gz
|
||||||
be18faeea6e7db9db6990d8667e2298f ./bin/drivers/geckodriver-v0.17.0-linux64.tar.gz
|
be18faeea6e7db9db6990d8667e2298f ./bin/drivers/geckodriver-v0.17.0-linux64.tar.gz
|
||||||
79b1a158f96d29942a111c0905f1c807 ./bin/drivers/geckodriver-v0.17.0-linux32.tar.gz
|
79b1a158f96d29942a111c0905f1c807 ./bin/drivers/geckodriver-v0.17.0-linux32.tar.gz
|
||||||
ca6935a72fd0527d15a78a17a35e56e8 ./bin/drivers/geckodriver-v0.19.0-linux64.tar.gz
|
ca6935a72fd0527d15a78a17a35e56e8 ./bin/drivers/geckodriver-v0.19.0-linux64.tar.gz
|
||||||
4ccb56fb3700005c9f9188f84152f21a ./bin/drivers/geckodriver-v0.18.0-linux64.tar.gz
|
4ccb56fb3700005c9f9188f84152f21a ./bin/drivers/geckodriver-v0.18.0-linux64.tar.gz
|
||||||
07cd383c8aef8ea5ef194a506141afd6 ./bin/drivers/geckodriver-v0.19.0-linux32.tar.gz
|
07cd383c8aef8ea5ef194a506141afd6 ./bin/drivers/geckodriver-v0.19.0-linux32.tar.gz
|
||||||
785c28da8b681a7e23964f99118b5aab ./lib/tamper_scripts/obfuscateordinal_encode.py
|
145e4a7dc985e99962dabe3b221fc51e ./lib/tamper_scripts/obfuscateordinal_encode.py
|
||||||
10bf1bc4ef0287d31633148fab557e8a ./lib/tamper_scripts/uppercase_encode.py
|
10bf1bc4ef0287d31633148fab557e8a ./lib/tamper_scripts/uppercase_encode.py
|
||||||
5b68de0ce3a783b870921b09b5222146 ./lib/tamper_scripts/hex_encode.py
|
fcef22874b6732fd1b1bd062e18e65db ./lib/tamper_scripts/hex_encode.py
|
||||||
1537b3b94566aebf0f89bed074e96581 ./lib/tamper_scripts/url_encode.py
|
1537b3b94566aebf0f89bed074e96581 ./lib/tamper_scripts/url_encode.py
|
||||||
d41d8cd98f00b204e9800998ecf8427e ./lib/tamper_scripts/__init__.py
|
d41d8cd98f00b204e9800998ecf8427e ./lib/tamper_scripts/__init__.py
|
||||||
7b636a332b2e99547ec9565d8e094308 ./lib/tamper_scripts/unicode_encode.py
|
7b636a332b2e99547ec9565d8e094308 ./lib/tamper_scripts/unicode_encode.py
|
||||||
07a792bccd13f64873a27aee4aaa8ea6 ./lib/tamper_scripts/space2comment_encode.py
|
07a792bccd13f64873a27aee4aaa8ea6 ./lib/tamper_scripts/space2comment_encode.py
|
||||||
1053a0c89e514d2c94bc822d34715896 ./lib/tamper_scripts/randomcase_encode.py
|
1053a0c89e514d2c94bc822d34715896 ./lib/tamper_scripts/randomcase_encode.py
|
||||||
349c30cbab4308bd94829d92b4e34f9d ./lib/tamper_scripts/lowercase_encode.py
|
349c30cbab4308bd94829d92b4e34f9d ./lib/tamper_scripts/lowercase_encode.py
|
||||||
6e1d6276a295f6c5d41b6f6f0e1316b0 ./lib/tamper_scripts/enclosebrackets_encode.py
|
0c5e78674a8d27e7c20af1dca8656789 ./lib/tamper_scripts/enclosebrackets_encode.py
|
||||||
694231b4c2f99406481c34ced85ddfe1 ./lib/tamper_scripts/base64_encode.py
|
|
||||||
6ac38bec8c32eab57efa01f7a06dff14 ./lib/tamper_scripts/space2null_encode.py
|
|
||||||
3b8c95a6a3b7cecce5118f2fb1ccc6b8 ./lib/tamper_scripts/appendnull_encode.py
|
|
||||||
5824916df46428a8304ee0156bcee989 ./lib/tamper_scripts/multispace2comment_encode.py
|
5824916df46428a8304ee0156bcee989 ./lib/tamper_scripts/multispace2comment_encode.py
|
||||||
|
9fd42d65993aa20d1bf5acbc4d042d2e ./lib/tamper_scripts/base64_encode.py
|
||||||
|
f77b7a9a19b94e26903eeecf5a787ea3 ./lib/tamper_scripts/space2null_encode.py
|
||||||
|
3b8c95a6a3b7cecce5118f2fb1ccc6b8 ./lib/tamper_scripts/appendnull_encode.py
|
||||||
|
8e8792e38649f18d90bb0084202bb59e ./lib/tamper_scripts/obfuscateentity_encode.py
|
||||||
|
d41d8cd98f00b204e9800998ecf8427e ./lib/__init__.py
|
||||||
6299b188a730844954044887f528435a ./lib/firewall/cloudfront.py
|
6299b188a730844954044887f528435a ./lib/firewall/cloudfront.py
|
||||||
d41d8cd98f00b204e9800998ecf8427e ./lib/firewall/__init__.py
|
d41d8cd98f00b204e9800998ecf8427e ./lib/firewall/__init__.py
|
||||||
eb3a3066efbcf87dbc10a49be445cb8f ./lib/firewall/urlscan.py
|
81a29a14d72980a306fbaec0dc772048 ./lib/firewall/fortigate.py
|
||||||
d4986f3d95a773d7c3585b07bcd6310e ./lib/firewall/sucuri.py
|
d4986f3d95a773d7c3585b07bcd6310e ./lib/firewall/sucuri.py
|
||||||
|
763af6773e920d6bdc185f5bd4df6084 ./lib/firewall/dw.py
|
||||||
e4514021485dbb94c3f0023b04af01ad ./lib/firewall/aws.py
|
e4514021485dbb94c3f0023b04af01ad ./lib/firewall/aws.py
|
||||||
|
eb3a3066efbcf87dbc10a49be445cb8f ./lib/firewall/urlscan.py
|
||||||
|
71744d7a95f42063a8fb6e720932cd3d ./lib/firewall/sonicwall.py
|
||||||
|
7af3ee8615c7dc761f050e0ba638eaef ./lib/firewall/armor.py
|
||||||
1f303641d59686d544f2986ff74c6b31 ./lib/firewall/webseal.py
|
1f303641d59686d544f2986ff74c6b31 ./lib/firewall/webseal.py
|
||||||
|
78e6b01feb9bad68c2fc8a79e75930fd ./lib/firewall/yundun.py
|
||||||
e4eef006dd909c222b1b9f48826c3ef5 ./lib/firewall/pk.py
|
e4eef006dd909c222b1b9f48826c3ef5 ./lib/firewall/pk.py
|
||||||
|
bf5285dc059c761e1719bc734ae8504f ./lib/firewall/varnish.py
|
||||||
6b370050b40d8c1d2221424f756c7842 ./lib/firewall/paloalto.py
|
6b370050b40d8c1d2221424f756c7842 ./lib/firewall/paloalto.py
|
||||||
|
73c1727e604ec6e00541687bfc64c0d6 ./lib/firewall/akamai.py
|
||||||
6bbe2f6f6a2a1ddf0e416e94ec1f0763 ./lib/firewall/siteguard.py
|
6bbe2f6f6a2a1ddf0e416e94ec1f0763 ./lib/firewall/siteguard.py
|
||||||
787e21ed577ff05b095aa0f0e5e5e9bf ./lib/firewall/cloudflare.py
|
787e21ed577ff05b095aa0f0e5e5e9bf ./lib/firewall/cloudflare.py
|
||||||
c3f01fc8ff7dfe7759f63bf16b00f127 ./lib/firewall/wordfence.py
|
c3f01fc8ff7dfe7759f63bf16b00f127 ./lib/firewall/wordfence.py
|
||||||
6ccf3a1df5aa6429cd3365b7b8ded8f4 ./lib/firewall/powerful.py
|
2f0a935d2bb9b8aa711e511f48595a81 ./lib/firewall/powerful.py
|
||||||
54815706261c32b57fbbdc99244b5cdd ./lib/firewall/modsecurity.py
|
|
||||||
5ee20e2c158d0734b4dd5a8eb47f8ea5 ./lib/firewall/squid.py
|
|
||||||
71744d7a95f42063a8fb6e720932cd3d ./lib/firewall/sonicwall.py
|
|
||||||
9070b43428bd17fd5faf86995cb559a2 ./lib/firewall/stringray.py
|
|
||||||
bf5285dc059c761e1719bc734ae8504f ./lib/firewall/varnish.py
|
|
||||||
78e6b01feb9bad68c2fc8a79e75930fd ./lib/firewall/yundun.py
|
|
||||||
cb45428e92485b759ff5cb46a0be9c73 ./lib/firewall/yunsuo.py
|
|
||||||
bbd8b4c6100070d420d48dc7dfc297eb ./lib/firewall/webknight.py
|
bbd8b4c6100070d420d48dc7dfc297eb ./lib/firewall/webknight.py
|
||||||
|
54815706261c32b57fbbdc99244b5cdd ./lib/firewall/modsecurity.py
|
||||||
|
9070b43428bd17fd5faf86995cb559a2 ./lib/firewall/stringray.py
|
||||||
|
5ee20e2c158d0734b4dd5a8eb47f8ea5 ./lib/firewall/squid.py
|
||||||
95b908a21c0ff456ae59df4c6c189c54 ./lib/firewall/wallarm.py
|
95b908a21c0ff456ae59df4c6c189c54 ./lib/firewall/wallarm.py
|
||||||
|
cb45428e92485b759ff5cb46a0be9c73 ./lib/firewall/yunsuo.py
|
||||||
8fc8d62377bebbfa7ca4d70a79eab115 ./lib/firewall/bigip.py
|
8fc8d62377bebbfa7ca4d70a79eab115 ./lib/firewall/bigip.py
|
||||||
73c1727e604ec6e00541687bfc64c0d6 ./lib/firewall/akamai.py
|
|
||||||
7af3ee8615c7dc761f050e0ba638eaef ./lib/firewall/armor.py
|
|
||||||
763af6773e920d6bdc185f5bd4df6084 ./lib/firewall/dw.py
|
|
||||||
81a29a14d72980a306fbaec0dc772048 ./lib/firewall/fortigate.py
|
|
||||||
6ea65a0160c21e144e92334acc2e3667 ./lib/firewall/anquanbao.py
|
6ea65a0160c21e144e92334acc2e3667 ./lib/firewall/anquanbao.py
|
||||||
22a0ad8f2fa1a16b651cb5ae37ca9b0d ./lib/firewall/generic.py
|
22a0ad8f2fa1a16b651cb5ae37ca9b0d ./lib/firewall/generic.py
|
||||||
ed18ed1f72f3887e63fa7ce060841e4a ./lib/plugins/aardvark.py
|
ed18ed1f72f3887e63fa7ce060841e4a ./lib/plugins/aardvark.py
|
||||||
a8b3e6924bab72607b1d1c1a8dcb561d ./lib/plugins/4d.py
|
a8b3e6924bab72607b1d1c1a8dcb561d ./lib/plugins/4d.py
|
||||||
03355a122c047dc598fc271620119978 ./lib/plugins/jquery.py
|
03355a122c047dc598fc271620119978 ./lib/plugins/jquery.py
|
||||||
d41d8cd98f00b204e9800998ecf8427e ./lib/plugins/__init__.py
|
d41d8cd98f00b204e9800998ecf8427e ./lib/plugins/__init__.py
|
||||||
|
353db8b22c031433ea73a12943927557 ./lib/plugins/clipbucket.py
|
||||||
5908a81cc9b332348b26a3ccd5ddb798 ./lib/plugins/ihtml.py
|
5908a81cc9b332348b26a3ccd5ddb798 ./lib/plugins/ihtml.py
|
||||||
d76d2839ed8875739328bb5f2a838ba6 ./lib/plugins/360.py
|
d76d2839ed8875739328bb5f2a838ba6 ./lib/plugins/360.py
|
||||||
16e4708c510811760129f6fb4842e92e ./lib/plugins/3dcart.py
|
16e4708c510811760129f6fb4842e92e ./lib/plugins/3dcart.py
|
||||||
2ce0a2101bb5706a136de83a729965f3 ./lib/plugins/b2evolution.py
|
2ce0a2101bb5706a136de83a729965f3 ./lib/plugins/b2evolution.py
|
||||||
b4ab6d1e0d3582fc66111988b246acc0 ./lib/plugins/bmcremedy.py
|
497facc7b12e6e691aab65980d8f5026 ./lib/plugins/bmcremedy.py
|
||||||
2dcee5bc924732dd21f16983eef9a99d ./lib/plugins/abyss.py
|
2dcee5bc924732dd21f16983eef9a99d ./lib/plugins/abyss.py
|
||||||
d2c100e6e6f7fbda8448d36a6928c979 ./lib/plugins/68classified.py
|
d2c100e6e6f7fbda8448d36a6928c979 ./lib/plugins/68classified.py
|
||||||
f1eb201cce16853049a615805b01bc60 ./lib/plugins/bomgar.py
|
f1eb201cce16853049a615805b01bc60 ./lib/plugins/bomgar.py
|
||||||
|
ce3b79dc80e369ffd55d2cbe90e6a0ab ./lib/plugins/mssqlreportmanager.py
|
||||||
55ec8cde9d438a90327911910164abf2 ./lib/plugins/opengraph.py
|
55ec8cde9d438a90327911910164abf2 ./lib/plugins/opengraph.py
|
||||||
8658f8a185499ec6d10b1d2da6104c27 ./lib/plugins/atomfeed.py
|
8658f8a185499ec6d10b1d2da6104c27 ./lib/plugins/atomfeed.py
|
||||||
c2533d4a8dc5fdaa4b8d584588b32ec2 ./lib/plugins/html5.py
|
c2533d4a8dc5fdaa4b8d584588b32ec2 ./lib/plugins/html5.py
|
||||||
a3ed012f11ff2bffbc143fbef63d0c12 ./lib/plugins/3com.py
|
a3ed012f11ff2bffbc143fbef63d0c12 ./lib/plugins/3com.py
|
||||||
|
55d834ae87e96787807e21b65ec68bca ./lib/plugins/moodle.py
|
||||||
44019a327ec1db91851d652630788742 ./lib/plugins/googleapi.py
|
44019a327ec1db91851d652630788742 ./lib/plugins/googleapi.py
|
||||||
c4ac50a3f3550c62219e7e4f38d4b496 ./lib/plugins/1024.py
|
c4ac50a3f3550c62219e7e4f38d4b496 ./lib/plugins/1024.py
|
||||||
0b63885649f369ea410c8169e947fdab ./lib/plugins/accellion.py
|
0b63885649f369ea410c8169e947fdab ./lib/plugins/accellion.py
|
||||||
76a1d1decfb872bfafdf510c656f113a ./lib/plugins/rssfeed.py
|
76a1d1decfb872bfafdf510c656f113a ./lib/plugins/rssfeed.py
|
||||||
320f0db977c85b477ba1ea78b140cb8a ./lib/plugins/4images.py
|
320f0db977c85b477ba1ea78b140cb8a ./lib/plugins/4images.py
|
||||||
35dc8b7da4becb60662aab3c48a9210b ./lib/plugins/openxchange.py
|
35dc8b7da4becb60662aab3c48a9210b ./lib/plugins/openxchange.py
|
||||||
b5ff3286060c0bbc0fe1f0f591131c9c ./lib/attacks/gist_lookup/__init__.py
|
bdb7ff546787d38bbbd0aac9d4a4cdf8 ./lib/attacks/clickjacking_scan/__init__.py
|
||||||
86224bd899c2a2438042cbdc077dc4cc ./lib/attacks/clickjacking_scan/__init__.py
|
|
||||||
d41d8cd98f00b204e9800998ecf8427e ./lib/attacks/__init__.py
|
d41d8cd98f00b204e9800998ecf8427e ./lib/attacks/__init__.py
|
||||||
4c644b0e3a62b6c1528d34a04837aa35 ./lib/attacks/sqlmap_scan/__init__.py
|
6e9e0a9e2c72e00d8690c0177b695d56 ./lib/attacks/sqlmap_scan/__init__.py
|
||||||
5e5bb575014ebe613db6bf671d008cf8 ./lib/attacks/sqlmap_scan/sqlmap_opts.py
|
5e5bb575014ebe613db6bf671d008cf8 ./lib/attacks/sqlmap_scan/sqlmap_opts.py
|
||||||
7bc7a6f3e85651aab3588f087563eded ./lib/attacks/whois_lookup/__init__.py
|
d41d8cd98f00b204e9800998ecf8427e ./lib/attacks/whois_lookup/__init__.py
|
||||||
8ec72bb33df998e32b925e3060d9d17a ./lib/attacks/whois_lookup/whois.py
|
c5b69617f040fef1d5930948905aa8d0 ./lib/attacks/whois_lookup/whois.py
|
||||||
916b768e783ff771bce80bd6f5112d4f ./lib/attacks/admin_panel_finder/__init__.py
|
4fd96bb3002e949687d7ae863ee87264 ./lib/attacks/admin_panel_finder/__init__.py
|
||||||
52942c7b33ff696901f5a4201ba4507f ./lib/attacks/xss_scan/__init__.py
|
2017e69c3420c9e240fccb310f086da7 ./lib/attacks/xss_scan/__init__.py
|
||||||
7642d078fe304a7ca8bfaaa070a0cb31 ./lib/attacks/nmap_scan/__init__.py
|
40ba04fb18dcbb81cb42376a825c238f ./lib/attacks/nmap_scan/__init__.py
|
||||||
216999fa0e84866d5c1d96d5676034e4 ./lib/attacks/nmap_scan/nmap_opts.py
|
216999fa0e84866d5c1d96d5676034e4 ./lib/attacks/nmap_scan/nmap_opts.py
|
||||||
c01ef6dc27a2d3ff99e282ccc89d7d45 ./lib/header_check/__init__.py
|
0114ebe3d45612ef143f2777f027374c ./lib/header_check/__init__.py
|
||||||
cd8e35cfd995d0a93892cfc83f01dea7 ./lib/core/common.py
|
2a8acb2191d80da75f0e4d09c00df9f6 ./lib/core/common.py
|
||||||
4433353fb5c55578391d8b4006191ee8 ./lib/core/errors.py
|
|
||||||
38d8ce4aec42ec147b44a36c69b15ea8 ./lib/core/parse.py
|
|
||||||
d41d8cd98f00b204e9800998ecf8427e ./lib/core/__init__.py
|
|
||||||
0112338e057d62d4580c86033c18df05 ./lib/core/settings.py
|
|
||||||
de4254c5e40f7aa4fb81e0608f758a2c ./lib/core/decorators.py
|
de4254c5e40f7aa4fb81e0608f758a2c ./lib/core/decorators.py
|
||||||
9a02e5b913d210350545ac26510a63c9 ./var/search/__init__.py
|
3f045c64ef155a517b7a3f3b66905325 ./lib/core/errors.py
|
||||||
83928f6c090722d87a905a447cb51aed ./var/search/selenium_search.py
|
d41d8cd98f00b204e9800998ecf8427e ./lib/core/__init__.py
|
||||||
cfcce04aac694eee7a6c73969861ce43 ./var/search/pgp_search.py
|
0faeed8eac30526f3751dd67fe5c9f7e ./lib/core/settings.py
|
||||||
|
27bce5d5d1e7d01788c5273016b19370 ./lib/core/parse.py
|
||||||
d41d8cd98f00b204e9800998ecf8427e ./var/__init__.py
|
d41d8cd98f00b204e9800998ecf8427e ./var/__init__.py
|
||||||
d41d8cd98f00b204e9800998ecf8427e ./var/auto_issue/__init__.py
|
d41d8cd98f00b204e9800998ecf8427e ./var/auto_issue/__init__.py
|
||||||
0c11c16126baf789388a661bbbefb149 ./var/auto_issue/github.py
|
c58e73857e42a07fa6eb559433b32c1a ./var/auto_issue/github.py
|
||||||
222102e56b3f4b9facda7ed28690d3f7 ./var/blackwidow/__init__.py
|
503e44b36f0bcd81e20840be5b73320e ./var/search/__init__.py
|
||||||
|
c52867e57beeeeac2da57f597b644faf ./var/search/selenium_search.py
|
||||||
|
12340de27a75273cd444f7257d354311 ./var/search/pgp_search.py
|
||||||
|
0af5ab455a535a2f141cfae4758a4bb4 ./var/blackwidow/__init__.py
|
||||||
4
etc/scripts/install_xvfb.sh
Normal file
4
etc/scripts/install_xvfb.sh
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
|
||||||
|
sudo apt-get install xvfb --yes > /dev/null 2>&1
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
for pid in $(ps -ef | grep "firefox" | awk '{print $2}'); do kill -9 ${pid}; done > /dev/null 2>&1
|
for pid in $(ps -ef | grep "firefox" | awk '{print $2}'); do kill -9 ${pid}; done > /dev/null 2>&1
|
||||||
mv ~/.mozilla ~/.mozilla.old > /dev/null 2>&1
|
mv ~/.mozilla ~/.mozilla.old > /dev/null 2>&1
|
||||||
|
rm /usr/lib/firefox* > /dev/null 2>&1
|
||||||
sudo apt-get update > /dev/null 2>&1
|
sudo apt-get update > /dev/null 2>&1
|
||||||
sudo apt-get --purge --reinstall --assume-yes install firefox=56.0 > /dev/null 2>&1
|
sudo apt-get --purge --reinstall --assume-yes install firefox=56.0 > /dev/null 2>&1
|
||||||
sudo pip2 install selenium -U
|
sudo pip2 install selenium -U > /dev/null 2>&1
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -35,7 +35,7 @@ def check_for_externals(url, data_sep="-" * 30, **kwargs):
|
||||||
currently_searching = ext[robots if robots else sitemap]
|
currently_searching = ext[robots if robots else sitemap]
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
||||||
"currently searching for a '{}'...".format(currently_searching), level=10
|
"currently searching for a '{}'".format(currently_searching), level=10
|
||||||
))
|
))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -44,13 +44,13 @@ def check_for_externals(url, data_sep="-" * 30, **kwargs):
|
||||||
_, code, data, _ = lib.core.common.get_page(full_url)
|
_, code, data, _ = lib.core.common.get_page(full_url)
|
||||||
except (TooManyRedirects, ConnectionError, ReadTimeout):
|
except (TooManyRedirects, ConnectionError, ReadTimeout):
|
||||||
lib.core.settings.logger.error(lib.core.settings.set_color(
|
lib.core.settings.logger.error(lib.core.settings.set_color(
|
||||||
"connection to '{}' failed, assuming does not exist and continuing...".format(full_url), level=40
|
"connection to '{}' failed, assuming does not exist and continuing".format(full_url), level=40
|
||||||
))
|
))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if code == 404:
|
if code == 404:
|
||||||
lib.core.settings.logger.error(lib.core.settings.set_color(
|
lib.core.settings.logger.error(lib.core.settings.set_color(
|
||||||
"unable to connect to '{}', assuming does not exist and continuing...".format(
|
"unable to connect to '{}', assuming does not exist and continuing".format(
|
||||||
full_url
|
full_url
|
||||||
), level=40
|
), level=40
|
||||||
))
|
))
|
||||||
|
|
@ -80,7 +80,7 @@ def check_for_externals(url, data_sep="-" * 30, **kwargs):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"robots.txt page will be saved into a file...", level=25
|
"robots.txt page will be saved into a file", level=25
|
||||||
))
|
))
|
||||||
return lib.core.common.write_to_log_file(
|
return lib.core.common.write_to_log_file(
|
||||||
data, lib.core.settings.ROBOTS_PAGE_PATH, lib.core.settings.ROBOTS_TXT_FILENAME.format(
|
data, lib.core.settings.ROBOTS_PAGE_PATH, lib.core.settings.ROBOTS_TXT_FILENAME.format(
|
||||||
|
|
@ -89,7 +89,7 @@ def check_for_externals(url, data_sep="-" * 30, **kwargs):
|
||||||
)
|
)
|
||||||
elif sitemap:
|
elif sitemap:
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"found a sitemap, saving to file...", level=25
|
"found a sitemap, saving to file", level=25
|
||||||
))
|
))
|
||||||
return lib.core.common.write_to_log_file(
|
return lib.core.common.write_to_log_file(
|
||||||
data, lib.core.settings.SITEMAP_FILE_LOG_PATH, lib.core.settings.SITEMAP_FILENAME.format(
|
data, lib.core.settings.SITEMAP_FILE_LOG_PATH, lib.core.settings.SITEMAP_FILENAME.format(
|
||||||
|
|
@ -114,12 +114,12 @@ def check_for_admin_page(url, exts, protocol="http://", **kwargs):
|
||||||
true_url = "{}{}{}".format(protocol, stripped_url, ext)
|
true_url = "{}{}{}".format(protocol, stripped_url, ext)
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
||||||
"trying '{}'...".format(true_url), level=10
|
"trying '{}'".format(true_url), level=10
|
||||||
))
|
))
|
||||||
try:
|
try:
|
||||||
urlopen(true_url, timeout=5)
|
urlopen(true_url, timeout=5)
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"connected successfully to '{}'...".format(true_url), level=25
|
"connected successfully to '{}'".format(true_url), level=25
|
||||||
))
|
))
|
||||||
connections.add(true_url)
|
connections.add(true_url)
|
||||||
except HTTPError as e:
|
except HTTPError as e:
|
||||||
|
|
@ -127,7 +127,7 @@ def check_for_admin_page(url, exts, protocol="http://", **kwargs):
|
||||||
if verbose:
|
if verbose:
|
||||||
if "Access Denied" in str(e):
|
if "Access Denied" in str(e):
|
||||||
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
||||||
"got access denied, possible control panel found without external access on '{}'...".format(
|
"got access denied, possible control panel found without external access on '{}'".format(
|
||||||
true_url
|
true_url
|
||||||
),
|
),
|
||||||
level=30
|
level=30
|
||||||
|
|
@ -137,7 +137,7 @@ def check_for_admin_page(url, exts, protocol="http://", **kwargs):
|
||||||
for error_code in lib.core.common.STATUS_CODES.iterkeys():
|
for error_code in lib.core.common.STATUS_CODES.iterkeys():
|
||||||
if int(data[2].split(":")[0]) == error_code:
|
if int(data[2].split(":")[0]) == error_code:
|
||||||
lib.core.settings.logger.error(lib.core.settings.set_color(
|
lib.core.settings.logger.error(lib.core.settings.set_color(
|
||||||
"failed to connect got error code {} (reason: {})...".format(
|
"failed to connect got error code {} (reason: {})".format(
|
||||||
data[2], lib.core.common.STATUS_CODES[error_code]
|
data[2], lib.core.common.STATUS_CODES[error_code]
|
||||||
), level=40
|
), level=40
|
||||||
))
|
))
|
||||||
|
|
@ -145,33 +145,33 @@ def check_for_admin_page(url, exts, protocol="http://", **kwargs):
|
||||||
if verbose:
|
if verbose:
|
||||||
if "<urlopen error timed out>" or "timeout: timed out" in str(e):
|
if "<urlopen error timed out>" or "timeout: timed out" in str(e):
|
||||||
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
||||||
"connection timed out assuming won't connect and skipping...", level=30
|
"connection timed out assuming won't connect and skipping", level=30
|
||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
lib.core.settings.logger.exception(lib.core.settings.set_color(
|
lib.core.settings.logger.exception(lib.core.settings.set_color(
|
||||||
"failed to connect with unexpected error '{}'...".format(str(e)), level=50
|
"failed to connect with unexpected error '{}'".format(str(e)), level=50
|
||||||
))
|
))
|
||||||
request_issue_creation()
|
request_issue_creation()
|
||||||
possible_connections, connections = list(possible_connections), list(connections)
|
possible_connections, connections = list(possible_connections), list(connections)
|
||||||
data_msg = "found {} possible connections(s) and {} successful connection(s)..."
|
data_msg = "found {} possible connections(s) and {} successful connection(s)"
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
data_msg.format(len(possible_connections), len(connections))
|
data_msg.format(len(possible_connections), len(connections))
|
||||||
))
|
))
|
||||||
if len(connections) > 0:
|
if len(connections) > 0:
|
||||||
# create the connection tree if we got some connections
|
# create the connection tree if we got some connections
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"creating connection tree..."
|
"creating connection tree"
|
||||||
))
|
))
|
||||||
lib.core.settings.create_tree(url, connections)
|
lib.core.settings.create_tree(url, connections)
|
||||||
else:
|
else:
|
||||||
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
||||||
"did not receive any successful connections to the admin page of "
|
"did not receive any successful connections to the admin page of "
|
||||||
"{}...".format(url), level=50
|
"{}".format(url), level=50
|
||||||
))
|
))
|
||||||
if show_possibles:
|
if show_possibles:
|
||||||
if len(possible_connections) > 0:
|
if len(possible_connections) > 0:
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"creating possible connection tree..."
|
"creating possible connection tree"
|
||||||
))
|
))
|
||||||
lib.core.settings.create_tree(url, possible_connections)
|
lib.core.settings.create_tree(url, possible_connections)
|
||||||
else:
|
else:
|
||||||
|
|
@ -181,7 +181,7 @@ def check_for_admin_page(url, exts, protocol="http://", **kwargs):
|
||||||
))
|
))
|
||||||
if len(connections) > 0:
|
if len(connections) > 0:
|
||||||
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
||||||
"only writing successful connections to log file...", level=30
|
"only writing successful connections to log file", level=30
|
||||||
))
|
))
|
||||||
lib.core.common.write_to_log_file(
|
lib.core.common.write_to_log_file(
|
||||||
list(connections),
|
list(connections),
|
||||||
|
|
@ -211,32 +211,32 @@ def main(url, show=False, verbose=False, **kwargs):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"parsing robots.txt..."
|
"parsing robots.txt"
|
||||||
))
|
))
|
||||||
results = check_for_externals(url, robots=True, batch=batch)
|
results = check_for_externals(url, robots=True, batch=batch)
|
||||||
if not results:
|
if not results:
|
||||||
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
||||||
"seems like this page is either blocking access to robots.txt or it does not exist...", level=30
|
"seems like this page is either blocking access to robots.txt or it does not exist", level=30
|
||||||
))
|
))
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"checking for a sitemap..."
|
"checking for a sitemap"
|
||||||
))
|
))
|
||||||
check_for_externals(url, sitemap=True)
|
check_for_externals(url, sitemap=True)
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"loading extensions..."
|
"loading extensions"
|
||||||
))
|
))
|
||||||
extensions = __load_extensions()
|
extensions = __load_extensions()
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
||||||
"loaded a total of {} extensions...".format(len(extensions)), level=10
|
"loaded a total of {} extensions".format(len(extensions)), level=10
|
||||||
))
|
))
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"attempting to bruteforce admin panel..."
|
"attempting to bruteforce admin panel"
|
||||||
))
|
))
|
||||||
if do_threading:
|
if do_threading:
|
||||||
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
||||||
"starting {} threads, you will not be able to end the process until "
|
"starting {} threads, you will not be able to end the process until "
|
||||||
"it is completed...".format(proc_num), level=30
|
"it is completed".format(proc_num), level=30
|
||||||
))
|
))
|
||||||
tasks = []
|
tasks = []
|
||||||
for _ in range(0, proc_num):
|
for _ in range(0, proc_num):
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ def clickjacking_main(url, **kwargs):
|
||||||
)
|
)
|
||||||
if question.lower().startswith("n"):
|
if question.lower().startswith("n"):
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"automatically removing all queries from URL..."
|
"automatically removing all queries from URL"
|
||||||
))
|
))
|
||||||
url = "http://{}".format(lib.core.settings.replace_http(url, complete=True))
|
url = "http://{}".format(lib.core.settings.replace_http(url, complete=True))
|
||||||
|
|
||||||
|
|
@ -73,14 +73,14 @@ def clickjacking_main(url, **kwargs):
|
||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
||||||
"generating HTML...", level=10
|
"generating HTML", level=10
|
||||||
))
|
))
|
||||||
|
|
||||||
data = scanner.generate_html()
|
data = scanner.generate_html()
|
||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
||||||
"HTML generated successfully...", level=10
|
"HTML generated successfully", level=10
|
||||||
))
|
))
|
||||||
print("{}\n{}\n{}".format("-" * 30, data, "-" * 30))
|
print("{}\n{}\n{}".format("-" * 30, data, "-" * 30))
|
||||||
|
|
||||||
|
|
@ -90,7 +90,7 @@ def clickjacking_main(url, **kwargs):
|
||||||
if results:
|
if results:
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"it appears that provided URL '{}' is vulnerable to clickjacking, writing "
|
"it appears that provided URL '{}' is vulnerable to clickjacking, writing "
|
||||||
"to HTML file...".format(url), level=25
|
"to HTML file".format(url), level=25
|
||||||
))
|
))
|
||||||
lib.core.common.write_to_log_file(
|
lib.core.common.write_to_log_file(
|
||||||
data,
|
data,
|
||||||
|
|
@ -99,7 +99,7 @@ def clickjacking_main(url, **kwargs):
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
lib.core.settings.logger.error(lib.core.settings.set_color(
|
lib.core.settings.logger.error(lib.core.settings.set_color(
|
||||||
"provided URL '{}' seems to have the correct protection from clickjacking...".format(
|
"provided URL '{}' seems to have the correct protection from clickjacking".format(
|
||||||
url
|
url
|
||||||
), level=40
|
), level=40
|
||||||
))
|
))
|
||||||
|
|
@ -109,6 +109,6 @@ def clickjacking_main(url, **kwargs):
|
||||||
except Exception as e: # until I figure out the errors, we'll just make issues about them
|
except Exception as e: # until I figure out the errors, we'll just make issues about them
|
||||||
lib.core.settings.logger.exception(lib.core.settings.set_color(
|
lib.core.settings.logger.exception(lib.core.settings.set_color(
|
||||||
"Zeus failed to process the clickjacking test and received "
|
"Zeus failed to process the clickjacking test and received "
|
||||||
"error code '{}'...".format(e), level=50
|
"error code '{}'".format(e), level=50
|
||||||
))
|
))
|
||||||
var.auto_issue.github.request_issue_creation()
|
var.auto_issue.github.request_issue_creation()
|
||||||
|
|
|
||||||
|
|
@ -1,158 +0,0 @@
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from bs4 import BeautifulSoup
|
|
||||||
|
|
||||||
import lib.core.common
|
|
||||||
import lib.core.settings
|
|
||||||
|
|
||||||
|
|
||||||
def __create_url(redirect, template="https://gist.github.com{}"):
|
|
||||||
"""
|
|
||||||
create the URL for the Gists
|
|
||||||
"""
|
|
||||||
return template.format(redirect)
|
|
||||||
|
|
||||||
|
|
||||||
def get_raw_html(redirect, verbose=False):
|
|
||||||
"""
|
|
||||||
get the raw HTML of the Gist plus the URL for it
|
|
||||||
"""
|
|
||||||
tag, descriptor = "a", "href"
|
|
||||||
raw_gist_regex = re.compile(r".raw.[a-z0-9]{40}", re.I)
|
|
||||||
_, status, html, _ = lib.core.common.get_page(redirect)
|
|
||||||
|
|
||||||
if status == 200:
|
|
||||||
soup = BeautifulSoup(html, "html.parser")
|
|
||||||
for link in soup.findAll(tag):
|
|
||||||
raw_gist_redirect = link.get(descriptor)
|
|
||||||
if raw_gist_regex.search(str(raw_gist_redirect)) is not None:
|
|
||||||
url = __create_url(raw_gist_redirect)
|
|
||||||
if verbose:
|
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
|
||||||
"found raw Gist URL '{}'...".format(url), level=10
|
|
||||||
))
|
|
||||||
_, _, html, _ = lib.core.common.get_page(url)
|
|
||||||
raw_soup = BeautifulSoup(html, "html.parser")
|
|
||||||
return raw_soup, url
|
|
||||||
else:
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
|
|
||||||
def get_links(page_set, proxy=None, agent=None):
|
|
||||||
"""
|
|
||||||
parse 10 pages of Github gists and use them
|
|
||||||
"""
|
|
||||||
redirects, retval = set(), set()
|
|
||||||
gist_search_url = "https://gist.github.com/discover?page={}"
|
|
||||||
tag, descriptor = "a", "href"
|
|
||||||
gist_regex = re.compile(r"[a-f0-9]{32}", re.I)
|
|
||||||
gist_skip_schema = ("stargazers", "forks", "#comments")
|
|
||||||
|
|
||||||
for i in range(page_set):
|
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
|
||||||
"fetching all Gists on page #{}...".format(i+1)
|
|
||||||
))
|
|
||||||
_, status, html, _ = lib.core.common.get_page(
|
|
||||||
gist_search_url.format(i+1), proxy=proxy, agent=agent
|
|
||||||
)
|
|
||||||
if status == 200:
|
|
||||||
soup = BeautifulSoup(html, "html.parser")
|
|
||||||
for link in soup.findAll(tag):
|
|
||||||
redirect = link.get(descriptor)
|
|
||||||
if not any(s in redirect for s in gist_skip_schema):
|
|
||||||
if gist_regex.search(redirect) is not None:
|
|
||||||
if not any(protocol in redirect for protocol in ["https://", "http://"]):
|
|
||||||
redirects.add(__create_url(redirect))
|
|
||||||
else:
|
|
||||||
redirects.add(redirect)
|
|
||||||
else:
|
|
||||||
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
|
||||||
"page #{} failed to load with status code {} (reason '{}')...".format(
|
|
||||||
i+1, status, lib.core.common.STATUS_CODES[int(status)]
|
|
||||||
), level=30
|
|
||||||
))
|
|
||||||
continue
|
|
||||||
return redirects
|
|
||||||
|
|
||||||
|
|
||||||
def check_files_for_information(data_to_search, query):
|
|
||||||
"""
|
|
||||||
check the files to see if they contain any of the information that was specified
|
|
||||||
"""
|
|
||||||
# create multiple regex types to ensure that we cover all our
|
|
||||||
# bases while we do the searching.
|
|
||||||
# this will make it so that if there is a match anywhere
|
|
||||||
# in anything, we'll find it.
|
|
||||||
data_to_search = str(data_to_search)
|
|
||||||
data_regex_schema = (
|
|
||||||
# match a URL with or without www
|
|
||||||
re.compile(r"(http(s)?)?(.//)?(www.)?{}".format(query), re.I),
|
|
||||||
# match our string and any random character around it (I like to call it the tittyex)
|
|
||||||
re.compile(r"(.)?{}(.)?".format(query), re.I),
|
|
||||||
# single boundary match, checks if it's inside of something else
|
|
||||||
re.compile(r"\b{}".format(query), re.I),
|
|
||||||
# double boundary, same as above but with another boundary
|
|
||||||
re.compile(r"\b{}\b".format(query), re.I),
|
|
||||||
# wildcard match
|
|
||||||
re.compile(r"{}*".format(query), re.I),
|
|
||||||
# normal match
|
|
||||||
re.compile(r"{}".format(query), re.I)
|
|
||||||
)
|
|
||||||
for regex in list(data_regex_schema):
|
|
||||||
if regex.search(data_to_search) is not None:
|
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
|
||||||
"found match with given specifics ('{}'), saving Gist to file...".format(
|
|
||||||
regex.pattern
|
|
||||||
), level=25
|
|
||||||
))
|
|
||||||
lib.core.common.write_to_log_file(
|
|
||||||
data_to_search,
|
|
||||||
lib.core.settings.GIST_MATCH_LOG,
|
|
||||||
lib.core.settings.GIST_FILENAME.format(query)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# @lib.core.decorators.tail_call_optimized
|
|
||||||
def github_gist_search_main(query, **kwargs):
|
|
||||||
"""
|
|
||||||
main function for searching Gists
|
|
||||||
"""
|
|
||||||
proxy = kwargs.get("proxy", None)
|
|
||||||
agent = kwargs.get("agent", None)
|
|
||||||
verbose = kwargs.get("verbose", False)
|
|
||||||
page_set = kwargs.get("page_set", 10)
|
|
||||||
|
|
||||||
# there seems to be a recursion issue in this function,
|
|
||||||
# so until I get this figured out, we're going to change
|
|
||||||
# the maximum recursion of the system when we get here
|
|
||||||
sys.setrecursionlimit(1500)
|
|
||||||
|
|
||||||
try:
|
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
|
||||||
"searching a total of {} pages of Gists for '{}'...".format(
|
|
||||||
page_set, query
|
|
||||||
)
|
|
||||||
))
|
|
||||||
|
|
||||||
if "www." in query:
|
|
||||||
query = query.split(".")[1]
|
|
||||||
|
|
||||||
links = get_links(page_set, proxy=proxy, agent=agent)
|
|
||||||
if verbose:
|
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
|
||||||
"found a total of {} links to search...".format(
|
|
||||||
len(links)
|
|
||||||
), level=15
|
|
||||||
))
|
|
||||||
for link in list(links):
|
|
||||||
if link is not None:
|
|
||||||
gist, gist_link = get_raw_html(link, verbose=verbose)
|
|
||||||
check_files_for_information(gist, query)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
if not lib.core.common.pause():
|
|
||||||
lib.core.common.shutdown()
|
|
||||||
except Exception as e:
|
|
||||||
lib.core.settings.logger.exception(lib.core.settings.set_color(
|
|
||||||
"Gist search has failed with error '{}'...".format(str(e)), level=50
|
|
||||||
))
|
|
||||||
|
|
@ -41,7 +41,7 @@ class NmapHook(object):
|
||||||
"""
|
"""
|
||||||
send all the information to a JSON file for further use
|
send all the information to a JSON file for further use
|
||||||
"""
|
"""
|
||||||
lib.core.common.write_to_log_file(
|
return lib.core.common.write_to_log_file(
|
||||||
data, lib.core.settings.NMAP_LOG_FILE_PATH,
|
data, lib.core.settings.NMAP_LOG_FILE_PATH,
|
||||||
lib.core.settings.NMAP_FILENAME.format(self.ip)
|
lib.core.settings.NMAP_FILENAME.format(self.ip)
|
||||||
)
|
)
|
||||||
|
|
@ -52,13 +52,14 @@ class NmapHook(object):
|
||||||
"""
|
"""
|
||||||
# have to create a spacer or the output comes out funky..
|
# have to create a spacer or the output comes out funky..
|
||||||
spacer_data = {4: " " * 8, 6: " " * 6, 8: " " * 4}
|
spacer_data = {4: " " * 8, 6: " " * 6, 8: " " * 4}
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color("finding data for IP '{}'...".format(self.ip)))
|
lib.core.settings.logger.info(lib.core.settings.set_color("finding data for IP '{}'".format(self.ip)))
|
||||||
json_data = json.loads(json_data)["scan"]
|
json_data = json.loads(json_data)["scan"]
|
||||||
host = json_data[self.ip]["hostnames"][0]["name"]
|
host = json_data[self.ip]["hostnames"][0]["name"]
|
||||||
|
host_skip = (not len(host) == 0, " ", "", None)
|
||||||
print(
|
print(
|
||||||
"{}\nScanned: {} ({})\tStatus: {}\nProtocol: {}\n".format(
|
"{}\nScanned: {} ({})\tStatus: {}\nProtocol: {}\n".format(
|
||||||
sep, self.ip,
|
sep, self.ip,
|
||||||
host if host is not "" or None or not len(host) == 0 else "unknown",
|
host if host != any(s for s in list(host_skip)) else "unknown",
|
||||||
json_data[self.ip]["status"]["state"],
|
json_data[self.ip]["status"]["state"],
|
||||||
"TCP"
|
"TCP"
|
||||||
)
|
)
|
||||||
|
|
@ -98,35 +99,35 @@ def perform_port_scan(url, scanner=NmapHook, **kwargs):
|
||||||
|
|
||||||
with lib.core.decorators.TimeOut(seconds=timeout_time):
|
with lib.core.decorators.TimeOut(seconds=timeout_time):
|
||||||
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
||||||
"if the port scan is not completed in {}(m) it will timeout...".format(
|
"if the port scan is not completed in {}(m) it will timeout".format(
|
||||||
lib.core.settings.convert_to_minutes(timeout_time)
|
lib.core.settings.convert_to_minutes(timeout_time)
|
||||||
), level=30
|
), level=30
|
||||||
))
|
))
|
||||||
url = url.strip()
|
url = url.strip()
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"attempting to find IP address for hostname '{}'...".format(url)
|
"attempting to find IP address for hostname '{}'".format(url)
|
||||||
))
|
))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
found_ip_address = socket.gethostbyname(url)
|
found_ip_address = socket.gethostbyname(url)
|
||||||
except socket.gaierror:
|
except socket.gaierror:
|
||||||
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
||||||
"failed to gather IP address for URL '{}'...".format(url)
|
"failed to gather IP address for URL '{}'".format(url)
|
||||||
))
|
))
|
||||||
return
|
return
|
||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
||||||
"checking for nmap on your system...", level=10
|
"checking for nmap on your system", level=10
|
||||||
))
|
))
|
||||||
nmap_exists = "".join(find_nmap())
|
nmap_exists = "".join(find_nmap())
|
||||||
if nmap_exists:
|
if nmap_exists:
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
||||||
"nmap has been found under '{}'...".format(nmap_exists), level=10
|
"nmap has been found under '{}'".format(nmap_exists), level=10
|
||||||
))
|
))
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"starting port scan on IP address '{}'...".format(found_ip_address)
|
"starting port scan on IP address '{}'".format(found_ip_address)
|
||||||
))
|
))
|
||||||
try:
|
try:
|
||||||
data = scanner(found_ip_address, opts=opts)
|
data = scanner(found_ip_address, opts=opts)
|
||||||
|
|
@ -134,11 +135,11 @@ def perform_port_scan(url, scanner=NmapHook, **kwargs):
|
||||||
data.show_open_ports(json_data)
|
data.show_open_ports(json_data)
|
||||||
file_path = data.send_to_file(json_data)
|
file_path = data.send_to_file(json_data)
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"port scan completed, all data saved to JSON file under '{}'...".format(file_path)
|
"port scan completed, all data saved to JSON file under '{}'".format(file_path)
|
||||||
))
|
))
|
||||||
except KeyError:
|
except KeyError:
|
||||||
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
||||||
"no port information found for '{}({})'...".format(
|
"no port information found for '{}({})'".format(
|
||||||
url, found_ip_address
|
url, found_ip_address
|
||||||
), level=50
|
), level=50
|
||||||
))
|
))
|
||||||
|
|
@ -149,20 +150,20 @@ def perform_port_scan(url, scanner=NmapHook, **kwargs):
|
||||||
lib.core.settings.logger.error(lib.core.settings.set_color(
|
lib.core.settings.logger.error(lib.core.settings.set_color(
|
||||||
"port scan is taking to long and has hit the timeout, you "
|
"port scan is taking to long and has hit the timeout, you "
|
||||||
"can increase this time by passing the --time-sec flag (IE "
|
"can increase this time by passing the --time-sec flag (IE "
|
||||||
"--time-sec 300)...", level=40
|
"--time-sec 300)", level=40
|
||||||
))
|
))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
lib.core.settings.logger.exception(lib.core.settings.set_color(
|
lib.core.settings.logger.exception(lib.core.settings.set_color(
|
||||||
"ran into exception '{}', cannot continue quitting...".format(e), level=50
|
"ran into exception '{}', cannot continue quitting".format(e), level=50
|
||||||
))
|
))
|
||||||
request_issue_creation()
|
request_issue_creation()
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
||||||
"nmap was not found on your system...", level=50
|
"nmap was not found on your system", level=50
|
||||||
))
|
))
|
||||||
lib.core.common.run_fix(
|
lib.core.common.run_fix(
|
||||||
"would you like to automatically install it",
|
"would you like to automatically install it",
|
||||||
"sudo sh {}".format(lib.core.settings.NMAP_INSTALLER_TOOL),
|
"sudo sh {}".format(lib.core.settings.NMAP_INSTALLER_TOOL),
|
||||||
"nmap is not installed, please install it in order to continue..."
|
"nmap is not installed, please install it in order to continue"
|
||||||
)
|
)
|
||||||
|
|
@ -111,7 +111,7 @@ class SqlmapHook(object):
|
||||||
if current_status != "running":
|
if current_status != "running":
|
||||||
raise lib.core.errors.SqlmapFailedStart(
|
raise lib.core.errors.SqlmapFailedStart(
|
||||||
"sqlmap API failed to start the run, check the client and see what "
|
"sqlmap API failed to start the run, check the client and see what "
|
||||||
"the problem is and try again..."
|
"the problem is and try again"
|
||||||
)
|
)
|
||||||
already_displayed = set()
|
already_displayed = set()
|
||||||
while current_status == "running":
|
while current_status == "running":
|
||||||
|
|
@ -156,7 +156,7 @@ def sqlmap_scan_main(url, port=None, verbose=None, opts=None, auto_start=False):
|
||||||
|
|
||||||
if auto_start:
|
if auto_start:
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"attempting to launch sqlmap API..."
|
"attempting to launch sqlmap API"
|
||||||
))
|
))
|
||||||
sqlmap_api_command = shlex.split("sudo sh {} p {}".format(
|
sqlmap_api_command = shlex.split("sudo sh {} p {}".format(
|
||||||
lib.core.settings.LAUNCH_SQLMAP_API_TOOL, "".join(found_path)
|
lib.core.settings.LAUNCH_SQLMAP_API_TOOL, "".join(found_path)
|
||||||
|
|
@ -164,58 +164,58 @@ def sqlmap_scan_main(url, port=None, verbose=None, opts=None, auto_start=False):
|
||||||
subprocess.Popen(sqlmap_api_command, stdout=subprocess.PIPE)
|
subprocess.Popen(sqlmap_api_command, stdout=subprocess.PIPE)
|
||||||
if is_started:
|
if is_started:
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"sqlmap API is up and running, continuing process..."
|
"sqlmap API is up and running, continuing process"
|
||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
lib.core.settings.logger.error(lib.core.settings.set_color(
|
lib.core.settings.logger.error(lib.core.settings.set_color(
|
||||||
"there was a problem starting sqlmap API...", level=40
|
"there was a problem starting sqlmap API", level=40
|
||||||
))
|
))
|
||||||
lib.core.common.prompt(
|
lib.core.common.prompt(
|
||||||
"manually start the API and press enter when ready..."
|
"manually start the API and press enter when ready"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if not is_started:
|
if not is_started:
|
||||||
lib.core.common.prompt(
|
lib.core.common.prompt(
|
||||||
"sqlmap API is not started, start it and press enter to continue..."
|
"sqlmap API is not started, start it and press enter to continue"
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
sqlmap_scan = SqlmapHook(url, port=port)
|
sqlmap_scan = SqlmapHook(url, port=port)
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"initializing new sqlmap scan with given URL '{}'...".format(url)
|
"initializing new sqlmap scan with given URL '{}'".format(url)
|
||||||
))
|
))
|
||||||
sqlmap_scan.init_new_scan()
|
sqlmap_scan.init_new_scan()
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
||||||
"scan initialized...", level=10
|
"scan initialized", level=10
|
||||||
))
|
))
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"gathering sqlmap API scan ID..."
|
"gathering sqlmap API scan ID"
|
||||||
))
|
))
|
||||||
api_id = sqlmap_scan.get_scan_id()
|
api_id = sqlmap_scan.get_scan_id()
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
||||||
"current sqlmap scan ID: '{}'...".format(api_id), level=10
|
"current sqlmap scan ID: '{}'".format(api_id), level=10
|
||||||
))
|
))
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"starting sqlmap scan on url: '{}'...".format(url), level=25
|
"starting sqlmap scan on url: '{}'".format(url), level=25
|
||||||
))
|
))
|
||||||
if opts:
|
if opts:
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
||||||
"using arguments: '{}'...".format(opts), level=10
|
"using arguments: '{}'".format(opts), level=10
|
||||||
))
|
))
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"adding arguments to sqlmap API..."
|
"adding arguments to sqlmap API"
|
||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
||||||
"no arguments passed, skipping...", level=10
|
"no arguments passed, skipping", level=10
|
||||||
))
|
))
|
||||||
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
||||||
"please keep in mind that this is the API, output will "
|
"please keep in mind that this is the API, output will "
|
||||||
"not be saved to log file, it may take a little longer "
|
"not be saved to log file, it may take a little longer "
|
||||||
"to finish processing, launching sqlmap...", level=30
|
"to finish processing, launching sqlmap", level=30
|
||||||
))
|
))
|
||||||
sqlmap_scan.start_scan(api_id, opts=opts)
|
sqlmap_scan.start_scan(api_id, opts=opts)
|
||||||
print("-" * 30)
|
print("-" * 30)
|
||||||
|
|
@ -224,7 +224,7 @@ def sqlmap_scan_main(url, port=None, verbose=None, opts=None, auto_start=False):
|
||||||
except requests.exceptions.HTTPError as e:
|
except requests.exceptions.HTTPError as e:
|
||||||
lib.core.settings.logger.exception(lib.core.settings.set_color(
|
lib.core.settings.logger.exception(lib.core.settings.set_color(
|
||||||
"ran into error '{}', seems you didn't start the server, check "
|
"ran into error '{}', seems you didn't start the server, check "
|
||||||
"the server port and try again...".format(e), level=50
|
"the server port and try again".format(e), level=50
|
||||||
))
|
))
|
||||||
pass
|
pass
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
|
@ -236,7 +236,7 @@ def sqlmap_scan_main(url, port=None, verbose=None, opts=None, auto_start=False):
|
||||||
"sqlmap API is not started, did you forget to start it? "
|
"sqlmap API is not started, did you forget to start it? "
|
||||||
"You will need to open a new terminal, cd into sqlmap, and "
|
"You will need to open a new terminal, cd into sqlmap, and "
|
||||||
"run `python sqlmapapi.py -s` otherwise pass the correct flags "
|
"run `python sqlmapapi.py -s` otherwise pass the correct flags "
|
||||||
"to auto start the API...", level=40
|
"to auto start the API", level=40
|
||||||
))
|
))
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ def whois_lookup_main(domain, **kwargs):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"performing WhoIs lookup on given domain '{}'...".format(domain)
|
"performing WhoIs lookup on given domain '{}'".format(domain)
|
||||||
))
|
))
|
||||||
if timeout is not None:
|
if timeout is not None:
|
||||||
time.sleep(timeout)
|
time.sleep(timeout)
|
||||||
|
|
@ -82,14 +82,14 @@ def whois_lookup_main(domain, **kwargs):
|
||||||
raw_information = gather_raw_whois_info(domain)
|
raw_information = gather_raw_whois_info(domain)
|
||||||
except Exception:
|
except Exception:
|
||||||
lib.core.settings.logger.error(lib.core.settings.set_color(
|
lib.core.settings.logger.error(lib.core.settings.set_color(
|
||||||
"unable to produce information from WhoIs lookup...", level=40
|
"unable to produce information from WhoIs lookup", level=40
|
||||||
))
|
))
|
||||||
return None
|
return None
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"discovered raw information...", level=25
|
"discovered raw information", level=25
|
||||||
))
|
))
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"gathering interesting information..."
|
"gathering interesting information"
|
||||||
))
|
))
|
||||||
interesting_data = get_interesting(raw_information)
|
interesting_data = get_interesting(raw_information)
|
||||||
if verbose:
|
if verbose:
|
||||||
|
|
@ -97,7 +97,7 @@ def whois_lookup_main(domain, **kwargs):
|
||||||
human_readable_display(domain, interesting_data)
|
human_readable_display(domain, interesting_data)
|
||||||
except (ValueError, Exception):
|
except (ValueError, Exception):
|
||||||
lib.core.settings.logger.error(lib.core.settings.set_color(
|
lib.core.settings.logger.error(lib.core.settings.set_color(
|
||||||
"unable to display any information from WhoIs lookup on domain '{}'...".format(domain), level=50
|
"unable to display any information from WhoIs lookup on domain '{}'".format(domain), level=50
|
||||||
))
|
))
|
||||||
return None
|
return None
|
||||||
lib.core.common.write_to_log_file(
|
lib.core.common.write_to_log_file(
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,19 @@ def list_tamper_scripts(path="{}/lib/tamper_scripts"):
|
||||||
return retval
|
return retval
|
||||||
|
|
||||||
|
|
||||||
|
def assign_protocol(url, force=False):
|
||||||
|
auto_assign = ("http://{}", "https://{}")
|
||||||
|
url_verification = re.compile(r"http(s)?", re.I)
|
||||||
|
|
||||||
|
if url_verification.search(url) is None:
|
||||||
|
if not force:
|
||||||
|
return auto_assign[0].format(url)
|
||||||
|
else:
|
||||||
|
return auto_assign[1].format(url)
|
||||||
|
else:
|
||||||
|
return url
|
||||||
|
|
||||||
|
|
||||||
def __tamper_payload(payload, tamper_type, warning=True, **kwargs):
|
def __tamper_payload(payload, tamper_type, warning=True, **kwargs):
|
||||||
"""
|
"""
|
||||||
add the tamper to the payload from the given tamper type
|
add the tamper to the payload from the given tamper type
|
||||||
|
|
@ -40,7 +53,7 @@ def __tamper_payload(payload, tamper_type, warning=True, **kwargs):
|
||||||
if warning:
|
if warning:
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
||||||
"tampering payload with '{}'...".format(tamper), level=10
|
"tampering payload with '{}'".format(tamper), level=10
|
||||||
))
|
))
|
||||||
if tamper in acceptable:
|
if tamper in acceptable:
|
||||||
tamper_name = "lib.tamper_scripts.{}_encode"
|
tamper_name = "lib.tamper_scripts.{}_encode"
|
||||||
|
|
@ -58,7 +71,7 @@ def __load_payloads(filename="{}/etc/text_files/xss_payloads.txt"):
|
||||||
with open(filename.format(os.getcwd())) as payloads: return payloads.readlines()
|
with open(filename.format(os.getcwd())) as payloads: return payloads.readlines()
|
||||||
|
|
||||||
|
|
||||||
def create_urls(url, payload_list, tamper=None, verbose=False):
|
def create_urls(url, payload_list, tamper=None, verbose=False, force=False):
|
||||||
"""
|
"""
|
||||||
create the tampered URL's, write them to a temporary file and read them from there
|
create the tampered URL's, write them to a temporary file and read them from there
|
||||||
"""
|
"""
|
||||||
|
|
@ -73,13 +86,12 @@ def create_urls(url, payload_list, tamper=None, verbose=False):
|
||||||
else:
|
else:
|
||||||
payload = __tamper_payload(payload, tamper_type=tamper, warning=False, verbose=verbose)
|
payload = __tamper_payload(payload, tamper_type=tamper, warning=False, verbose=verbose)
|
||||||
except InvalidTamperProvided:
|
except InvalidTamperProvided:
|
||||||
lib.core.settings.logger.error(lib.core.settings.set_color(
|
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
||||||
"you provided and invalid tamper script, acceptable tamper scripts are: {}...".format(
|
"you provided and invalid tamper script, acceptable tamper scripts are: {}".format(
|
||||||
" | ".join(list_tamper_scripts()), level=40
|
" | ".join(list_tamper_scripts()), level=40
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
lib.core.common.shutdown()
|
loaded_url = "{}{}\n".format(assign_protocol(url.strip(), force=force), payload.strip())
|
||||||
loaded_url = "{}{}\n".format(url.strip(), payload.strip())
|
|
||||||
tmp.write(loaded_url)
|
tmp.write(loaded_url)
|
||||||
return tf_name
|
return tf_name
|
||||||
|
|
||||||
|
|
@ -97,7 +109,7 @@ def find_xss_script(url, **kwargs):
|
||||||
else:
|
else:
|
||||||
retval = data[payload_parser["query"]]
|
retval = data[payload_parser["query"]]
|
||||||
|
|
||||||
# just double checking...
|
# just double checking
|
||||||
if retval == "" or None:
|
if retval == "" or None:
|
||||||
retval = data[payload_parser["path"]]
|
retval = data[payload_parser["path"]]
|
||||||
return retval
|
return retval
|
||||||
|
|
@ -110,17 +122,6 @@ def scan_xss(url, agent=None, proxy=None):
|
||||||
be tampered or encoded if the site is not vulnerable
|
be tampered or encoded if the site is not vulnerable
|
||||||
"""
|
"""
|
||||||
|
|
||||||
retry_flags = 3
|
|
||||||
auto_assign = "http://{}"
|
|
||||||
url_verification = re.compile(r"http(s)?", re.I)
|
|
||||||
|
|
||||||
if url_verification.search(url) is None:
|
|
||||||
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
|
||||||
"protocol missing from URL, automatically assigning protocol...", level=30
|
|
||||||
))
|
|
||||||
url = auto_assign.format(url)
|
|
||||||
|
|
||||||
while retry_flags > 0:
|
|
||||||
try:
|
try:
|
||||||
_, status, html_data, _ = lib.core.common.get_page(url, agent=agent, proxy=proxy)
|
_, status, html_data, _ = lib.core.common.get_page(url, agent=agent, proxy=proxy)
|
||||||
query = find_xss_script(url)
|
query = find_xss_script(url)
|
||||||
|
|
@ -131,13 +132,8 @@ def scan_xss(url, agent=None, proxy=None):
|
||||||
if status != 404:
|
if status != 404:
|
||||||
if query in html_data:
|
if query in html_data:
|
||||||
return True, None
|
return True, None
|
||||||
retry_flags -= 1
|
return False, None
|
||||||
except requests.exceptions.ChunkedEncodingError:
|
except (requests.exceptions.ChunkedEncodingError, requests.exceptions.ConnectionError):
|
||||||
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
|
||||||
"encoding seems to be messed up, retrying request...", level=30
|
|
||||||
))
|
|
||||||
retry_flags -= 1
|
|
||||||
|
|
||||||
return False, None
|
return False, None
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -148,6 +144,7 @@ def main_xss(start_url, proxy=None, agent=None, **kwargs):
|
||||||
tamper = kwargs.get("tamper", None)
|
tamper = kwargs.get("tamper", None)
|
||||||
verbose = kwargs.get("verbose", False)
|
verbose = kwargs.get("verbose", False)
|
||||||
batch = kwargs.get("batch", False)
|
batch = kwargs.get("batch", False)
|
||||||
|
force = kwargs.get("force_ssl", False)
|
||||||
|
|
||||||
question_msg = (
|
question_msg = (
|
||||||
"it appears that heuristic tests have shown this URL may not be a good "
|
"it appears that heuristic tests have shown this URL may not be a good "
|
||||||
|
|
@ -168,30 +165,30 @@ def main_xss(start_url, proxy=None, agent=None, **kwargs):
|
||||||
try:
|
try:
|
||||||
if tamper:
|
if tamper:
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"tampering payloads with '{}'...".format(tamper)
|
"tampering payloads with '{}'".format(tamper)
|
||||||
))
|
))
|
||||||
find_xss_script(start_url)
|
find_xss_script(start_url)
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"loading payloads..."
|
"loading payloads"
|
||||||
))
|
))
|
||||||
payloads = __load_payloads()
|
payloads = __load_payloads()
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
||||||
"a total of {} payloads loaded...".format(len(payloads)), level=10
|
"a total of {} payloads loaded".format(len(payloads)), level=10
|
||||||
))
|
))
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"payloads will be written to a temporary file and read from there..."
|
"payloads will be written to a temporary file and read from there"
|
||||||
))
|
))
|
||||||
filename = create_urls(start_url, payloads, tamper=tamper, verbose=verbose)
|
filename = create_urls(start_url, payloads, tamper=tamper, verbose=verbose, force=force)
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"loaded URL's have been saved to '{}'...".format(filename), level=25
|
"loaded URL's have been saved to '{}'".format(filename), level=25
|
||||||
))
|
))
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"testing for XSS vulnerabilities on host '{}'...".format(start_url)
|
"testing for XSS vulnerabilities on host '{}'".format(start_url)
|
||||||
))
|
))
|
||||||
if proxy is not None:
|
if proxy is not None:
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"using proxy '{}'...".format(proxy)
|
"using proxy '{}'".format(proxy)
|
||||||
))
|
))
|
||||||
success = set()
|
success = set()
|
||||||
with open(filename) as urls:
|
with open(filename) as urls:
|
||||||
|
|
@ -202,41 +199,43 @@ def main_xss(start_url, proxy=None, agent=None, **kwargs):
|
||||||
result = scan_xss(url, proxy=proxy, agent=agent)
|
result = scan_xss(url, proxy=proxy, agent=agent)
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"trying payload '{}'...".format(payload)
|
"trying payload '{}'".format(payload)
|
||||||
))
|
))
|
||||||
if result[0] != "sqli" and result[0] is True:
|
if result[0] != "sqli" and result[0] is True:
|
||||||
success.add(url)
|
success.add(url)
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
||||||
"payload '{}' appears to be usable...".format(payload), level=15
|
"payload '{}' appears to be usable".format(payload), level=15
|
||||||
))
|
))
|
||||||
elif result[0] is "sqli":
|
elif result[0] is "sqli":
|
||||||
if i <= 1:
|
if i <= 1:
|
||||||
lib.core.settings.logger.error(lib.core.settings.set_color(
|
lib.core.settings.logger.error(lib.core.settings.set_color(
|
||||||
"loaded URL '{}' threw a DBMS error and appears to be injectable, test for "
|
"loaded URL '{}' threw a DBMS error and appears to be injectable, test for "
|
||||||
"SQL injection, backend DBMS appears to be '{}'...".format(
|
"SQL injection, backend DBMS appears to be '{}'".format(
|
||||||
url, result[1]
|
url, result[1]
|
||||||
), level=40
|
), level=40
|
||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.error(lib.core.settings.set_color(
|
lib.core.settings.logger.error(lib.core.settings.set_color(
|
||||||
"SQL error discovered...", level=40
|
"SQL error discovered", level=40
|
||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
||||||
"host '{}' does not appear to be vulnerable to XSS attacks with payload '{}'...".format(
|
"host '{}' does not appear to be vulnerable to XSS attacks with payload '{}'".format(
|
||||||
start_url, payload
|
start_url, payload
|
||||||
), level=10
|
), level=10
|
||||||
))
|
))
|
||||||
except (
|
except (
|
||||||
requests.exceptions.ConnectionError,
|
requests.exceptions.ConnectionError,
|
||||||
requests.exceptions.TooManyRedirects,
|
requests.exceptions.TooManyRedirects,
|
||||||
requests.exceptions.ReadTimeout
|
requests.exceptions.ReadTimeout,
|
||||||
|
requests.exceptions.InvalidURL
|
||||||
):
|
):
|
||||||
|
if not payload == "":
|
||||||
lib.core.settings.logger.error(lib.core.settings.set_color(
|
lib.core.settings.logger.error(lib.core.settings.set_color(
|
||||||
"payload '{}' caused a connection error, assuming no good and continuing...".format(payload), level=40
|
"payload '{}' caused a connection error, assuming no good and continuing".format(payload), level=40
|
||||||
))
|
))
|
||||||
|
|
||||||
if len(success) != 0:
|
if len(success) != 0:
|
||||||
|
|
@ -246,7 +245,7 @@ def main_xss(start_url, proxy=None, agent=None, **kwargs):
|
||||||
lib.core.settings.create_tree(start_url, list(success))
|
lib.core.settings.create_tree(start_url, list(success))
|
||||||
else:
|
else:
|
||||||
lib.core.settings.logger.error(lib.core.settings.set_color(
|
lib.core.settings.logger.error(lib.core.settings.set_color(
|
||||||
"host '{}' does not appear to be vulnerable to XSS attacks...".format(start_url), level=40
|
"host '{}' does not appear to be vulnerable to XSS attacks".format(start_url), level=40
|
||||||
))
|
))
|
||||||
question_msg = "would you like to keep the created URLs saved for further testing"
|
question_msg = "would you like to keep the created URLs saved for further testing"
|
||||||
if not batch:
|
if not batch:
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ STATUS_CODES = {
|
||||||
200: "OK", 201: "created", 202: "accepted", 203: "non-authoritative information",
|
200: "OK", 201: "created", 202: "accepted", 203: "non-authoritative information",
|
||||||
204: "no content", 205: "reset content", 206: "partial content",
|
204: "no content", 205: "reset content", 206: "partial content",
|
||||||
207: "multi-status", 208: "already reported", 226: "IM used",
|
207: "multi-status", 208: "already reported", 226: "IM used",
|
||||||
300: "multiple choices", 301: "moved permanently", 302: "not found",
|
300: "multiple choices", 301: "moved permanently", 302: "found redirect",
|
||||||
303: "see other", 304: "not modified", 305: "use proxy",
|
303: "see other", 304: "not modified", 305: "use proxy",
|
||||||
306: "switch proxy", 308: "permanent redirect",
|
306: "switch proxy", 308: "permanent redirect",
|
||||||
400: "bad request", 401: "unauthorized", 402: "payment required",
|
400: "bad request", 401: "unauthorized", 402: "payment required",
|
||||||
|
|
@ -162,7 +162,7 @@ def write_to_log_file(data_to_write, path, filename, blacklist=False):
|
||||||
items = log.readlines()
|
items = log.readlines()
|
||||||
if any(d.strip() == data_to_write for d in items):
|
if any(d.strip() == data_to_write for d in items):
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"query already in blacklist..."
|
"query already in blacklist"
|
||||||
))
|
))
|
||||||
return full_file_path
|
return full_file_path
|
||||||
else:
|
else:
|
||||||
|
|
@ -181,7 +181,7 @@ def write_to_log_file(data_to_write, path, filename, blacklist=False):
|
||||||
else:
|
else:
|
||||||
log.write(data_to_write + "\n")
|
log.write(data_to_write + "\n")
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"successfully wrote found items to '{}'...".format(full_file_path)
|
"successfully wrote found items to '{}'".format(full_file_path)
|
||||||
))
|
))
|
||||||
return full_file_path
|
return full_file_path
|
||||||
|
|
||||||
|
|
@ -276,7 +276,7 @@ def run_fix(message, command, fail_message, exit_process=False):
|
||||||
subprocess.call(cmd)
|
subprocess.call(cmd)
|
||||||
if exit_process:
|
if exit_process:
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"command completed successfully, should be safe to re-run Zeus..."
|
"command completed successfully, should be safe to re-run Zeus"
|
||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
||||||
|
|
@ -329,7 +329,11 @@ def get_page(url, **kwargs):
|
||||||
else:
|
else:
|
||||||
proxies = {}
|
proxies = {}
|
||||||
|
|
||||||
req = requests.get(url, params=headers, proxies=proxies, verify=False if skip_verf else True, timeout=20)
|
if proxy is not None and "127.0.0.1" in proxy:
|
||||||
|
req = requests.get(url, params=headers, proxies=proxies, verify=False, timeout=40)
|
||||||
|
else:
|
||||||
|
req = requests.get(url, params=headers, proxies=proxies, verify=False, timeout=20)
|
||||||
|
|
||||||
status = req.status_code
|
status = req.status_code
|
||||||
html = req.content
|
html = req.content
|
||||||
headers = req.headers
|
headers = req.headers
|
||||||
|
|
|
||||||
|
|
@ -20,3 +20,6 @@ class InvalidTamperProvided(Exception): pass
|
||||||
|
|
||||||
|
|
||||||
class PortScanTimeOutException(Exception): pass
|
class PortScanTimeOutException(Exception): pass
|
||||||
|
|
||||||
|
|
||||||
|
class ZeusArgumentException(Exception): pass
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import sys
|
||||||
from optparse import (
|
from optparse import (
|
||||||
OptionParser,
|
OptionParser,
|
||||||
OptionGroup,
|
OptionGroup,
|
||||||
|
|
@ -6,6 +7,7 @@ from optparse import (
|
||||||
|
|
||||||
import lib.core.settings
|
import lib.core.settings
|
||||||
import lib.core.common
|
import lib.core.common
|
||||||
|
import lib.core.errors
|
||||||
import lib.attacks.nmap_scan.nmap_opts
|
import lib.attacks.nmap_scan.nmap_opts
|
||||||
import lib.attacks.sqlmap_scan.sqlmap_opts
|
import lib.attacks.sqlmap_scan.sqlmap_opts
|
||||||
|
|
||||||
|
|
@ -24,7 +26,7 @@ class ZeusParser(OptionParser):
|
||||||
"""
|
"""
|
||||||
command line parser, parses all of Zeus's arguments and flags
|
command line parser, parses all of Zeus's arguments and flags
|
||||||
"""
|
"""
|
||||||
parser = OptionParser(usage="./zeus.py -d|r|l|f|b| DORK|FILE|URL [ATTACKS] [--OPTS]")
|
parser = OptionParser(usage="./zeus.py -d|r|l|f|b DORK|FILE|URL [ATTACKS] [--OPTS]")
|
||||||
|
|
||||||
# mandatory options
|
# mandatory options
|
||||||
mandatory = OptionGroup(parser, "Mandatory Options",
|
mandatory = OptionGroup(parser, "Mandatory Options",
|
||||||
|
|
@ -45,6 +47,11 @@ class ZeusParser(OptionParser):
|
||||||
mandatory.add_option("-f", "--url-file", dest="fileToEnumerate", metavar="FILE-PATH",
|
mandatory.add_option("-f", "--url-file", dest="fileToEnumerate", metavar="FILE-PATH",
|
||||||
help="Run an attack on URL's in a given file")
|
help="Run an attack on URL's in a given file")
|
||||||
|
|
||||||
|
# being worked on
|
||||||
|
# TODO:/
|
||||||
|
mandatory.add_option("-u", "--url", dest="singleTargetRecon", metavar="URL",
|
||||||
|
help=SUPPRESS_HELP)
|
||||||
|
|
||||||
# attack options
|
# attack options
|
||||||
attacks = OptionGroup(parser, "Attack arguments",
|
attacks = OptionGroup(parser, "Attack arguments",
|
||||||
"These arguments will give you the choice on how you want to check the websites")
|
"These arguments will give you the choice on how you want to check the websites")
|
||||||
|
|
@ -67,8 +74,10 @@ class ZeusParser(OptionParser):
|
||||||
attacks.add_option("-c", "--clickjacking", dest="performClickjackingScan", action="store_true",
|
attacks.add_option("-c", "--clickjacking", dest="performClickjackingScan", action="store_true",
|
||||||
help="Perform a clickjacking scan on a provided URL")
|
help="Perform a clickjacking scan on a provided URL")
|
||||||
|
|
||||||
|
# being worked on
|
||||||
|
# TODO:/
|
||||||
attacks.add_option("-g", "--github-search", dest="searchGithub", action="store_true",
|
attacks.add_option("-g", "--github-search", dest="searchGithub", action="store_true",
|
||||||
help="Perform a Github Gist search for any information on the found websites")
|
help=SUPPRESS_HELP)
|
||||||
|
|
||||||
attacks.add_option("-P", "--pgp", dest="pgpLookup", action="store_true",
|
attacks.add_option("-P", "--pgp", dest="pgpLookup", action="store_true",
|
||||||
help="Perform a PGP public key lookup on the found URLs")
|
help="Perform a PGP public key lookup on the found URLs")
|
||||||
|
|
@ -96,6 +105,8 @@ class ZeusParser(OptionParser):
|
||||||
attacks.add_option("--tamper", dest="tamperXssPayloads", metavar="TAMPER-SCRIPT",
|
attacks.add_option("--tamper", dest="tamperXssPayloads", metavar="TAMPER-SCRIPT",
|
||||||
help="Send the XSS payloads through tampering before sending to the target")
|
help="Send the XSS payloads through tampering before sending to the target")
|
||||||
|
|
||||||
|
# being worked on
|
||||||
|
# TODO:/
|
||||||
attacks.add_option("--thread", dest="threadPanels", action="store_true",
|
attacks.add_option("--thread", dest="threadPanels", action="store_true",
|
||||||
help=SUPPRESS_HELP)
|
help=SUPPRESS_HELP)
|
||||||
|
|
||||||
|
|
@ -141,6 +152,11 @@ class ZeusParser(OptionParser):
|
||||||
help="Attempt to identify if the target is protected by some kind of "
|
help="Attempt to identify if the target is protected by some kind of "
|
||||||
"WAF/IDS/IPS")
|
"WAF/IDS/IPS")
|
||||||
|
|
||||||
|
# being worked on
|
||||||
|
# TODO:/
|
||||||
|
search_items.add_option("--force-ssl", dest="forceSSL", action="store_true",
|
||||||
|
help=SUPPRESS_HELP)
|
||||||
|
|
||||||
search_items.add_option("--identify-plugins", dest="identifyPlugin", action="store_true",
|
search_items.add_option("--identify-plugins", dest="identifyPlugin", action="store_true",
|
||||||
help="Attempt to identify what plugins the target is using")
|
help="Attempt to identify what plugins the target is using")
|
||||||
|
|
||||||
|
|
@ -182,6 +198,8 @@ class ZeusParser(OptionParser):
|
||||||
misc.add_option("--version", dest="showCurrentVersion", action="store_true",
|
misc.add_option("--version", dest="showCurrentVersion", action="store_true",
|
||||||
help="Show the current version and exit")
|
help="Show the current version and exit")
|
||||||
|
|
||||||
|
# being worked on
|
||||||
|
# TODO:/
|
||||||
misc.add_option("-T", "--x-threads", dest="amountOfThreads", metavar="THREAD-AMOUNT", type=int,
|
misc.add_option("-T", "--x-threads", dest="amountOfThreads", metavar="THREAD-AMOUNT", type=int,
|
||||||
help=SUPPRESS_HELP)
|
help=SUPPRESS_HELP)
|
||||||
|
|
||||||
|
|
@ -221,7 +239,7 @@ class ZeusParser(OptionParser):
|
||||||
)
|
)
|
||||||
print("\n")
|
print("\n")
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"for more information about sqlmap arguments, see here '{}'...".format(
|
"for more information about sqlmap arguments, see here '{}'".format(
|
||||||
lib.core.settings.SQLMAP_MAN_PAGE_URL
|
lib.core.settings.SQLMAP_MAN_PAGE_URL
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
@ -240,7 +258,7 @@ class ZeusParser(OptionParser):
|
||||||
)
|
)
|
||||||
print("\n")
|
print("\n")
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"for more information on what the arguments do please see here '{}'...".format(
|
"for more information on what the arguments do please see here '{}'".format(
|
||||||
lib.core.settings.NMAP_MAN_PAGE_URL
|
lib.core.settings.NMAP_MAN_PAGE_URL
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
@ -249,7 +267,29 @@ class ZeusParser(OptionParser):
|
||||||
# update the program
|
# update the program
|
||||||
if opt.updateZeus:
|
if opt.updateZeus:
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"update in progress..."
|
"update in progress"
|
||||||
))
|
))
|
||||||
lib.core.settings.update_zeus()
|
lib.core.settings.update_zeus()
|
||||||
lib.core.common.shutdown()
|
lib.core.common.shutdown()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def verify_args(args=sys.argv):
|
||||||
|
not_implemented_args = (
|
||||||
|
"-T", "--x-threads", "--force-ssl", "--thread",
|
||||||
|
"-g", "--github-search", "-u", "--url"
|
||||||
|
)
|
||||||
|
# check if any of the arguments are not implemented that have been passed
|
||||||
|
# via the command line
|
||||||
|
# TODO:/
|
||||||
|
# need to create a way to parse all arguments for compatibility with one another
|
||||||
|
for arg in args:
|
||||||
|
for nia in not_implemented_args:
|
||||||
|
if arg == nia:
|
||||||
|
raise lib.core.errors.ZeusArgumentException(
|
||||||
|
"\n\nit appears that one of the arguments you have passed ('{}'), "
|
||||||
|
"has not been implemented into Zeus production yet. This usually means "
|
||||||
|
"that the option is still in testing and is not ready for use. Arguments "
|
||||||
|
"that are still in testing are: {}\n".format(
|
||||||
|
nia, ", ".join(["'{}'".format(a) for a in not_implemented_args])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
@ -8,7 +8,6 @@ import shlex
|
||||||
import difflib
|
import difflib
|
||||||
import logging
|
import logging
|
||||||
import base64
|
import base64
|
||||||
import string
|
|
||||||
import random
|
import random
|
||||||
import socket
|
import socket
|
||||||
import struct
|
import struct
|
||||||
|
|
@ -45,7 +44,7 @@ CLONE = "https://github.com/ekultek/zeus-scanner.git"
|
||||||
ISSUE_LINK = "https://github.com/ekultek/zeus-scanner/issues"
|
ISSUE_LINK = "https://github.com/ekultek/zeus-scanner/issues"
|
||||||
|
|
||||||
# current version <major.minor.commit.patch ID>
|
# current version <major.minor.commit.patch ID>
|
||||||
VERSION = "1.4".format(PATCH_ID)
|
VERSION = "1.5.2.{}".format(PATCH_ID)
|
||||||
|
|
||||||
# colors to output depending on the version
|
# colors to output depending on the version
|
||||||
VERSION_TYPE_COLORS = {"dev": 33, "stable": 92, "other": 30}
|
VERSION_TYPE_COLORS = {"dev": 33, "stable": 92, "other": 30}
|
||||||
|
|
@ -284,13 +283,6 @@ AUTHORIZED_SEARCH_ENGINES = {
|
||||||
"pgp": "https://pgp.mit.edu/pks/lookup?search={}&op=index"
|
"pgp": "https://pgp.mit.edu/pks/lookup?search={}&op=index"
|
||||||
}
|
}
|
||||||
|
|
||||||
# search page for Gists and rate checking URL
|
|
||||||
GITHUB_GIST_SEARCH_URLS = {
|
|
||||||
"search": "https://api.github.com/gists/public?page={}&per_page=100",
|
|
||||||
"check_rate": "https://api.github.com/users/ZeusIssueReporter"
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
# extensions to exclude from the spider
|
# extensions to exclude from the spider
|
||||||
SPIDER_EXT_EXCLUDE = (
|
SPIDER_EXT_EXCLUDE = (
|
||||||
"3ds", "3g2", "3gp", "7z", "DS_Store", "a", "aac", "adp", "ai", "aif", "aiff",
|
"3ds", "3g2", "3gp", "7z", "DS_Store", "a", "aac", "adp", "ai", "aif", "aiff",
|
||||||
|
|
@ -320,7 +312,7 @@ URL_EXCLUDES = (
|
||||||
"torproject.org", "search-results.com", "index.com",
|
"torproject.org", "search-results.com", "index.com",
|
||||||
"gov", ".gov", "facebook.com", "instagram.com", "snapchat",
|
"gov", ".gov", "facebook.com", "instagram.com", "snapchat",
|
||||||
"stackoverflow", "stackexchange", "github.com", "apple.com",
|
"stackoverflow", "stackexchange", "github.com", "apple.com",
|
||||||
"http://my."
|
"http://my.", "root.cern"
|
||||||
)
|
)
|
||||||
|
|
||||||
# regular expressions used for DBMS recognition based on error message response
|
# regular expressions used for DBMS recognition based on error message response
|
||||||
|
|
@ -465,7 +457,7 @@ def setup(verbose=False):
|
||||||
"""
|
"""
|
||||||
if verbose:
|
if verbose:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
"checking if the application has been run before...", level=10
|
"checking if the application has been run before", level=10
|
||||||
))
|
))
|
||||||
bin.unzip_gecko.main(verbose=verbose)
|
bin.unzip_gecko.main(verbose=verbose)
|
||||||
|
|
||||||
|
|
@ -513,12 +505,12 @@ def grab_random_agent(agent_path="{}/etc/text_files/agents.txt", verbose=False):
|
||||||
"""
|
"""
|
||||||
if verbose:
|
if verbose:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
"grabbing random user-agent from '{}'...".format(agent_path.format(os.getcwd())), level=10
|
"grabbing random user-agent from '{}'".format(agent_path.format(os.getcwd())), level=10
|
||||||
))
|
))
|
||||||
with open(agent_path.format(os.getcwd())) as agents:
|
with open(agent_path.format(os.getcwd())) as agents:
|
||||||
retval = random.choice(agents.readlines())
|
retval = random.choice(agents.readlines())
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"random agent being used '{}'...".format(retval.strip())
|
"random agent being used '{}'".format(retval.strip())
|
||||||
))
|
))
|
||||||
return retval.strip()
|
return retval.strip()
|
||||||
|
|
||||||
|
|
@ -555,7 +547,7 @@ def update_zeus():
|
||||||
return os.system("git pull origin master")
|
return os.system("git pull origin master")
|
||||||
else:
|
else:
|
||||||
logger.fatal(set_color(
|
logger.fatal(set_color(
|
||||||
"no git repository found in directory, unable to update automatically..."
|
"no git repository found in directory, unable to update automatically"
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -608,28 +600,34 @@ def search_for_process(name):
|
||||||
return False if not any(name in proc for proc in list(all_process_names)) else True
|
return False if not any(name in proc for proc in list(all_process_names)) else True
|
||||||
|
|
||||||
|
|
||||||
def get_browser_version():
|
def get_browser_version(output=True):
|
||||||
"""
|
"""
|
||||||
obtain the firefox browser version, this is necessary because zeus can only handle certain versions.
|
obtain the firefox browser version, this is necessary because zeus can only handle certain versions.
|
||||||
"""
|
"""
|
||||||
|
if output:
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"attempting to get firefox browser version..."
|
"attempting to get firefox browser version"
|
||||||
))
|
))
|
||||||
try:
|
try:
|
||||||
firefox_version_command = shlex.split("firefox --version")
|
firefox_version_command = shlex.split("firefox --version")
|
||||||
output = subprocess.check_output(firefox_version_command)
|
output = subprocess.check_output(firefox_version_command)
|
||||||
except (OSError, Exception):
|
except OSError:
|
||||||
logger.error(set_color(
|
logger.error(set_color(
|
||||||
"failed to run firefox...", level=50
|
"failed to run firefox", level=50
|
||||||
))
|
))
|
||||||
return "failed to start"
|
return "failed to start"
|
||||||
try:
|
try:
|
||||||
major, minor = map(int, re.search(r"(\d+).(\d+)", output).groups())
|
major, minor = map(int, re.search(r"(\d+).(\d+)", output).groups())
|
||||||
except (ValueError, Exception):
|
except ValueError:
|
||||||
logger.error(set_color(
|
logger.error(set_color(
|
||||||
"failed to parse '{}' for version number...".format(output), level=50
|
"failed to parse '{}' for version number".format(output), level=50
|
||||||
))
|
))
|
||||||
return "failed to gather"
|
return output
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(set_color(
|
||||||
|
"received and exception from firefox '{}'".format(str(e), level=50)
|
||||||
|
))
|
||||||
|
return str(e)
|
||||||
return major, minor
|
return major, minor
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -643,11 +641,15 @@ def config_headers(**kwargs):
|
||||||
rand_agent = kwargs.get("rand_agent", None)
|
rand_agent = kwargs.get("rand_agent", None)
|
||||||
verbose = kwargs.get("verbose", False)
|
verbose = kwargs.get("verbose", False)
|
||||||
if proxy is not None:
|
if proxy is not None:
|
||||||
|
if "127.0.0.1" in proxy:
|
||||||
|
logger.warning(set_color(
|
||||||
|
"timeout will be increased to 40s due to Tor being used", level=30
|
||||||
|
))
|
||||||
proxy_retval = proxy
|
proxy_retval = proxy
|
||||||
elif rand_proxy is not None:
|
elif rand_proxy is not None:
|
||||||
if verbose:
|
if verbose:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
"loading random proxy from '{}'...".format(rand_proxy), level=10
|
"loading random proxy from '{}'".format(rand_proxy), level=10
|
||||||
))
|
))
|
||||||
with open(rand_proxy) as proxies:
|
with open(rand_proxy) as proxies:
|
||||||
possible = proxies.readlines()
|
possible = proxies.readlines()
|
||||||
|
|
@ -673,14 +675,14 @@ def get_md5sum(url="https://raw.githubusercontent.com/Ekultek/Zeus-Scanner/maste
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def create_identifier(chars=string.ascii_letters):
|
def create_identifier(st):
|
||||||
"""
|
"""
|
||||||
create the identifier for your Github issue
|
create the identifier for your Github issue
|
||||||
"""
|
"""
|
||||||
retval = []
|
import hashlib
|
||||||
for _ in range(0, 7):
|
obj = hashlib.md5()
|
||||||
retval.append(random.choice(chars))
|
obj.update(st)
|
||||||
return "".join(retval)
|
return obj.hexdigest()[1:9]
|
||||||
|
|
||||||
|
|
||||||
def config_search_engine(**kwargs):
|
def config_search_engine(**kwargs):
|
||||||
|
|
@ -693,8 +695,8 @@ def config_search_engine(**kwargs):
|
||||||
ddg = kwargs.get("ddg", False)
|
ddg = kwargs.get("ddg", False)
|
||||||
enum = kwargs.get("enum", None)
|
enum = kwargs.get("enum", None)
|
||||||
|
|
||||||
non_default_msg = "specified to use non-default search engine..."
|
non_default_msg = "specified to use non-default search engine"
|
||||||
se_message = "using '{}' as the search engine..."
|
se_message = "using '{}' as the search engine"
|
||||||
if ddg:
|
if ddg:
|
||||||
if verbose:
|
if verbose:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
|
|
@ -706,7 +708,7 @@ def config_search_engine(**kwargs):
|
||||||
se = AUTHORIZED_SEARCH_ENGINES["duckduckgo"]
|
se = AUTHORIZED_SEARCH_ENGINES["duckduckgo"]
|
||||||
elif aol:
|
elif aol:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"AOL will take a little longer due to pop-ups...", level=30
|
"AOL will take a little longer due to pop-ups", level=30
|
||||||
))
|
))
|
||||||
if verbose:
|
if verbose:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
|
|
@ -727,16 +729,16 @@ def config_search_engine(**kwargs):
|
||||||
se = AUTHORIZED_SEARCH_ENGINES["bing"]
|
se = AUTHORIZED_SEARCH_ENGINES["bing"]
|
||||||
elif enum is not None:
|
elif enum is not None:
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"running enumeration on given file '{}'...".format(enum)
|
"running enumeration on given file '{}'".format(enum)
|
||||||
))
|
))
|
||||||
se = None
|
se = None
|
||||||
else:
|
else:
|
||||||
if verbose:
|
if verbose:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
"using default search engine (Google)...", level=10
|
"using default search engine (Google)", level=10
|
||||||
))
|
))
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"using default search engine..."
|
"using default search engine"
|
||||||
))
|
))
|
||||||
se = AUTHORIZED_SEARCH_ENGINES["google"]
|
se = AUTHORIZED_SEARCH_ENGINES["google"]
|
||||||
return se
|
return se
|
||||||
|
|
@ -753,7 +755,7 @@ def create_arguments(**kwargs):
|
||||||
conf_file = kwargs.get("conf", None)
|
conf_file = kwargs.get("conf", None)
|
||||||
|
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"creating arguments for {}...".format("sqlmap" if sqlmap else "nmap")
|
"creating arguments for {}".format("sqlmap" if sqlmap else "nmap")
|
||||||
))
|
))
|
||||||
retval = []
|
retval = []
|
||||||
splitter = {"sqlmap": ",", "nmap": "|"}
|
splitter = {"sqlmap": ",", "nmap": "|"}
|
||||||
|
|
@ -765,7 +767,7 @@ def create_arguments(**kwargs):
|
||||||
if o.lower() == opt[0]:
|
if o.lower() == opt[0]:
|
||||||
retval.append((o, opt[1]))
|
retval.append((o, opt[1]))
|
||||||
elif sqlmap:
|
elif sqlmap:
|
||||||
warn_msg = "option '{}' is not recognized by sqlmap API, skipping..."
|
warn_msg = "option '{}' is not recognized by sqlmap API, skipping"
|
||||||
if sqlmap_args is not None:
|
if sqlmap_args is not None:
|
||||||
for line in sqlmap_args.split(splitter["sqlmap"]):
|
for line in sqlmap_args.split(splitter["sqlmap"]):
|
||||||
try:
|
try:
|
||||||
|
|
@ -788,7 +790,7 @@ def create_arguments(**kwargs):
|
||||||
))
|
))
|
||||||
|
|
||||||
elif nmap:
|
elif nmap:
|
||||||
warning_msg = "option {} is not known by the nmap api, skipping..."
|
warning_msg = "option {} is not known by the nmap api, skipping"
|
||||||
if nmap_args is not None:
|
if nmap_args is not None:
|
||||||
for line in nmap_args.split(splitter["nmap"]):
|
for line in nmap_args.split(splitter["nmap"]):
|
||||||
try:
|
try:
|
||||||
|
|
@ -826,7 +828,7 @@ def create_random_ip():
|
||||||
if generated == "0.0.0.0" or "255.255.255.255":
|
if generated == "0.0.0.0" or "255.255.255.255":
|
||||||
generated = __get_nodes() # if it isn't a real IP regenerate it
|
generated = __get_nodes() # if it isn't a real IP regenerate it
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"random IP address generated for header '{}'...".format(generated)
|
"random IP address generated for header '{}'".format(generated)
|
||||||
))
|
))
|
||||||
return generated
|
return generated
|
||||||
|
|
||||||
|
|
@ -854,7 +856,7 @@ def check_for_protection(protected, attack_type):
|
||||||
|
|
||||||
if attack_type in items or "all" in items:
|
if attack_type in items or "all" in items:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"provided target seems to have protection against this attack type...", level=30
|
"provided target seems to have protection against this attack type", level=30
|
||||||
))
|
))
|
||||||
protected.clear() # clear the set
|
protected.clear() # clear the set
|
||||||
return True
|
return True
|
||||||
|
|
@ -868,7 +870,7 @@ def deprecation(target_version, method, connect=True, *args, **kwargs):
|
||||||
print(
|
print(
|
||||||
"[{} DEPRECATION] {}".format(
|
"[{} DEPRECATION] {}".format(
|
||||||
time.strftime("%H:%M:%S"), set_color(
|
time.strftime("%H:%M:%S"), set_color(
|
||||||
"{} will be deprecated by version {}...".format(
|
"{} will be deprecated by version {}".format(
|
||||||
method.__name__, target_version
|
method.__name__, target_version
|
||||||
), level=35
|
), level=35
|
||||||
)
|
)
|
||||||
|
|
@ -880,7 +882,7 @@ def deprecation(target_version, method, connect=True, *args, **kwargs):
|
||||||
"[{} DEPRECATION] {}".format(
|
"[{} DEPRECATION] {}".format(
|
||||||
time.strftime("%H:%M:%S"), set_color(
|
time.strftime("%H:%M:%S"), set_color(
|
||||||
"{} has been deprecated and will no longer work, "
|
"{} has been deprecated and will no longer work, "
|
||||||
"this attack type will be completely removed by v{}...".format(
|
"this attack type will be completely removed by v{}".format(
|
||||||
method.__name__, target_version
|
method.__name__, target_version
|
||||||
), level=35
|
), level=35
|
||||||
)
|
)
|
||||||
|
|
@ -896,10 +898,10 @@ def check_thread_num(number, batch=False, default=5):
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"you have specified {} threads, it is highly advised to not go over {} threads, "
|
"you have specified {} threads, it is highly advised to not go over {} threads, "
|
||||||
"doing so will most likely not give a significant performance increase and also "
|
"doing so will most likely not give a significant performance increase and also "
|
||||||
"will most likely cause unforeseen issues...".format(number, MAX_THREADS), level=30
|
"will most likely cause unforeseen issues".format(number, MAX_THREADS), level=30
|
||||||
))
|
))
|
||||||
question_msg = "would you like to continue anyways"
|
question_msg = "would you like to continue anyways"
|
||||||
default_msg = "defaulting to 5 threads..."
|
default_msg = "defaulting to 5 threads"
|
||||||
if not batch:
|
if not batch:
|
||||||
question = lib.core.common.prompt(
|
question = lib.core.common.prompt(
|
||||||
question_msg, opts="yN"
|
question_msg, opts="yN"
|
||||||
|
|
@ -931,7 +933,7 @@ def run_attacks(url, **kwargs):
|
||||||
verbose = kwargs.get("verbose", False)
|
verbose = kwargs.get("verbose", False)
|
||||||
whois = kwargs.get("whois", False)
|
whois = kwargs.get("whois", False)
|
||||||
clickjacking = kwargs.get("clickjacking", False)
|
clickjacking = kwargs.get("clickjacking", False)
|
||||||
github = kwargs.get("github", False)
|
# github = kwargs.get("github", False)
|
||||||
pgp = kwargs.get("pgp", False)
|
pgp = kwargs.get("pgp", False)
|
||||||
auto_start = kwargs.get("auto_start", False)
|
auto_start = kwargs.get("auto_start", False)
|
||||||
sqlmap_arguments = kwargs.get("sqlmap_args", None)
|
sqlmap_arguments = kwargs.get("sqlmap_args", None)
|
||||||
|
|
@ -946,6 +948,7 @@ def run_attacks(url, **kwargs):
|
||||||
agent = kwargs.get("agent", None)
|
agent = kwargs.get("agent", None)
|
||||||
conf_file = kwargs.get("conf_file", None)
|
conf_file = kwargs.get("conf_file", None)
|
||||||
threads = kwargs.get("threads", None)
|
threads = kwargs.get("threads", None)
|
||||||
|
force_ssl = kwargs.get("ssl", False)
|
||||||
|
|
||||||
if threads > MAX_THREADS:
|
if threads > MAX_THREADS:
|
||||||
threads = check_thread_num(threads, batch=batch)
|
threads = check_thread_num(threads, batch=batch)
|
||||||
|
|
@ -969,7 +972,7 @@ def run_attacks(url, **kwargs):
|
||||||
"as of now only 1 attack is supported at a time, choose "
|
"as of now only 1 attack is supported at a time, choose "
|
||||||
"your attack and try again. You can use the -f flag if "
|
"your attack and try again. You can use the -f flag if "
|
||||||
"you do not want to complete an entire search again "
|
"you do not want to complete an entire search again "
|
||||||
"(IE -f /home/me/zeus-scanner/log/url-log/url-log-1.log)...", level=40
|
"(IE -f /home/me/zeus-scanner/log/url-log/url-log-1.log)", level=40
|
||||||
))
|
))
|
||||||
lib.core.common.shutdown()
|
lib.core.common.shutdown()
|
||||||
|
|
||||||
|
|
@ -1008,6 +1011,7 @@ def run_attacks(url, **kwargs):
|
||||||
main_xss(
|
main_xss(
|
||||||
url, verbose=verbose, proxy=proxy,
|
url, verbose=verbose, proxy=proxy,
|
||||||
agent=agent, tamper=tamper_script, batch=batch,
|
agent=agent, tamper=tamper_script, batch=batch,
|
||||||
|
force_ssl=force_ssl
|
||||||
)
|
)
|
||||||
elif whois:
|
elif whois:
|
||||||
from lib.attacks.whois_lookup.whois import whois_lookup_main
|
from lib.attacks.whois_lookup.whois import whois_lookup_main
|
||||||
|
|
@ -1019,10 +1023,10 @@ def run_attacks(url, **kwargs):
|
||||||
if check_for_protection(PROTECTED, "clickjacking"):
|
if check_for_protection(PROTECTED, "clickjacking"):
|
||||||
clickjacking_main(url, agent=agent, proxy=proxy,
|
clickjacking_main(url, agent=agent, proxy=proxy,
|
||||||
forward=forwarded, batch=batch)
|
forward=forwarded, batch=batch)
|
||||||
elif github:
|
# elif github:
|
||||||
from lib.attacks.gist_lookup import github_gist_search_main
|
# from lib.attacks.gist_lookup import github_gist_search_main
|
||||||
query = replace_http(url)
|
# query = replace_http(url)
|
||||||
github_gist_search_main(query, agent=agent, proxy=proxy, verbose=verbose)
|
# github_gist_search_main(query, agent=agent, proxy=proxy, verbose=verbose)
|
||||||
elif pgp:
|
elif pgp:
|
||||||
from var.search.pgp_search import pgp_main
|
from var.search.pgp_search import pgp_main
|
||||||
pgp_main(url, verbose=verbose)
|
pgp_main(url, verbose=verbose)
|
||||||
|
|
@ -1030,7 +1034,7 @@ def run_attacks(url, **kwargs):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"skipping '{}'...".format(url), level=30
|
"skipping '{}'".format(url), level=30
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,14 @@
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import time
|
||||||
import importlib
|
import importlib
|
||||||
import unicodedata
|
import unicodedata
|
||||||
|
|
||||||
from xml.dom import minidom
|
from xml.dom import minidom
|
||||||
from requests.exceptions import ConnectionError
|
from requests.exceptions import (
|
||||||
|
ConnectionError,
|
||||||
|
ReadTimeout
|
||||||
|
)
|
||||||
|
|
||||||
from var.auto_issue.github import request_issue_creation
|
from var.auto_issue.github import request_issue_creation
|
||||||
from lib.core.common import (
|
from lib.core.common import (
|
||||||
|
|
@ -12,7 +16,7 @@ from lib.core.common import (
|
||||||
shutdown,
|
shutdown,
|
||||||
pause,
|
pause,
|
||||||
get_page,
|
get_page,
|
||||||
HTTP_HEADER
|
HTTP_HEADER,
|
||||||
)
|
)
|
||||||
from lib.core.settings import (
|
from lib.core.settings import (
|
||||||
logger, set_color,
|
logger, set_color,
|
||||||
|
|
@ -46,17 +50,12 @@ def get_charset(html, headers, **kwargs):
|
||||||
content = headers.get(HTTP_HEADER.CONTENT_TYPE, "")
|
content = headers.get(HTTP_HEADER.CONTENT_TYPE, "")
|
||||||
charset = charset_regex.search(content)
|
charset = charset_regex.search(content)
|
||||||
if charset is not None:
|
if charset is not None:
|
||||||
return charset
|
return charset.group(1)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def detect_protection(url, status, html, headers, **kwargs):
|
def detect_protection(url, status, html, headers, **kwargs):
|
||||||
verbose = kwargs.get("verbose", False)
|
verbose = kwargs.get("verbose", False)
|
||||||
|
|
||||||
if verbose:
|
|
||||||
logger.debug(set_color(
|
|
||||||
"attempting connection to '{}'...".format(url), level=10
|
|
||||||
))
|
|
||||||
try:
|
try:
|
||||||
# make sure there are no DBMS errors in the HTML
|
# make sure there are no DBMS errors in the HTML
|
||||||
for dbms in DBMS_ERRORS:
|
for dbms in DBMS_ERRORS:
|
||||||
|
|
@ -65,7 +64,7 @@ def detect_protection(url, status, html, headers, **kwargs):
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"it appears that the WAF/IDS/IPS check threw a DBMS error and may be vulnerable "
|
"it appears that the WAF/IDS/IPS check threw a DBMS error and may be vulnerable "
|
||||||
"to SQL injection attacks. it appears the backend DBMS is '{}', site will be "
|
"to SQL injection attacks. it appears the backend DBMS is '{}', site will be "
|
||||||
"saved for further processing...".format(dbms), level=30
|
"saved for further processing".format(dbms), level=30
|
||||||
))
|
))
|
||||||
write_to_log_file(url, SQLI_SITES_FILEPATH, SQLI_FOUND_FILENAME)
|
write_to_log_file(url, SQLI_SITES_FILEPATH, SQLI_FOUND_FILENAME)
|
||||||
return None
|
return None
|
||||||
|
|
@ -76,7 +75,7 @@ def detect_protection(url, status, html, headers, **kwargs):
|
||||||
item = item[:-3]
|
item = item[:-3]
|
||||||
if verbose:
|
if verbose:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
"loading script '{}'...".format(item), level=10
|
"loading script '{}'".format(item), level=10
|
||||||
))
|
))
|
||||||
detection_name = "lib.firewall.{}"
|
detection_name = "lib.firewall.{}"
|
||||||
detection_name = detection_name.format(item)
|
detection_name = detection_name.format(item)
|
||||||
|
|
@ -89,7 +88,7 @@ def detect_protection(url, status, html, headers, **kwargs):
|
||||||
del retval[retval.index("Generic (Unknown)")]
|
del retval[retval.index("Generic (Unknown)")]
|
||||||
except (Exception, IndexError):
|
except (Exception, IndexError):
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"multiple firewalls identified ({}), displaying most likely...".format(
|
"multiple firewalls identified ({}), displaying most likely".format(
|
||||||
", ".join([item.split("(")[0] for item in retval])
|
", ".join([item.split("(")[0] for item in retval])
|
||||||
), level=30
|
), level=30
|
||||||
))
|
))
|
||||||
|
|
@ -100,7 +99,7 @@ def detect_protection(url, status, html, headers, **kwargs):
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"discovered firewall is unknown to Zeus, saving fingerprint to file. "
|
"discovered firewall is unknown to Zeus, saving fingerprint to file. "
|
||||||
"if you know the details or the context of the firewall please create "
|
"if you know the details or the context of the firewall please create "
|
||||||
"an issue ({}) with the fingerprint, or a pull request with the script...".format(
|
"an issue ({}) with the fingerprint, or a pull request with the script".format(
|
||||||
ISSUE_LINK
|
ISSUE_LINK
|
||||||
), level=30
|
), level=30
|
||||||
))
|
))
|
||||||
|
|
@ -113,14 +112,14 @@ def detect_protection(url, status, html, headers, **kwargs):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if "Read timed out." or "Connection reset by peer" in str(e):
|
if any(err in str(e) for err in ["Read timed out.", "Connection reset by peer"]):
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"detection request failed, assuming no protection and continuing...", level=30
|
"detection request failed, assuming no protection and continuing", level=30
|
||||||
))
|
))
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
logger.exception(set_color(
|
logger.exception(set_color(
|
||||||
"Zeus ran into an unexpected error '{}'...".format(e), level=50
|
"Zeus ran into an unexpected error '{}'".format(e), level=50
|
||||||
))
|
))
|
||||||
request_issue_creation()
|
request_issue_creation()
|
||||||
return None
|
return None
|
||||||
|
|
@ -137,7 +136,7 @@ def detect_plugins(html, headers, **kwargs):
|
||||||
plugin = plugin[:-3]
|
plugin = plugin[:-3]
|
||||||
if verbose:
|
if verbose:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
"loading script '{}'...".format(plugin), level=10
|
"loading script '{}'".format(plugin), level=10
|
||||||
))
|
))
|
||||||
plugin_detection = "lib.plugins.{}"
|
plugin_detection = "lib.plugins.{}"
|
||||||
plugin_detection = plugin_detection.format(plugin)
|
plugin_detection = plugin_detection.format(plugin)
|
||||||
|
|
@ -151,12 +150,12 @@ def detect_plugins(html, headers, **kwargs):
|
||||||
logger.exception(str(e))
|
logger.exception(str(e))
|
||||||
if "Read timed out." or "Connection reset by peer" in str(e):
|
if "Read timed out." or "Connection reset by peer" in str(e):
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"plugin request failed, assuming no plugins and continuing...", level=30
|
"plugin request failed, assuming no plugins and continuing", level=30
|
||||||
))
|
))
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
logger.exception(set_color(
|
logger.exception(set_color(
|
||||||
"plugin detection has failed with error {}...".format(str(e))
|
"plugin detection has failed with error {}".format(str(e))
|
||||||
))
|
))
|
||||||
request_issue_creation()
|
request_issue_creation()
|
||||||
|
|
||||||
|
|
@ -181,7 +180,7 @@ def load_headers(url, req, **kwargs):
|
||||||
|
|
||||||
if len(req.cookies) > 0:
|
if len(req.cookies) > 0:
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"found a request cookie, saving to file...", level=25
|
"found a request cookie, saving to file", level=25
|
||||||
))
|
))
|
||||||
try:
|
try:
|
||||||
cookie_start = req.cookies.keys()
|
cookie_start = req.cookies.keys()
|
||||||
|
|
@ -247,7 +246,9 @@ def main_header_check(url, **kwargs):
|
||||||
identify_waf = kwargs.get("identify_waf", True)
|
identify_waf = kwargs.get("identify_waf", True)
|
||||||
identify_plugins = kwargs.get("identify_plugins", True)
|
identify_plugins = kwargs.get("identify_plugins", True)
|
||||||
show_description = kwargs.get("show_description", False)
|
show_description = kwargs.get("show_description", False)
|
||||||
|
attempts = kwargs.get("attempts", 3)
|
||||||
|
|
||||||
|
default_sleep_time = 5
|
||||||
protection = {"hostname": url}
|
protection = {"hostname": url}
|
||||||
definition = {
|
definition = {
|
||||||
"x-xss": ("protection against XSS attacks", "XSS"),
|
"x-xss": ("protection against XSS attacks", "XSS"),
|
||||||
|
|
@ -260,69 +261,74 @@ def main_header_check(url, **kwargs):
|
||||||
"content-security": ("header protection against multiple attack types", "ALL")
|
"content-security": ("header protection against multiple attack types", "ALL")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
req, status, html, headers = get_page(url, proxy=proxy, agent=agent, xforward=xforward)
|
req, status, html, headers = get_page(url, proxy=proxy, agent=agent, xforward=xforward)
|
||||||
|
|
||||||
try:
|
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"detecting target charset..."
|
"detecting target charset"
|
||||||
))
|
))
|
||||||
charset = get_charset(url, headers)
|
charset = get_charset(html, headers)
|
||||||
if charset is not None:
|
if charset is not None:
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"target charset appears to be '{}'...".format(charset), level=25
|
"target charset appears to be '{}'".format(charset), level=25
|
||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"unable to detect target charset...", level=30
|
"unable to detect target charset", level=30
|
||||||
))
|
))
|
||||||
if identify_waf:
|
if identify_waf:
|
||||||
waf_url = "{} {}".format(url, PROTECTION_CHECK_PAYLOAD)
|
waf_url = "{} {}".format(url.strip(), PROTECTION_CHECK_PAYLOAD)
|
||||||
_, waf_status, waf_html, waf_headers = get_page(waf_url, xforward=xforward, proxy=proxy, agent=agent)
|
_, waf_status, waf_html, waf_headers = get_page(waf_url, xforward=xforward, proxy=proxy, agent=agent)
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"checking if target URL is protected by some kind of WAF/IPS/IDS..."
|
"checking if target URL is protected by some kind of WAF/IPS/IDS"
|
||||||
))
|
))
|
||||||
|
if verbose:
|
||||||
|
logger.debug(set_color(
|
||||||
|
"attempting connection to '{}'".format(waf_url), level=10
|
||||||
|
))
|
||||||
|
|
||||||
identified_waf = detect_protection(url, waf_status, waf_html, waf_headers, verbose=verbose)
|
identified_waf = detect_protection(url, waf_status, waf_html, waf_headers, verbose=verbose)
|
||||||
|
|
||||||
if identified_waf is None:
|
if identified_waf is None:
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"no WAF/IDS/IPS has been identified on target URL...", level=25
|
"no WAF/IDS/IPS has been identified on target URL", level=25
|
||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"the target URL WAF/IDS/IPS has been identified as '{}'...".format(identified_waf), level=35
|
"the target URL WAF/IDS/IPS has been identified as '{}'".format(identified_waf), level=35
|
||||||
))
|
))
|
||||||
|
|
||||||
if identify_plugins:
|
if identify_plugins:
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"attempting to identify plugins..."
|
"attempting to identify plugins"
|
||||||
))
|
))
|
||||||
identified_plugin = detect_plugins(html, headers, verbose=verbose)
|
identified_plugin = detect_plugins(html, headers, verbose=verbose)
|
||||||
if identified_plugin is not None:
|
if identified_plugin is not None:
|
||||||
for plugin in identified_plugin:
|
for plugin in identified_plugin:
|
||||||
if show_description:
|
if show_description:
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"possible plugin identified as '{}' (description: '{}')...".format(
|
"possible plugin identified as '{}' (description: '{}')".format(
|
||||||
plugin[0], plugin[1]
|
plugin[0], plugin[1]
|
||||||
), level=25
|
), level=25
|
||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"possible plugin identified as '{}'...".format(
|
"possible plugin identified as '{}'".format(
|
||||||
plugin[0]
|
plugin[0]
|
||||||
), level=25
|
), level=25
|
||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"no known plugins identified on target...", level=30
|
"no known plugins identified on target", level=30
|
||||||
))
|
))
|
||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
"loading XML data...", level=10
|
"loading XML data", level=10
|
||||||
))
|
))
|
||||||
comparable_headers = load_xml_data(HEADER_XML_DATA)
|
comparable_headers = load_xml_data(HEADER_XML_DATA)
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"attempting to get request headers for '{}'...".format(url.strip())
|
"attempting to get request headers for '{}'".format(url.strip())
|
||||||
))
|
))
|
||||||
try:
|
try:
|
||||||
found_headers = load_headers(url, req)
|
found_headers = load_headers(url, req)
|
||||||
|
|
@ -331,31 +337,56 @@ def main_header_check(url, **kwargs):
|
||||||
found_headers = None
|
found_headers = None
|
||||||
else:
|
else:
|
||||||
logger.exception(set_color(
|
logger.exception(set_color(
|
||||||
"Zeus has hit an unexpected error and cannot continue '{}'...".format(e), level=50
|
"Zeus has hit an unexpected error and cannot continue '{}'".format(e), level=50
|
||||||
))
|
))
|
||||||
request_issue_creation()
|
request_issue_creation()
|
||||||
|
|
||||||
if found_headers is not None:
|
if found_headers is not None:
|
||||||
if verbose:
|
if verbose:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
"fetched {}...".format(found_headers), level=10
|
"fetched {}".format(found_headers), level=10
|
||||||
))
|
))
|
||||||
headers_established = [str(h) for h in compare_headers(found_headers, comparable_headers)]
|
headers_established = [str(h) for h in compare_headers(found_headers, comparable_headers)]
|
||||||
for key in definition.iterkeys():
|
for key in definition.iterkeys():
|
||||||
if any(key in h.lower() for h in headers_established):
|
if any(key in h.lower() for h in headers_established):
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"provided target has {}...".format(definition[key][0]), level=30
|
"provided target has {}".format(definition[key][0]), level=30
|
||||||
))
|
))
|
||||||
for key in found_headers.iterkeys():
|
for key in found_headers.iterkeys():
|
||||||
protection[key] = found_headers[key]
|
protection[key] = found_headers[key]
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"writing found headers to log file...", level=25
|
"writing found headers to log file", level=25
|
||||||
))
|
))
|
||||||
return write_to_log_file(protection, HEADER_RESULT_PATH, HEADERS_FILENAME.format(replace_http(url)))
|
return write_to_log_file(protection, HEADER_RESULT_PATH, HEADERS_FILENAME.format(replace_http(url)))
|
||||||
else:
|
else:
|
||||||
logger.error(set_color(
|
logger.error(set_color(
|
||||||
"unable to retrieve headers for site '{}'...".format(url.strip()), level=40
|
"unable to retrieve headers for site '{}'".format(url.strip()), level=40
|
||||||
|
))
|
||||||
|
except ConnectionError:
|
||||||
|
attempts = attempts - 1
|
||||||
|
if attempts == 0:
|
||||||
|
return False
|
||||||
|
logger.warning(set_color(
|
||||||
|
"target actively refused the connection, sleeping for {}s and retrying the request".format(
|
||||||
|
default_sleep_time
|
||||||
|
), level=30
|
||||||
|
))
|
||||||
|
time.sleep(default_sleep_time)
|
||||||
|
main_header_check(
|
||||||
|
url, proxy=proxy, agent=agent, xforward=xforward, show_description=show_description,
|
||||||
|
identify_plugins=identify_plugins, identify_waf=identify_waf, verbose=verbose,
|
||||||
|
attempts=attempts
|
||||||
|
)
|
||||||
|
except ReadTimeout:
|
||||||
|
logger.error(set_color(
|
||||||
|
"meta-data retrieval failed due to target URL timing out, skipping", level=40
|
||||||
))
|
))
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
if not pause():
|
if not pause():
|
||||||
shutdown()
|
shutdown()
|
||||||
|
except Exception as e:
|
||||||
|
logger.exception(set_color(
|
||||||
|
"meta-data retrieval failed with unexpected error '{}'".format(
|
||||||
|
str(e)
|
||||||
|
), level=50
|
||||||
|
))
|
||||||
21
lib/plugins/clipbucket.py
Normal file
21
lib/plugins/clipbucket.py
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
__product__ = "ClipBucket"
|
||||||
|
__description__ = (
|
||||||
|
"ClipBucket is an Open Source and freely downloadable PHP "
|
||||||
|
"script that will let you start your own Video Sharing website"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def search(html, **kwargs):
|
||||||
|
html = str(html)
|
||||||
|
plugin_detection_schema = (
|
||||||
|
re.compile(r"<.\S+.clipbucket", re.I),
|
||||||
|
re.compile(r"content.[\'\"]clipbucket", re.I),
|
||||||
|
re.compile(r"http(s)?.//(www.)?clip.bucket.com", re.I),
|
||||||
|
re.compile(r"http(s)?.//(www.)?clipbucket.com", re.I),
|
||||||
|
)
|
||||||
|
for plugin in plugin_detection_schema:
|
||||||
|
if plugin.search(html) is not None:
|
||||||
|
return True
|
||||||
19
lib/plugins/moodle.py
Normal file
19
lib/plugins/moodle.py
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
__product__ = "Moodle"
|
||||||
|
__description__ = (
|
||||||
|
"Moodle is an opensource educational software written in PHP"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def search(html, **kwargs):
|
||||||
|
html = str(html)
|
||||||
|
plugin_detection_schema = (
|
||||||
|
re.compile(r".moodle.", re.I),
|
||||||
|
re.compile(r".moodlesession.", re.I),
|
||||||
|
re.compile(r".php.moodlesession.(\w+)?(\d+)?", re.I)
|
||||||
|
)
|
||||||
|
for plugin in plugin_detection_schema:
|
||||||
|
if plugin.search(html) is not None:
|
||||||
|
return True
|
||||||
18
lib/plugins/mssqlreportmanager.py
Normal file
18
lib/plugins/mssqlreportmanager.py
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
__product__ = "Microsoft SQL Report Manager"
|
||||||
|
__description__ = (
|
||||||
|
"Microsoft SQL Server Report Manager - web-based report access and management tool"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def search(html, **kwargs):
|
||||||
|
html = str(html)
|
||||||
|
plugin_detection_schema = (
|
||||||
|
re.compile(r"content.[\'\"]?microsoft.sql.server.report", re.I),
|
||||||
|
re.compile(r"microsoft.sql.server.report.manager", re.I)
|
||||||
|
)
|
||||||
|
for plugin in plugin_detection_schema:
|
||||||
|
if plugin.search(html) is not None:
|
||||||
|
return True
|
||||||
|
|
@ -11,6 +11,6 @@ def tamper(payload, **kwargs):
|
||||||
if warning:
|
if warning:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"base64 tamper scripts may increase the possibility of not finding vulnerabilities "
|
"base64 tamper scripts may increase the possibility of not finding vulnerabilities "
|
||||||
"in otherwise vulnerable sites...", level=30
|
"in otherwise vulnerable sites", level=30
|
||||||
))
|
))
|
||||||
return base64.b64encode(payload)
|
return base64.b64encode(payload)
|
||||||
|
|
@ -12,7 +12,7 @@ def tamper(payload, **kwargs):
|
||||||
if warning:
|
if warning:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"enclosing brackets is meant to be used as an obfuscation "
|
"enclosing brackets is meant to be used as an obfuscation "
|
||||||
"against an already valid vulnerable site...", level=30
|
"against an already valid vulnerable site", level=30
|
||||||
))
|
))
|
||||||
|
|
||||||
to_enclose = string.digits
|
to_enclose = string.digits
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ def tamper(payload, **kwargs):
|
||||||
warning = kwargs.get("warning", True)
|
warning = kwargs.get("warning", True)
|
||||||
if warning:
|
if warning:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"hex tamper scripts may increase the risk of false positives...", level=30
|
"hex tamper scripts may increase the risk of false positives", level=30
|
||||||
))
|
))
|
||||||
retval = hex(hash(payload))
|
retval = hex(hash(payload))
|
||||||
if "-" in str(retval):
|
if "-" in str(retval):
|
||||||
|
|
|
||||||
29
lib/tamper_scripts/obfuscateentity_encode.py
Normal file
29
lib/tamper_scripts/obfuscateentity_encode.py
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
from lib.core.settings import (
|
||||||
|
logger,
|
||||||
|
set_color
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def tamper(payload, **kwargs):
|
||||||
|
warning = kwargs.get("warning", True)
|
||||||
|
|
||||||
|
if warning:
|
||||||
|
logger.warning(set_color(
|
||||||
|
"obfuscating payloads by their entity encoding equivalent may increase the "
|
||||||
|
"risk of false positives", level=30
|
||||||
|
))
|
||||||
|
|
||||||
|
skip = ";"
|
||||||
|
encoding_schema = {
|
||||||
|
" ": " ", "<": "<", ">": ">",
|
||||||
|
"&": "&", '"': """, "'": "'",
|
||||||
|
}
|
||||||
|
retval = ""
|
||||||
|
for char in str(payload):
|
||||||
|
if char in encoding_schema.iterkeys():
|
||||||
|
retval += encoding_schema[char]
|
||||||
|
elif char not in encoding_schema.iterkeys() and char != skip:
|
||||||
|
retval += char
|
||||||
|
else:
|
||||||
|
retval += char
|
||||||
|
return retval
|
||||||
|
|
@ -10,7 +10,7 @@ def tamper(payload, **kwargs):
|
||||||
if warning:
|
if warning:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"obfuscating the payloads by ordinal equivalents may increase the risk "
|
"obfuscating the payloads by ordinal equivalents may increase the risk "
|
||||||
"of false positives...", level=30
|
"of false positives", level=30
|
||||||
))
|
))
|
||||||
|
|
||||||
retval = ""
|
retval = ""
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ def tamper(payload, **kwargs):
|
||||||
if warning:
|
if warning:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"NULL encoding tamper scripts may increase the possibility of not finding vulnerabilities "
|
"NULL encoding tamper scripts may increase the possibility of not finding vulnerabilities "
|
||||||
"in otherwise vulnerable sites...", level=30
|
"in otherwise vulnerable sites", level=30
|
||||||
))
|
))
|
||||||
|
|
||||||
retval = ""
|
retval = ""
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ def request_issue_creation():
|
||||||
if not lib.core.settings.get_md5sum():
|
if not lib.core.settings.get_md5sum():
|
||||||
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
||||||
"it appears that your checksums did not match, therefore it is assumed "
|
"it appears that your checksums did not match, therefore it is assumed "
|
||||||
"that you have edited some of the code, issue request denied...", level=50
|
"that you have edited some of the code, issue request denied", level=50
|
||||||
))
|
))
|
||||||
lib.core.common.shutdown()
|
lib.core.common.shutdown()
|
||||||
|
|
||||||
|
|
@ -49,18 +49,18 @@ def request_issue_creation():
|
||||||
)
|
)
|
||||||
if question.lower().startswith("n"):
|
if question.lower().startswith("n"):
|
||||||
lib.core.settings.logger.error(lib.core.settings.set_color(
|
lib.core.settings.logger.error(lib.core.settings.set_color(
|
||||||
"Zeus has experienced an internal error and cannot continue, shutting down...", level=40
|
"Zeus has experienced an internal error and cannot continue, shutting down", level=40
|
||||||
))
|
))
|
||||||
lib.core.common.shutdown()
|
lib.core.common.shutdown()
|
||||||
|
|
||||||
lib.core.settings.fix_log_file()
|
lib.core.settings.fix_log_file()
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"Zeus got an unexpected error and will automatically create an issue for this error, please wait..."
|
"Zeus got an unexpected error and will automatically create an issue for this error, please wait"
|
||||||
))
|
))
|
||||||
|
|
||||||
def __extract_stacktrace(file_data):
|
def __extract_stacktrace(file_data):
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"extracting traceback from log file..."
|
"extracting traceback from log file"
|
||||||
))
|
))
|
||||||
retval, buff_mode, _buffer = [], False, ""
|
retval, buff_mode, _buffer = [], False, ""
|
||||||
with open(file_data, "r+") as log:
|
with open(file_data, "r+") as log:
|
||||||
|
|
@ -73,19 +73,19 @@ def request_issue_creation():
|
||||||
_buffer = ""
|
_buffer = ""
|
||||||
if buff_mode:
|
if buff_mode:
|
||||||
if len(line) > 400:
|
if len(line) > 400:
|
||||||
line = line[:400] + "...\n"
|
line = line[:400] + "\n"
|
||||||
_buffer += line
|
_buffer += line
|
||||||
return "".join(retval)
|
return "".join(retval)
|
||||||
|
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"getting authorization..."
|
"getting authorization"
|
||||||
))
|
))
|
||||||
|
|
||||||
token = lib.core.settings.get_token(lib.core.settings.GITHUB_AUTH_PATH)
|
token = lib.core.settings.get_token(lib.core.settings.GITHUB_AUTH_PATH)
|
||||||
|
|
||||||
current_log_file = lib.core.settings.get_latest_log_file(lib.core.settings.CURRENT_LOG_FILE_PATH)
|
current_log_file = lib.core.settings.get_latest_log_file(lib.core.settings.CURRENT_LOG_FILE_PATH)
|
||||||
stacktrace = __extract_stacktrace(current_log_file)
|
stacktrace = __extract_stacktrace(current_log_file)
|
||||||
identifier = lib.core.settings.create_identifier()
|
identifier = lib.core.settings.create_identifier(stacktrace)
|
||||||
issue_title = "Unhandled exception ({})".format(identifier)
|
issue_title = "Unhandled exception ({})".format(identifier)
|
||||||
ff_version = lib.core.settings.get_browser_version()
|
ff_version = lib.core.settings.get_browser_version()
|
||||||
log_file_information = lib.core.settings.tails(current_log_file)
|
log_file_information = lib.core.settings.tails(current_log_file)
|
||||||
|
|
@ -95,7 +95,7 @@ def request_issue_creation():
|
||||||
"body": "Zeus version:\n`{}`\n\n"
|
"body": "Zeus version:\n`{}`\n\n"
|
||||||
"Firefox version:\n`{}`\n\n"
|
"Firefox version:\n`{}`\n\n"
|
||||||
"Geckodriver version:\n`{}`\n\n"
|
"Geckodriver version:\n`{}`\n\n"
|
||||||
"Error info:\n```{}````\n\n"
|
"Error info:\n```{}```\n\n"
|
||||||
"Running details:\n`{}`\n\n"
|
"Running details:\n`{}`\n\n"
|
||||||
"Commands used:\n`{}`\n\n"
|
"Commands used:\n`{}`\n\n"
|
||||||
"Log file info:\n```{}```".format(
|
"Log file info:\n```{}```".format(
|
||||||
|
|
@ -121,12 +121,12 @@ def request_issue_creation():
|
||||||
urllib2.urlopen(req, timeout=10).read()
|
urllib2.urlopen(req, timeout=10).read()
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"issue has been created successfully with the following name '{}', your unique identifier "
|
"issue has been created successfully with the following name '{}', your unique identifier "
|
||||||
"for this issue is '{}' and the URL to your issue is '{}'...".format(
|
"for this issue is '{}' and the URL to your issue is '{}'".format(
|
||||||
issue_title, identifier, find_url(identifier)
|
issue_title, identifier, find_url(identifier)
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
lib.core.settings.logger.exception(lib.core.settings.set_color(
|
lib.core.settings.logger.exception(lib.core.settings.set_color(
|
||||||
"failed to auto create the issue, got exception '{}', "
|
"failed to auto create the issue, got exception '{}', "
|
||||||
"you may manually create an issue...".format(e), level=50
|
"you may manually create an issue".format(e), level=50
|
||||||
))
|
))
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,4 @@
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
reload(sys)
|
|
||||||
sys.setdefaultencoding("utf-8") # this will take care of most of the Unicode errors.
|
|
||||||
|
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
|
@ -20,7 +17,7 @@ class Blackwidow(object):
|
||||||
def __init__(self, url, user_agent=None, proxy=None, forward=None):
|
def __init__(self, url, user_agent=None, proxy=None, forward=None):
|
||||||
self.url = url
|
self.url = url
|
||||||
self.forward = forward or None
|
self.forward = forward or None
|
||||||
self.proxy = lib.core.settings.proxy_string_to_dict(proxy) or None
|
self.proxy = proxy
|
||||||
self.user_agent = user_agent or lib.core.settings.DEFAULT_USER_AGENT
|
self.user_agent = user_agent or lib.core.settings.DEFAULT_USER_AGENT
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
@ -39,7 +36,8 @@ class Blackwidow(object):
|
||||||
make sure the connection is good before you continue
|
make sure the connection is good before you continue
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# verify=False will take care of SSLErrors
|
# we'll skip SSL verification to avoid any SSLErrors that might
|
||||||
|
# arise, we won't really need it with this anyways
|
||||||
attempt, status, _, _ = lib.core.common.get_page(
|
attempt, status, _, _ = lib.core.common.get_page(
|
||||||
self.url, agent=self.user_agent, xforward=self.forward, skip_verf=True,
|
self.url, agent=self.user_agent, xforward=self.forward, skip_verf=True,
|
||||||
proxy=self.proxy
|
proxy=self.proxy
|
||||||
|
|
@ -55,14 +53,14 @@ class Blackwidow(object):
|
||||||
else:
|
else:
|
||||||
info_msg += ""
|
info_msg += ""
|
||||||
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
||||||
"provided website '{}' is refusing connection{}...".format(
|
"provided website '{}' is refusing connection{}".format(
|
||||||
self.url, info_msg
|
self.url, info_msg
|
||||||
), level=50
|
), level=50
|
||||||
))
|
))
|
||||||
lib.core.common.shutdown()
|
lib.core.common.shutdown()
|
||||||
else:
|
else:
|
||||||
lib.core.settings.logger.exception(lib.core.settings.set_color(
|
lib.core.settings.logger.exception(lib.core.settings.set_color(
|
||||||
"failed to connect to '{}' received error '{}'...".format(
|
"failed to connect to '{}' received error '{}'".format(
|
||||||
self.url, e
|
self.url, e
|
||||||
), level=50
|
), level=50
|
||||||
))
|
))
|
||||||
|
|
@ -106,27 +104,27 @@ def blackwidow_main(url, **kwargs):
|
||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
||||||
"settings user-agent to '{}'...".format(agent), level=10
|
"settings user-agent to '{}'".format(agent), level=10
|
||||||
))
|
))
|
||||||
if proxy is not None:
|
if proxy is not None:
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
||||||
"running behind proxy '{}'...".format(proxy), level=10
|
"running behind proxy '{}'".format(proxy), level=10
|
||||||
))
|
))
|
||||||
lib.core.settings.create_dir("{}/{}".format(os.getcwd(), "log/blackwidow-log"))
|
lib.core.settings.create_dir("{}/{}".format(os.getcwd(), "log/blackwidow-log"))
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"starting blackwidow on '{}'...".format(url)
|
"starting blackwidow on '{}'".format(url)
|
||||||
))
|
))
|
||||||
crawler = Blackwidow(url, user_agent=agent, proxy=proxy, forward=forward)
|
crawler = Blackwidow(url, user_agent=agent, proxy=proxy, forward=forward)
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
||||||
"testing connection to the URL...", level=10
|
"testing connection to the URL", level=10
|
||||||
))
|
))
|
||||||
test_code = crawler.test_connection()
|
test_code = crawler.test_connection()
|
||||||
if not test_code[0] == "ok":
|
if not test_code[0] == "ok":
|
||||||
error_msg = (
|
error_msg = (
|
||||||
"connection test failed with status code: {}, reason: '{}'. "
|
"connection test failed with status code: {}, reason: '{}'. "
|
||||||
"test connection needs to pass, try a different link..."
|
"test connection needs to pass, try a different link"
|
||||||
)
|
)
|
||||||
for error_code in lib.core.common.STATUS_CODES.keys():
|
for error_code in lib.core.common.STATUS_CODES.keys():
|
||||||
if error_code == test_code[1]:
|
if error_code == test_code[1]:
|
||||||
|
|
@ -144,15 +142,15 @@ def blackwidow_main(url, **kwargs):
|
||||||
lib.core.common.shutdown()
|
lib.core.common.shutdown()
|
||||||
else:
|
else:
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"connection test succeeded, continuing...", level=25
|
"connection test succeeded, continuing", level=25
|
||||||
))
|
))
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"crawling given URL '{}' for links...".format(url)
|
"crawling given URL '{}' for links".format(url)
|
||||||
))
|
))
|
||||||
found = crawler.scrape_page_for_links(url)
|
found = crawler.scrape_page_for_links(url)
|
||||||
if len(found) > 0:
|
if len(found) > 0:
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"found a total of {} links from given URL '{}'...".format(
|
"found a total of {} links from given URL '{}'".format(
|
||||||
len(found), url
|
len(found), url
|
||||||
), level=25
|
), level=25
|
||||||
))
|
))
|
||||||
|
|
@ -160,5 +158,5 @@ def blackwidow_main(url, **kwargs):
|
||||||
filename=lib.core.settings.BLACKWIDOW_FILENAME)
|
filename=lib.core.settings.BLACKWIDOW_FILENAME)
|
||||||
else:
|
else:
|
||||||
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
lib.core.settings.logger.fatal(lib.core.settings.set_color(
|
||||||
"did not find any usable links from '{}'...".format(url), level=50
|
"did not find any usable links from '{}'".format(url), level=50
|
||||||
))
|
))
|
||||||
|
|
@ -128,7 +128,7 @@ class SetBrowser(object):
|
||||||
try:
|
try:
|
||||||
if not self.tor:
|
if not self.tor:
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"setting the browser..."
|
"setting the browser"
|
||||||
))
|
))
|
||||||
profile.set_preference("general.useragent.override", self.agent)
|
profile.set_preference("general.useragent.override", self.agent)
|
||||||
browser = webdriver.Firefox(profile, proxy=self.__set_proxy())
|
browser = webdriver.Firefox(profile, proxy=self.__set_proxy())
|
||||||
|
|
@ -137,7 +137,7 @@ class SetBrowser(object):
|
||||||
browser = webdriver.Firefox(profile, proxy=self.__set_proxy())
|
browser = webdriver.Firefox(profile, proxy=self.__set_proxy())
|
||||||
else:
|
else:
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"setting the Tor browser emulation..."
|
"setting the Tor browser emulation"
|
||||||
))
|
))
|
||||||
profile = self.__tor_browser_emulation(profile)
|
profile = self.__tor_browser_emulation(profile)
|
||||||
browser = webdriver.Firefox(profile)
|
browser = webdriver.Firefox(profile)
|
||||||
|
|
|
||||||
|
|
@ -109,18 +109,18 @@ def get_pgp_keys(url_list, query, attribute="pre", **kwargs):
|
||||||
identity_matcher = re.compile(r"\bbegin.pgp.public.key.block", re.I)
|
identity_matcher = re.compile(r"\bbegin.pgp.public.key.block", re.I)
|
||||||
amount_left = len(url_list)
|
amount_left = len(url_list)
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"checking a maximum of {} PGP keys...".format(amount_to_search)
|
"checking a maximum of {} PGP keys".format(amount_to_search)
|
||||||
))
|
))
|
||||||
for i, url in enumerate(url_list, start=1):
|
for i, url in enumerate(url_list, start=1):
|
||||||
if i >= amount_to_search:
|
if i >= amount_to_search:
|
||||||
break
|
break
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
||||||
"checking '{}'...".format(url), level=10
|
"checking '{}'".format(url), level=10
|
||||||
))
|
))
|
||||||
if i % 25 == 0:
|
if i % 25 == 0:
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"currently checking PGP key #{}, {} left to check ({} total found)...".format(
|
"currently checking PGP key #{}, {} left to check ({} total found)".format(
|
||||||
i, amount_to_search - i, amount_left
|
i, amount_to_search - i, amount_left
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
@ -140,7 +140,7 @@ def get_pgp_keys(url_list, query, attribute="pre", **kwargs):
|
||||||
extracted_keys.add(context)
|
extracted_keys.add(context)
|
||||||
except ReadTimeout:
|
except ReadTimeout:
|
||||||
lib.core.settings.logger.error(lib.core.settings.set_color(
|
lib.core.settings.logger.error(lib.core.settings.set_color(
|
||||||
"PGP key failed connection, assuming no good and skipping...", level=40
|
"PGP key failed connection, assuming no good and skipping", level=40
|
||||||
))
|
))
|
||||||
for i, k in enumerate(extracted_keys):
|
for i, k in enumerate(extracted_keys):
|
||||||
pgp_key = str(k).split("<{}>".format(attribute)) # split the string by the tag
|
pgp_key = str(k).split("<{}>".format(attribute)) # split the string by the tag
|
||||||
|
|
@ -164,7 +164,7 @@ def pgp_main(query, verbose=False):
|
||||||
except Exception:
|
except Exception:
|
||||||
query = query
|
query = query
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"searching public PGP files with given query '{}'...".format(query)
|
"searching public PGP files with given query '{}'".format(query)
|
||||||
))
|
))
|
||||||
try:
|
try:
|
||||||
html = obtain_html(
|
html = obtain_html(
|
||||||
|
|
@ -172,25 +172,25 @@ def pgp_main(query, verbose=False):
|
||||||
)
|
)
|
||||||
except (Exception, ReadTimeout):
|
except (Exception, ReadTimeout):
|
||||||
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
||||||
"connection failed, assuming no PGP keys...", level=30
|
"connection failed, assuming no PGP keys", level=30
|
||||||
))
|
))
|
||||||
html = None
|
html = None
|
||||||
if html is not None:
|
if html is not None:
|
||||||
urls = gather_urls(html)
|
urls = gather_urls(html)
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"found a total of {} URLs...".format(len(urls))
|
"found a total of {} URLs".format(len(urls))
|
||||||
))
|
))
|
||||||
if verbose:
|
if verbose:
|
||||||
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
lib.core.settings.logger.debug(lib.core.settings.set_color(
|
||||||
"found a '{}'...".format(urls), level=10
|
"found a '{}'".format(urls), level=10
|
||||||
))
|
))
|
||||||
lib.core.settings.logger.info(lib.core.settings.set_color(
|
lib.core.settings.logger.info(lib.core.settings.set_color(
|
||||||
"gathering PGP key(s) and writing to a file...", level=25
|
"gathering PGP key(s) and writing to a file", level=25
|
||||||
))
|
))
|
||||||
return get_pgp_keys(urls, query, verbose=verbose)
|
return get_pgp_keys(urls, query, verbose=verbose)
|
||||||
else:
|
else:
|
||||||
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
lib.core.settings.logger.warning(lib.core.settings.set_color(
|
||||||
"did not find anything using query '{}'...".format(query), level=30
|
"did not find anything using query '{}'".format(query), level=30
|
||||||
))
|
))
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
if not lib.core.common.pause():
|
if not lib.core.common.pause():
|
||||||
|
|
|
||||||
|
|
@ -75,20 +75,20 @@ def get_urls(query, url, verbose=False, **kwargs):
|
||||||
batch = kwargs.get("batch", False)
|
batch = kwargs.get("batch", False)
|
||||||
xforward = kwargs.get("xforward", False)
|
xforward = kwargs.get("xforward", False)
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"setting up virtual display to hide the browser..."
|
"setting up virtual display to hide the browser"
|
||||||
))
|
))
|
||||||
ff_display = Display(visible=0, size=(800, 600))
|
ff_display = Display(visible=0, size=(800, 600))
|
||||||
ff_display.start()
|
ff_display.start()
|
||||||
browser = var.search.SetBrowser(agent=user_agent, proxy=proxy, tor=tor, xforward=xforward).set_browser()
|
browser = var.search.SetBrowser(agent=user_agent, proxy=proxy, tor=tor, xforward=xforward).set_browser()
|
||||||
logger.info(set_color("browser will open shortly...", level=25))
|
logger.info(set_color("browser will open shortly", level=25))
|
||||||
browser.get(url)
|
browser.get(url)
|
||||||
if verbose:
|
if verbose:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
"searching search engine for the 'q' element (search button)...", level=10
|
"searching search engine for the 'q' element (search button)", level=10
|
||||||
))
|
))
|
||||||
search = browser.find_element_by_name('q')
|
search = browser.find_element_by_name('q')
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"searching search engine using query '{}'...".format(query)
|
"searching search engine using query '{}'".format(query)
|
||||||
))
|
))
|
||||||
try:
|
try:
|
||||||
# enter the text you want to search and hit enter
|
# enter the text you want to search and hit enter
|
||||||
|
|
@ -98,31 +98,35 @@ def get_urls(query, url, verbose=False, **kwargs):
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
else:
|
else:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"sleep time has been increased to 10 seconds due to tor being used...", level=30
|
"sleep time has been increased to 10 seconds due to tor being used", level=30
|
||||||
))
|
))
|
||||||
time.sleep(10)
|
time.sleep(10)
|
||||||
except ElementNotInteractableException:
|
except ElementNotInteractableException:
|
||||||
# get rid of the popup box and hit enter after entering the text to search
|
# get rid of the popup box and hit enter after entering the text to search
|
||||||
browser.execute_script("document.querySelectorAll('label.boxed')[1].click()")
|
try:
|
||||||
|
for _ in range(5):
|
||||||
|
browser.execute_script("document.querySelectorAll('label.boxed')[{}].click()".format(_))
|
||||||
search.send_keys(query)
|
search.send_keys(query)
|
||||||
search.send_keys(Keys.RETURN)
|
search.send_keys(Keys.RETURN)
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
logger.error(set_color(
|
logger.error(set_color(
|
||||||
"your query '{}' appears to have unicode characters in it, selenium is not "
|
"your query '{}' appears to have unicode characters in it, selenium is not "
|
||||||
"properly formatted to handle unicode characters, this dork will be skipped...".format(
|
"properly formatted to handle unicode characters, this dork will be skipped".format(
|
||||||
query
|
query
|
||||||
), level=40
|
), level=40
|
||||||
))
|
))
|
||||||
if verbose:
|
if verbose:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
"obtaining URL from selenium..."
|
"obtaining URL from selenium"
|
||||||
))
|
))
|
||||||
try:
|
try:
|
||||||
retval = browser.current_url
|
retval = browser.current_url
|
||||||
except UnexpectedAlertPresentException:
|
except UnexpectedAlertPresentException:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"alert present, closing...", level=30
|
"alert present, closing", level=30
|
||||||
))
|
))
|
||||||
# discover the alert and close it before continuing
|
# discover the alert and close it before continuing
|
||||||
alert = browser.switch_to.alert
|
alert = browser.switch_to.alert
|
||||||
|
|
@ -131,7 +135,7 @@ def get_urls(query, url, verbose=False, **kwargs):
|
||||||
# if you have been IP banned, we'll extract the URL from it
|
# if you have been IP banned, we'll extract the URL from it
|
||||||
if IP_BAN_REGEX.search(retval) is not None:
|
if IP_BAN_REGEX.search(retval) is not None:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"it appears that Google is attempting to block your IP address, attempting bypass...", level=30
|
"it appears that Google is attempting to block your IP address, attempting bypass", level=30
|
||||||
))
|
))
|
||||||
try:
|
try:
|
||||||
retval = URLParser(retval).extract_ip_ban_url()
|
retval = URLParser(retval).extract_ip_ban_url()
|
||||||
|
|
@ -155,7 +159,7 @@ def get_urls(query, url, verbose=False, **kwargs):
|
||||||
write_to_log_file(retval, EXTRACTED_URL_LOG, EXTRACTED_URL_FILENAME)
|
write_to_log_file(retval, EXTRACTED_URL_LOG, EXTRACTED_URL_FILENAME)
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"it is advised to extract the URL's from the produced URL written to the above "
|
"it is advised to extract the URL's from the produced URL written to the above "
|
||||||
"(IE open the log, copy the url into firefox)...".format(retval)
|
"(IE open the log, copy the url into firefox)".format(retval)
|
||||||
))
|
))
|
||||||
shutdown()
|
shutdown()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
@ -165,7 +169,7 @@ def get_urls(query, url, verbose=False, **kwargs):
|
||||||
ff_display.stop()
|
ff_display.stop()
|
||||||
logger.exception(set_color(
|
logger.exception(set_color(
|
||||||
"zeus was unable to extract the correct URL from the ban URL '{}', "
|
"zeus was unable to extract the correct URL from the ban URL '{}', "
|
||||||
"got exception '{}'...".format(
|
"got exception '{}'".format(
|
||||||
unquote(retval), e
|
unquote(retval), e
|
||||||
), level=50
|
), level=50
|
||||||
))
|
))
|
||||||
|
|
@ -173,7 +177,7 @@ def get_urls(query, url, verbose=False, **kwargs):
|
||||||
shutdown()
|
shutdown()
|
||||||
if verbose:
|
if verbose:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
"found current URL from selenium browser...", level=10
|
"found current URL from selenium browser", level=10
|
||||||
))
|
))
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"closing the browser and continuing process.."
|
"closing the browser and continuing process.."
|
||||||
|
|
@ -201,31 +205,31 @@ def parse_search_results(query, url_to_search, verbose=False, **kwargs):
|
||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
"parsing blacklist...", level=10
|
"parsing blacklist", level=10
|
||||||
))
|
))
|
||||||
parse_blacklist(query, BLACKLIST_FILE_PATH, batch=batch)
|
parse_blacklist(query, BLACKLIST_FILE_PATH, batch=batch)
|
||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
"checking for user-agent and proxy configuration...", level=10
|
"checking for user-agent and proxy configuration", level=10
|
||||||
))
|
))
|
||||||
|
|
||||||
if not parse_webcache and "google" in url_to_search:
|
if not parse_webcache and "google" in url_to_search:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"will not parse webcache URL's (to parse webcache pass -W)...", level=30
|
"will not parse webcache URL's (to parse webcache pass -W)", level=30
|
||||||
))
|
))
|
||||||
if not pull_all:
|
if not pull_all:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"only pulling URLs with GET(query) parameters (to pull all URL's pass -E)...", level=30
|
"only pulling URLs with GET(query) parameters (to pull all URL's pass -E)", level=30
|
||||||
))
|
))
|
||||||
|
|
||||||
user_agent_info = "adjusting user-agent header to {}..."
|
user_agent_info = "adjusting user-agent header to {}"
|
||||||
if user_agent is not DEFAULT_USER_AGENT:
|
if user_agent is not DEFAULT_USER_AGENT:
|
||||||
user_agent_info = user_agent_info.format(user_agent.strip())
|
user_agent_info = user_agent_info.format(user_agent.strip())
|
||||||
else:
|
else:
|
||||||
user_agent_info = user_agent_info.format("default user agent '{}'".format(DEFAULT_USER_AGENT))
|
user_agent_info = user_agent_info.format("default user agent '{}'".format(DEFAULT_USER_AGENT))
|
||||||
|
|
||||||
proxy_string_info = "setting proxy to {}..."
|
proxy_string_info = "setting proxy to {}"
|
||||||
if proxy_string is not None:
|
if proxy_string is not None:
|
||||||
proxy_string = proxy_string_to_dict(proxy_string)
|
proxy_string = proxy_string_to_dict(proxy_string)
|
||||||
proxy_string_info = proxy_string_info.format(
|
proxy_string_info = proxy_string_info.format(
|
||||||
|
|
@ -236,13 +240,13 @@ def parse_search_results(query, url_to_search, verbose=False, **kwargs):
|
||||||
"tor proxy settings"
|
"tor proxy settings"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
proxy_string_info = "no proxy configuration detected..."
|
proxy_string_info = "no proxy configuration detected"
|
||||||
|
|
||||||
if forward_for:
|
if forward_for:
|
||||||
ip_to_use = (create_random_ip(), create_random_ip(), create_random_ip())
|
ip_to_use = (create_random_ip(), create_random_ip(), create_random_ip())
|
||||||
if verbose:
|
if verbose:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
"random IP addresses generated for headers '{}'...".format(ip_to_use), level=10
|
"random IP addresses generated for headers '{}'".format(ip_to_use), level=10
|
||||||
))
|
))
|
||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
|
|
@ -256,7 +260,7 @@ def parse_search_results(query, url_to_search, verbose=False, **kwargs):
|
||||||
HTTP_HEADER.USER_AGENT: user_agent
|
HTTP_HEADER.USER_AGENT: user_agent
|
||||||
}
|
}
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"attempting to gather query URL..."
|
"attempting to gather query URL"
|
||||||
))
|
))
|
||||||
try:
|
try:
|
||||||
query_url = get_urls(
|
query_url = get_urls(
|
||||||
|
|
@ -268,17 +272,17 @@ def parse_search_results(query, url_to_search, verbose=False, **kwargs):
|
||||||
logger.fatal(set_color(
|
logger.fatal(set_color(
|
||||||
"firefox was not found in the default location on your system, "
|
"firefox was not found in the default location on your system, "
|
||||||
"check your installation and make sure it is in /usr/lib, if you "
|
"check your installation and make sure it is in /usr/lib, if you "
|
||||||
"find it there, restart your system and try again...", level=50
|
"find it there, restart your system and try again", level=50
|
||||||
))
|
))
|
||||||
elif "connection refused" in str(e).lower():
|
elif "connection refused" in str(e).lower():
|
||||||
logger.fatal(set_color(
|
logger.fatal(set_color(
|
||||||
"there are to many sessions of firefox opened and selenium cannot "
|
"there are to many sessions of firefox opened and selenium cannot "
|
||||||
"create a new one...", level=50
|
"create a new one", level=50
|
||||||
))
|
))
|
||||||
run_fix(
|
run_fix(
|
||||||
"would you like to attempt to auto clean the open sessions",
|
"would you like to attempt to auto clean the open sessions",
|
||||||
"sudo sh {}".format(CLEANUP_TOOL_PATH),
|
"sudo sh {}".format(CLEANUP_TOOL_PATH),
|
||||||
"kill off the open sessions of firefox and re-run Zeus...",
|
"kill off the open sessions of firefox and re-run Zeus",
|
||||||
exit_process=True
|
exit_process=True
|
||||||
)
|
)
|
||||||
elif "Program install error!" in str(e):
|
elif "Program install error!" in str(e):
|
||||||
|
|
@ -289,50 +293,50 @@ def parse_search_results(query, url_to_search, verbose=False, **kwargs):
|
||||||
run_fix(
|
run_fix(
|
||||||
"would you like to attempt to fix this issue automatically",
|
"would you like to attempt to fix this issue automatically",
|
||||||
"sudo sh {}".format(FIX_PROGRAM_INSTALL_PATH),
|
"sudo sh {}".format(FIX_PROGRAM_INSTALL_PATH),
|
||||||
"you can manually try and re-install Xvfb to fix the problem...",
|
"you can manually try and re-install Xvfb to fix the problem",
|
||||||
exit_process=True
|
exit_process=True
|
||||||
)
|
)
|
||||||
elif "Message: Reached error page:" in str(e):
|
elif "Message: Reached error page:" in str(e):
|
||||||
logger.fatal(set_color(
|
logger.fatal(set_color(
|
||||||
"geckodriver has hit an error that usually means it needs to be reinstalled...", level=50
|
"geckodriver has hit an error that usually means it needs to be reinstalled", level=50
|
||||||
))
|
))
|
||||||
question = prompt(
|
question = prompt(
|
||||||
"would you like to attempt a reinstallation of the geckodriver", opts="yN"
|
"would you like to attempt a reinstallation of the geckodriver", opts="yN"
|
||||||
)
|
)
|
||||||
if question.lower().startswith("y"):
|
if question.lower().startswith("y"):
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"rewriting all executed information, path information, and removing geckodriver...", level=30
|
"rewriting all executed information, path information, and removing geckodriver", level=30
|
||||||
))
|
))
|
||||||
rewrite_all_paths()
|
rewrite_all_paths()
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"all paths rewritten, you will be forced to re-install everything next run of Zeus..."
|
"all paths rewritten, you will be forced to re-install everything next run of Zeus"
|
||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
logger.fatal(set_color(
|
logger.fatal(set_color(
|
||||||
"you will need to remove the geckodriver from /usr/bin and reinstall it...", level=50
|
"you will need to remove the geckodriver from /usr/bin and reinstall it", level=50
|
||||||
))
|
))
|
||||||
shutdown()
|
shutdown()
|
||||||
elif "Unable to find a matching set of capabilities" in str(e):
|
elif "Unable to find a matching set of capabilities" in str(e):
|
||||||
logger.fatal(set_color(
|
logger.fatal(set_color(
|
||||||
"it appears that firefox, selenium, and geckodriver are not playing nice with one another...", level=50
|
"it appears that firefox, selenium, and geckodriver are not playing nice with one another", level=50
|
||||||
))
|
))
|
||||||
run_fix(
|
run_fix(
|
||||||
"would you like to attempt to resolve this issue automatically",
|
"would you like to attempt to resolve this issue automatically",
|
||||||
"sudo sh {}".format(REINSTALL_TOOL),
|
"sudo sh {}".format(REINSTALL_TOOL),
|
||||||
("you will need to reinstall firefox to a later version, update selenium, and reinstall the "
|
("you will need to reinstall firefox to a later version, update selenium, and reinstall the "
|
||||||
"geckodriver to continue using Zeus..."),
|
"geckodriver to continue using Zeus"),
|
||||||
exit_process=True
|
exit_process=True
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
logger.exception(set_color(
|
logger.exception(set_color(
|
||||||
"{} failed to gather the URL from search engine, caught exception '{}' "
|
"{} failed to gather the URL from search engine, caught exception '{}' "
|
||||||
"exception has been logged to current log file...".format(
|
"exception has been logged to current log file".format(
|
||||||
os.path.basename(__file__), str(e).strip()), level=50)
|
os.path.basename(__file__), str(e).strip()), level=50)
|
||||||
)
|
)
|
||||||
request_issue_creation()
|
request_issue_creation()
|
||||||
shutdown()
|
shutdown()
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"URL successfully gathered, searching for GET parameters..."
|
"URL successfully gathered, searching for GET parameters"
|
||||||
))
|
))
|
||||||
|
|
||||||
logger.info(set_color(proxy_string_info))
|
logger.info(set_color(proxy_string_info))
|
||||||
|
|
@ -341,7 +345,7 @@ def parse_search_results(query, url_to_search, verbose=False, **kwargs):
|
||||||
req = requests.get(query_url, proxies=proxy_string, params=headers)
|
req = requests.get(query_url, proxies=proxy_string, params=headers)
|
||||||
except ConnectionError:
|
except ConnectionError:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"target machine refused connection, delaying and trying again...", level=30
|
"target machine refused connection, delaying and trying again", level=30
|
||||||
))
|
))
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
req = requests.get(query_url, proxies=proxy_string, params=headers)
|
req = requests.get(query_url, proxies=proxy_string, params=headers)
|
||||||
|
|
@ -365,15 +369,15 @@ def parse_search_results(query, url_to_search, verbose=False, **kwargs):
|
||||||
if verbose:
|
if verbose:
|
||||||
try:
|
try:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
"found '{}'...".format(url.split(splitter)[0]), level=10
|
"found '{}'".format(url.split(splitter)[0]), level=10
|
||||||
))
|
))
|
||||||
except TypeError:
|
except TypeError:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
"found '{}'...".format(str(url).split(splitter)[0]), level=10
|
"found '{}'".format(str(url).split(splitter)[0]), level=10
|
||||||
))
|
))
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
"found '{}...".format(str(url)), level=10
|
"found '{}".format(str(url)), level=10
|
||||||
))
|
))
|
||||||
if url is not None:
|
if url is not None:
|
||||||
retval.add(url.split(splitter)[0])
|
retval.add(url.split(splitter)[0])
|
||||||
|
|
@ -384,12 +388,12 @@ def parse_search_results(query, url_to_search, verbose=False, **kwargs):
|
||||||
if parse_webcache:
|
if parse_webcache:
|
||||||
if "webcache" in url:
|
if "webcache" in url:
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"found a webcache URL, extracting..."
|
"found a webcache URL, extracting"
|
||||||
))
|
))
|
||||||
url = URLParser(url).extract_webcache_url()
|
url = URLParser(url).extract_webcache_url()
|
||||||
if verbose:
|
if verbose:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
"found '{}'...".format(url), level=15
|
"found '{}'".format(url), level=15
|
||||||
))
|
))
|
||||||
true_retval.add(url)
|
true_retval.add(url)
|
||||||
else:
|
else:
|
||||||
|
|
@ -403,18 +407,18 @@ def parse_search_results(query, url_to_search, verbose=False, **kwargs):
|
||||||
amount_of_urls = len(open(file_path).readlines())
|
amount_of_urls = len(open(file_path).readlines())
|
||||||
success_rate = calculate_success(amount_of_urls)
|
success_rate = calculate_success(amount_of_urls)
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"provided query has a {} success rate...".format(success_rate)
|
"provided query has a {} success rate".format(success_rate)
|
||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
logger.fatal(set_color(
|
logger.warning(set_color(
|
||||||
"did not find any URLs with given query '{}' writing query to blacklist...".format(query), level=50
|
"did not find any URLs with given query '{}' writing query to blacklist".format(query), level=50
|
||||||
))
|
))
|
||||||
write_to_log_file(query, BLACKLIST_FILE_PATH, BLACKLIST_FILENAME, blacklist=True)
|
write_to_log_file(query, BLACKLIST_FILE_PATH, BLACKLIST_FILENAME, blacklist=True)
|
||||||
shutdown()
|
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"found a total of {} URLs with given query '{}'...".format(len(true_retval), query)
|
"found a total of {} URLs with given query '{}'".format(len(true_retval), query)
|
||||||
))
|
))
|
||||||
return list(true_retval) if len(true_retval) != 0 else None
|
|
||||||
|
|
||||||
|
|
||||||
def search_multiple_pages(query, link_amount, verbose=False, **kwargs):
|
def search_multiple_pages(query, link_amount, verbose=False, **kwargs):
|
||||||
|
|
@ -431,7 +435,7 @@ def search_multiple_pages(query, link_amount, verbose=False, **kwargs):
|
||||||
search_engine = AUTHORIZED_SEARCH_ENGINES["search-results"]
|
search_engine = AUTHORIZED_SEARCH_ENGINES["search-results"]
|
||||||
|
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"searching multiple pages will not be done on Google...".format(search_engine), level=30
|
"searching multiple pages will not be done on Google".format(search_engine), level=30
|
||||||
))
|
))
|
||||||
|
|
||||||
if not parse_blacklist(query, BLACKLIST_FILE_PATH, batch=batch):
|
if not parse_blacklist(query, BLACKLIST_FILE_PATH, batch=batch):
|
||||||
|
|
@ -455,11 +459,11 @@ def search_multiple_pages(query, link_amount, verbose=False, **kwargs):
|
||||||
while len(retval) <= link_amount:
|
while len(retval) <= link_amount:
|
||||||
if verbose:
|
if verbose:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
"searching page number {}...".format(page_number), level=10
|
"searching page number {}".format(page_number), level=10
|
||||||
))
|
))
|
||||||
if page_number % 10 == 0:
|
if page_number % 10 == 0:
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"currently on page {} of search results...".format(
|
"currently on page {} of search results".format(
|
||||||
page_number
|
page_number
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
@ -481,44 +485,44 @@ def search_multiple_pages(query, link_amount, verbose=False, **kwargs):
|
||||||
page_number += 1
|
page_number += 1
|
||||||
else:
|
else:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"hit max page number {}...".format(MAX_PAGE_NUMBER), level=30
|
"hit max page number {}".format(MAX_PAGE_NUMBER), level=30
|
||||||
))
|
))
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"no more results found for given query '{}'...".format(query), level=30
|
"no more results found for given query '{}'".format(query), level=30
|
||||||
))
|
))
|
||||||
break
|
break
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
logger.error(set_color(
|
logger.error(set_color(
|
||||||
"user aborted, dumping already found URL(s)...", level=40
|
"user aborted, dumping already found URL(s)", level=40
|
||||||
))
|
))
|
||||||
write_to_log_file(retval, URL_LOG_PATH, URL_FILENAME)
|
write_to_log_file(retval, URL_LOG_PATH, URL_FILENAME)
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"found a total of {} URL(s)...".format(len(retval)), level=25
|
"found a total of {} URL(s)".format(len(retval)), level=25
|
||||||
))
|
))
|
||||||
shutdown()
|
shutdown()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(set_color(
|
logger.exception(set_color(
|
||||||
"Zeus ran into an unexpected error '{}'...".format(e), level=50
|
"Zeus ran into an unexpected error '{}'".format(e), level=50
|
||||||
))
|
))
|
||||||
request_issue_creation()
|
request_issue_creation()
|
||||||
shutdown()
|
shutdown()
|
||||||
|
|
||||||
if len(retval) > 0:
|
if len(retval) > 0:
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"a total of {} URL(s) found out of the requested {}...".format(len(retval), link_amount), level=25
|
"a total of {} URL(s) found out of the requested {}".format(len(retval), link_amount), level=25
|
||||||
))
|
))
|
||||||
file_path = write_to_log_file(retval, URL_LOG_PATH, URL_FILENAME)
|
file_path = write_to_log_file(retval, URL_LOG_PATH, URL_FILENAME)
|
||||||
if show_success:
|
if show_success:
|
||||||
amount_of_urls = len(open(file_path).readlines())
|
amount_of_urls = len(open(file_path).readlines())
|
||||||
success_rate = calculate_success(amount_of_urls)
|
success_rate = calculate_success(amount_of_urls)
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"provided query has a {} success rate...".format(success_rate)
|
"provided query has a {} success rate".format(success_rate)
|
||||||
))
|
))
|
||||||
return list(retval)
|
return list(retval)
|
||||||
else:
|
else:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"did not find any links with given query '{}' writing to blacklist...".format(query), level=30
|
"did not find any links with given query '{}' writing to blacklist".format(query), level=30
|
||||||
))
|
))
|
||||||
write_to_log_file(query, BLACKLIST_FILE_PATH, BLACKLIST_FILENAME)
|
write_to_log_file(query, BLACKLIST_FILE_PATH, BLACKLIST_FILENAME)
|
||||||
|
|
|
||||||
94
zeus.py
94
zeus.py
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
import io
|
import io
|
||||||
|
import sys
|
||||||
import time
|
import time
|
||||||
import shlex
|
import shlex
|
||||||
import warnings
|
import warnings
|
||||||
|
|
@ -14,7 +15,8 @@ from lib.header_check import main_header_check
|
||||||
from lib.core.parse import ZeusParser
|
from lib.core.parse import ZeusParser
|
||||||
from lib.core.errors import (
|
from lib.core.errors import (
|
||||||
InvalidInputProvided,
|
InvalidInputProvided,
|
||||||
InvalidProxyType
|
InvalidProxyType,
|
||||||
|
ZeusArgumentException
|
||||||
)
|
)
|
||||||
from lib.core.common import (
|
from lib.core.common import (
|
||||||
start_up,
|
start_up,
|
||||||
|
|
@ -43,10 +45,19 @@ warnings.simplefilter("ignore")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
# this will take care of most of the Unicode errors.
|
||||||
|
reload(sys)
|
||||||
|
sys.setdefaultencoding("utf-8")
|
||||||
|
sys.setrecursionlimit(1500)
|
||||||
|
|
||||||
opt = ZeusParser.cmd_parser()
|
opt = ZeusParser.cmd_parser()
|
||||||
|
|
||||||
ZeusParser().single_show_args(opt)
|
ZeusParser().single_show_args(opt)
|
||||||
|
|
||||||
|
# verify all the arguments passed before we continue
|
||||||
|
# with the process
|
||||||
|
ZeusParser().verify_args()
|
||||||
|
|
||||||
# run the setup on the program
|
# run the setup on the program
|
||||||
setup(verbose=opt.runInVerbose)
|
setup(verbose=opt.runInVerbose)
|
||||||
|
|
||||||
|
|
@ -58,11 +69,11 @@ if __name__ == "__main__":
|
||||||
if opt.runInVerbose:
|
if opt.runInVerbose:
|
||||||
being_run = find_running_opts(opt)
|
being_run = find_running_opts(opt)
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
"running with options '{}'...".format(being_run), level=10
|
"running with options '{}'".format(being_run), level=10
|
||||||
))
|
))
|
||||||
|
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"log file being saved to '{}'...".format(get_latest_log_file(CURRENT_LOG_FILE_PATH))
|
"log file being saved to '{}'".format(get_latest_log_file(CURRENT_LOG_FILE_PATH))
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -83,14 +94,14 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
if urls_to_use is None:
|
if urls_to_use is None:
|
||||||
logger.error(set_color(
|
logger.error(set_color(
|
||||||
"unable to run attacks appears that no file was created for the retrieved data...", level=40
|
"unable to run attacks appears that no file was created for the retrieved data", level=40
|
||||||
))
|
))
|
||||||
shutdown()
|
shutdown()
|
||||||
options = [
|
options = [
|
||||||
opt.runSqliScan, opt.runPortScan,
|
opt.runSqliScan, opt.runPortScan,
|
||||||
opt.adminPanelFinder, opt.runXssScan,
|
opt.adminPanelFinder, opt.runXssScan,
|
||||||
opt.performWhoisLookup, opt.performClickjackingScan,
|
opt.performWhoisLookup, opt.performClickjackingScan,
|
||||||
opt.searchGithub, opt.pgpLookup
|
opt.pgpLookup
|
||||||
]
|
]
|
||||||
if any(options):
|
if any(options):
|
||||||
with open(urls_to_use) as urls:
|
with open(urls_to_use) as urls:
|
||||||
|
|
@ -98,24 +109,29 @@ if __name__ == "__main__":
|
||||||
current = i
|
current = i
|
||||||
if "webcache" in url:
|
if "webcache" in url:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"ran into unexpected webcache URL skipping...", level=30
|
"ran into unexpected webcache URL skipping", level=30
|
||||||
))
|
))
|
||||||
current -= 1
|
current -= 1
|
||||||
else:
|
else:
|
||||||
|
if not url.strip() == "http://" or url == "https://":
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"currently running on '{}' (target #{})...".format(
|
"currently running on '{}' (target #{})".format(
|
||||||
url.strip(), current
|
url.strip(), current
|
||||||
), level=25
|
), level=25
|
||||||
))
|
))
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"fetching target meta-data..."
|
"fetching target meta-data"
|
||||||
))
|
))
|
||||||
main_header_check(
|
identified = main_header_check(
|
||||||
url, verbose=opt.runInVerbose, agent=agent_to_use,
|
url, verbose=opt.runInVerbose, agent=agent_to_use,
|
||||||
proxy=proxy_to_use, xforward=opt.forwardedForRandomIP,
|
proxy=proxy_to_use, xforward=opt.forwardedForRandomIP,
|
||||||
identify_plugins=opt.identifyPlugin, identify_waf=opt.identifyProtection,
|
identify_plugins=opt.identifyPlugin, identify_waf=opt.identifyProtection,
|
||||||
show_description=opt.showPluginDescription
|
show_description=opt.showPluginDescription
|
||||||
)
|
)
|
||||||
|
if not identified:
|
||||||
|
logger.error(set_color(
|
||||||
|
"target is refusing to allow meta-data dumping, skipping", level=40
|
||||||
|
))
|
||||||
run_attacks(
|
run_attacks(
|
||||||
url.strip(),
|
url.strip(),
|
||||||
sqlmap=opt.runSqliScan, nmap=opt.runPortScan, pgp=opt.pgpLookup,
|
sqlmap=opt.runSqliScan, nmap=opt.runPortScan, pgp=opt.pgpLookup,
|
||||||
|
|
@ -127,9 +143,13 @@ if __name__ == "__main__":
|
||||||
show_all=opt.showAllConnections, do_threading=opt.threadPanels,
|
show_all=opt.showAllConnections, do_threading=opt.threadPanels,
|
||||||
tamper_script=opt.tamperXssPayloads, timeout=opt.controlTimeout,
|
tamper_script=opt.tamperXssPayloads, timeout=opt.controlTimeout,
|
||||||
proxy=proxy_to_use, agent=agent_to_use, conf_file=opt.sqlmapConfigFile,
|
proxy=proxy_to_use, agent=agent_to_use, conf_file=opt.sqlmapConfigFile,
|
||||||
threads=opt.amountOfThreads
|
threads=opt.amountOfThreads, force_ssl=opt.forceSSL
|
||||||
)
|
)
|
||||||
print("\n")
|
print("\n")
|
||||||
|
else:
|
||||||
|
logger.warning(set_color(
|
||||||
|
"malformed URL discovered, skipping", level=30
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
proxy_to_use, agent_to_use = config_headers(
|
proxy_to_use, agent_to_use = config_headers(
|
||||||
|
|
@ -146,7 +166,7 @@ if __name__ == "__main__":
|
||||||
# use a personal dork as the query
|
# use a personal dork as the query
|
||||||
if opt.dorkToUse is not None and not opt.searchMultiplePages:
|
if opt.dorkToUse is not None and not opt.searchMultiplePages:
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"starting dork scan with query '{}'...".format(opt.dorkToUse)
|
"starting dork scan with query '{}'".format(opt.dorkToUse)
|
||||||
))
|
))
|
||||||
try:
|
try:
|
||||||
selenium_search.parse_search_results(
|
selenium_search.parse_search_results(
|
||||||
|
|
@ -159,19 +179,19 @@ if __name__ == "__main__":
|
||||||
supported_proxy_types = ("socks5", "socks4", "https", "http")
|
supported_proxy_types = ("socks5", "socks4", "https", "http")
|
||||||
logger.fatal(set_color(
|
logger.fatal(set_color(
|
||||||
"the provided proxy is not valid, specify the protocol and try again, supported "
|
"the provided proxy is not valid, specify the protocol and try again, supported "
|
||||||
"proxy protocols are {} (IE socks5://127.0.0.1:9050)...".format(
|
"proxy protocols are {} (IE socks5://127.0.0.1:9050)".format(
|
||||||
", ".join(list(supported_proxy_types))), level=50
|
", ".join(list(supported_proxy_types))), level=50
|
||||||
))
|
))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if "Permission denied:" in str(e):
|
if "Permission denied:" in str(e):
|
||||||
logger.fatal(set_color(
|
logger.fatal(set_color(
|
||||||
"your permissions are not allowing Zeus to run, "
|
"your permissions are not allowing Zeus to run, "
|
||||||
"try running Zeus with sudo...", level=50
|
"try running Zeus with sudo", level=50
|
||||||
))
|
))
|
||||||
shutdown()
|
shutdown()
|
||||||
else:
|
else:
|
||||||
logger.exception(set_color(
|
logger.exception(set_color(
|
||||||
"ran into exception '{}'...".format(e), level=50
|
"ran into exception '{}'".format(e), level=50
|
||||||
))
|
))
|
||||||
request_issue_creation()
|
request_issue_creation()
|
||||||
pass
|
pass
|
||||||
|
|
@ -189,7 +209,7 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
if dork_to_use is None:
|
if dork_to_use is None:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"there has been no dork to specified to do the searching, defaulting to random dork...", level=30
|
"there has been no dork to specified to do the searching, defaulting to random dork", level=30
|
||||||
))
|
))
|
||||||
dork_to_use = get_random_dork()
|
dork_to_use = get_random_dork()
|
||||||
|
|
||||||
|
|
@ -197,14 +217,14 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
if opt.amountToSearch is None:
|
if opt.amountToSearch is None:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"did not specify amount of links to find defaulting to 75...", level=30
|
"did not specify amount of links to find defaulting to 75", level=30
|
||||||
))
|
))
|
||||||
link_amount_to_search = 75
|
link_amount_to_search = 75
|
||||||
else:
|
else:
|
||||||
link_amount_to_search = opt.amountToSearch
|
link_amount_to_search = opt.amountToSearch
|
||||||
|
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"searching Google using dork '{}' for a total of {} links...".format(
|
"searching Google using dork '{}' for a total of {} links".format(
|
||||||
dork_to_use, link_amount_to_search
|
dork_to_use, link_amount_to_search
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
@ -218,11 +238,11 @@ if __name__ == "__main__":
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if "Error 400" in str(e):
|
if "Error 400" in str(e):
|
||||||
logger.fatal(set_color(
|
logger.fatal(set_color(
|
||||||
"failed to connect to search engine...".format(e), level=50
|
"failed to connect to search engine".format(e), level=50
|
||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
logger.exception(set_color(
|
logger.exception(set_color(
|
||||||
"failed with unexpected error '{}'...".format(e), level=50
|
"failed with unexpected error '{}'".format(e), level=50
|
||||||
))
|
))
|
||||||
shutdown()
|
shutdown()
|
||||||
|
|
||||||
|
|
@ -234,7 +254,7 @@ if __name__ == "__main__":
|
||||||
for dork in dorks.readlines():
|
for dork in dorks.readlines():
|
||||||
dork = dork.strip()
|
dork = dork.strip()
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"starting dork scan with query '{}'...".format(dork)
|
"starting dork scan with query '{}'".format(dork)
|
||||||
))
|
))
|
||||||
try:
|
try:
|
||||||
selenium_search.parse_search_results(
|
selenium_search.parse_search_results(
|
||||||
|
|
@ -244,7 +264,7 @@ if __name__ == "__main__":
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(set_color(
|
logger.exception(set_color(
|
||||||
"ran into exception '{}'...".format(e), level=50
|
"ran into exception '{}'".format(e), level=50
|
||||||
))
|
))
|
||||||
request_issue_creation()
|
request_issue_creation()
|
||||||
pass
|
pass
|
||||||
|
|
@ -256,10 +276,10 @@ if __name__ == "__main__":
|
||||||
random_dork = get_random_dork().strip()
|
random_dork = get_random_dork().strip()
|
||||||
if opt.runInVerbose:
|
if opt.runInVerbose:
|
||||||
logger.debug(set_color(
|
logger.debug(set_color(
|
||||||
"choosing random dork from etc/dorks.txt...", level=10
|
"choosing random dork from etc/dorks.txt", level=10
|
||||||
))
|
))
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"using random dork '{}' as the search query...".format(random_dork)
|
"using random dork '{}' as the search query".format(random_dork)
|
||||||
))
|
))
|
||||||
try:
|
try:
|
||||||
selenium_search.parse_search_results(
|
selenium_search.parse_search_results(
|
||||||
|
|
@ -271,7 +291,7 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(set_color(
|
logger.exception(set_color(
|
||||||
"ran into exception '{}' and cannot continue, saved to current log file...".format(e),
|
"ran into exception '{}' and cannot continue, saved to current log file".format(e),
|
||||||
level=50
|
level=50
|
||||||
))
|
))
|
||||||
request_issue_creation()
|
request_issue_creation()
|
||||||
|
|
@ -281,7 +301,7 @@ if __name__ == "__main__":
|
||||||
elif opt.spiderWebSite:
|
elif opt.spiderWebSite:
|
||||||
problem_identifiers = ["http://", "https://"]
|
problem_identifiers = ["http://", "https://"]
|
||||||
if not URL_REGEX.match(opt.spiderWebSite):
|
if not URL_REGEX.match(opt.spiderWebSite):
|
||||||
err_msg = "URL did not match a true URL{}..."
|
err_msg = "URL did not match a true URL{}"
|
||||||
if not any(m in opt.spiderWebSite for m in problem_identifiers):
|
if not any(m in opt.spiderWebSite for m in problem_identifiers):
|
||||||
err_msg = err_msg.format(" issue seems to be that http:// "
|
err_msg = err_msg.format(" issue seems to be that http:// "
|
||||||
"or https:// is not present in the URL")
|
"or https:// is not present in the URL")
|
||||||
|
|
@ -317,7 +337,7 @@ if __name__ == "__main__":
|
||||||
# enumerate a file and run attacks on the URL's provided
|
# enumerate a file and run attacks on the URL's provided
|
||||||
elif opt.fileToEnumerate is not None:
|
elif opt.fileToEnumerate is not None:
|
||||||
logger.info(set_color(
|
logger.info(set_color(
|
||||||
"found a total of {} URL's to enumerate in given file...".format(
|
"found a total of {} URL's to enumerate in given file".format(
|
||||||
len(open(opt.fileToEnumerate).readlines())
|
len(open(opt.fileToEnumerate).readlines())
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
@ -325,7 +345,7 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.critical(set_color(
|
logger.critical(set_color(
|
||||||
"failed to provide a mandatory argument, you will be redirected to the help menu...", level=50
|
"failed to provide a mandatory argument, you will be redirected to the help menu", level=50
|
||||||
))
|
))
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
zeus_help_menu_command = shlex.split("python zeus.py --help")
|
zeus_help_menu_command = shlex.split("python zeus.py --help")
|
||||||
|
|
@ -333,7 +353,7 @@ if __name__ == "__main__":
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
if "Invalid URL" in str(e):
|
if "Invalid URL" in str(e):
|
||||||
logger.exception(set_color(
|
logger.exception(set_color(
|
||||||
"URL provided is not valid, schema appears to be missing...", level=50
|
"URL provided is not valid, schema appears to be missing", level=50
|
||||||
))
|
))
|
||||||
request_issue_creation()
|
request_issue_creation()
|
||||||
shutdown()
|
shutdown()
|
||||||
|
|
@ -344,38 +364,40 @@ if __name__ == "__main__":
|
||||||
))
|
))
|
||||||
shutdown()
|
shutdown()
|
||||||
elif "No such file or directory" in str(e):
|
elif "No such file or directory" in str(e):
|
||||||
logger.exception(e)
|
|
||||||
logger.fatal(set_color(
|
logger.fatal(set_color(
|
||||||
"provided file does not exist, make sure you have the full path...", level=50
|
"provided file does not exist, make sure you have the full path", level=50
|
||||||
))
|
))
|
||||||
|
shutdown()
|
||||||
else:
|
else:
|
||||||
logger.exception(set_color(
|
logger.exception(set_color(
|
||||||
"Zeus has hit an unexpected error and cannot continue, error code '{}'...".format(e), level=50
|
"Zeus has hit an unexpected error and cannot continue, error code '{}'".format(e), level=50
|
||||||
))
|
))
|
||||||
request_issue_creation()
|
request_issue_creation()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
logger.fatal(set_color(
|
logger.fatal(set_color(
|
||||||
"user aborted process...", level=50
|
"user aborted process", level=50
|
||||||
))
|
))
|
||||||
shutdown()
|
shutdown()
|
||||||
except UnboundLocalError:
|
except UnboundLocalError:
|
||||||
logger.warning(set_color(
|
logger.warning(set_color(
|
||||||
"do not interrupt the browser when selenium is running, "
|
"do not interrupt the browser when selenium is running, "
|
||||||
"it will cause Zeus to crash...", level=30
|
"it will cause Zeus to crash", level=30
|
||||||
))
|
))
|
||||||
|
except ZeusArgumentException:
|
||||||
|
shutdown()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if "url did not match a true url" in str(e).lower():
|
if "url did not match a true url" in str(e).lower():
|
||||||
logger.error(set_color(
|
logger.error(set_color(
|
||||||
"you did not provide a URL that is capable of being processed, "
|
"you did not provide a URL that is capable of being processed, "
|
||||||
"the URL provided to the spider needs to contain protocol as well "
|
"the URL provided to the spider needs to contain protocol as well "
|
||||||
"ie. 'http://google.com' (it is advised not to add the GET parameter), "
|
"ie. 'http://google.com' (it is advised not to add the GET parameter), "
|
||||||
"fix the URL you want to scan and try again...", level=40
|
"fix the URL you want to scan and try again", level=40
|
||||||
))
|
))
|
||||||
shutdown()
|
shutdown()
|
||||||
elif "Service geckodriver unexpectedly exited" in str(e):
|
elif "Service geckodriver unexpectedly exited" in str(e):
|
||||||
logger.fatal(set_color(
|
logger.fatal(set_color(
|
||||||
"it seems your firefox version is not compatible with the geckodriver version, "
|
"it seems your firefox version is not compatible with the geckodriver version, "
|
||||||
"please re-install Zeus and try again...", level=50
|
"please re-install Zeus and try again", level=50
|
||||||
))
|
))
|
||||||
shutdown()
|
shutdown()
|
||||||
elif "Max retries exceeded with url" in str(e):
|
elif "Max retries exceeded with url" in str(e):
|
||||||
|
|
@ -387,7 +409,7 @@ if __name__ == "__main__":
|
||||||
shutdown()
|
shutdown()
|
||||||
else:
|
else:
|
||||||
logger.exception(set_color(
|
logger.exception(set_color(
|
||||||
"ran into exception '{}' exception has been saved to log file...".format(e), level=50
|
"ran into exception '{}' exception has been saved to log file".format(e), level=50
|
||||||
))
|
))
|
||||||
request_issue_creation()
|
request_issue_creation()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue